RepoPilotOpen in app →

kishikawakatsumi/KeychainAccess

Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 16 active contributors
  • MIT licensed
  • CI configured
Show 3 more →
  • Tests present
  • Stale — last commit 2y ago
  • Single-maintainer risk — top contributor 81% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/kishikawakatsumi/keychainaccess)](https://repopilot.app/r/kishikawakatsumi/keychainaccess)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/kishikawakatsumi/keychainaccess on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: kishikawakatsumi/KeychainAccess

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/kishikawakatsumi/KeychainAccess shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 16 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y ago
  • ⚠ Single-maintainer risk — top contributor 81% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live kishikawakatsumi/KeychainAccess repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/kishikawakatsumi/KeychainAccess.

What it runs against: a local clone of kishikawakatsumi/KeychainAccess — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in kishikawakatsumi/KeychainAccess | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 739 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>kishikawakatsumi/KeychainAccess</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of kishikawakatsumi/KeychainAccess. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/kishikawakatsumi/KeychainAccess.git
#   cd KeychainAccess
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of kishikawakatsumi/KeychainAccess and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "kishikawakatsumi/KeychainAccess(\\.git)?\\b" \\
  && ok "origin remote is kishikawakatsumi/KeychainAccess" \\
  || miss "origin remote is not kishikawakatsumi/KeychainAccess (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "Sources/Keychain.swift" \\
  && ok "Sources/Keychain.swift" \\
  || miss "missing critical file: Sources/Keychain.swift"
test -f "Lib/KeychainAccess/Keychain.swift" \\
  && ok "Lib/KeychainAccess/Keychain.swift" \\
  || miss "missing critical file: Lib/KeychainAccess/Keychain.swift"
test -f "Package.swift" \\
  && ok "Package.swift" \\
  || miss "missing critical file: Package.swift"
test -f "Lib/KeychainAccess.xcodeproj/project.pbxproj" \\
  && ok "Lib/KeychainAccess.xcodeproj/project.pbxproj" \\
  || miss "missing critical file: Lib/KeychainAccess.xcodeproj/project.pbxproj"
test -f "Lib/KeychainAccessTests/KeychainAccessTests.swift" \\
  && ok "Lib/KeychainAccessTests/KeychainAccessTests.swift" \\
  || miss "missing critical file: Lib/KeychainAccessTests/KeychainAccessTests.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 739 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~709d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/kishikawakatsumi/KeychainAccess"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

KeychainAccess is a lightweight Swift wrapper around Apple's Keychain Services that abstracts away the verbose Security framework APIs. It enables iOS, macOS, watchOS, and tvOS apps to securely store credentials, API tokens, and passwords with a simple subscript-based interface (e.g., keychain["username"] = "token"), supporting both application passwords and internet passwords with features like TouchID integration, iCloud syncing, and shared web credentials. Lib/KeychainAccess/ contains the core Keychain.swift implementation; Lib/KeychainAccessTests/ holds unit tests for core functionality, enums, errors, and shared credentials; Examples/Example-iOS/ provides a complete runnable iOS app demonstrating password storage, retrieval, and account management; build configuration is centralized in Lib/Configurations/ with platform-specific settings.

👥Who it's for

Swift app developers building iOS/macOS/watchOS/tvOS applications who need to store sensitive data like authentication tokens, passwords, or API keys without wrestling with the low-level Security framework or managing Keychain's obtuse query dictionaries directly.

🌱Maturity & risk

Production-ready and actively maintained. The repo shows a mature codebase with comprehensive test suites (Lib/KeychainAccessTests/), CI setup via .github/workflows/test.yml, multiplatform support (iOS, macOS, watchOS, tvOS, Mac Catalyst), and SPM/Carthage/CocoaPods distribution. No recent commit date visible in provided data, but the structured test coverage and example apps indicate stability.

Low-to-minimal risk: the library is a thin wrapper over Apple's native APIs (no heavy dependencies visible), has strong test coverage with dedicated test suites for enums and error types, and maintains backward compatibility across Swift 3–5. Single-maintainer risk exists (kishikawakatsumi), but the focused scope (Keychain only) and stable API surface minimize breaking-change exposure.

Active areas of work

No active PR or milestone data is visible in the provided file structure. The repo appears in a mature, stable state with periodic maintenance rather than active feature development.

🚀Get running

git clone https://github.com/kishikawakatsumi/KeychainAccess.git
cd KeychainAccess
open KeychainAccess.xcworkspace
# Or for Swift Package Manager:
swift package resolve

Daily commands: Open KeychainAccess.xcworkspace in Xcode and build the KeychainAccess scheme, or run tests via TestHost scheme. For the iOS example: open Examples/Example-iOS/Example-iOS.xcodeproj and run on simulator/device. Swift Package Manager: swift build and swift test.

🗺️Map of the codebase

  • Sources/Keychain.swift — Core wrapper implementation providing the public API for all keychain operations across iOS, watchOS, tvOS, and macOS.
  • Lib/KeychainAccess/Keychain.swift — Mirror implementation of the main Keychain wrapper used in the Xcode project build; primary entry point for library consumers.
  • Package.swift — Swift Package Manager manifest defining library targets, supported platforms, and deployment configurations.
  • Lib/KeychainAccess.xcodeproj/project.pbxproj — Xcode project configuration defining build settings, targets, and framework dependencies for the library.
  • Lib/KeychainAccessTests/KeychainAccessTests.swift — Primary test suite validating core keychain operations, error handling, and cross-platform compatibility.
  • KeychainAccess.podspec — CocoaPods specification defining versioning, platform support, and distribution metadata for the library.

🧩Components & responsibilities

  • Keychain class (main API) (Swift, Security.framework (SecItemAdd, SecItemCopyMatching, SecItemDelete, SecItemUpdate)) — Provides subscript-based type-safe access to secure storage; manages query dictionaries, error handling, and result parsing
    • Failure mode: Returns nil on missing keys; throws KeychainAccessError on system errors (permissions, corrupted keychain, device locked)
  • KeychainAccessError enum (Swift error protocol, Security.framework error codes) — Maps OSStatus error codes to human-readable error variants with recovery suggestions
    • Failure mode: Unknown errors

🛠️How to make changes

Add a new Keychain accessor method

  1. Open Sources/Keychain.swift and locate the main Keychain class definition (Sources/Keychain.swift)
  2. Add a new computed property or method following the pattern: subscript(key: String) -> T? { get set } for type-safe access (Sources/Keychain.swift)
  3. Use SecItemCopyMatching or SecItemAdd for retrieval, wrapping in error handling with KeychainAccessError (Sources/Keychain.swift)
  4. Add corresponding test case in KeychainAccessTests.swift to validate read/write/delete flows (Lib/KeychainAccessTests/KeychainAccessTests.swift)

Support a new Apple platform

  1. Update Package.swift to add the new platform in the platforms array (e.g., .macOS(.v10_15)) (Package.swift)
  2. Add #if os(NewPlatform) / #endif conditional compilation blocks in Keychain.swift if platform-specific APIs are needed (Sources/Keychain.swift)
  3. Create a corresponding test host project under Lib/ with entitlements matching the new platform's keychain requirements (Lib/TestHost/TestHost.entitlements)
  4. Update .github/workflows/test.yml to run tests on the new platform in CI/CD (.github/workflows/test.yml)

Add a new example app

  1. Create a new folder under Examples/ with platform name (e.g., Examples/Example-macOS) (Examples/Example-iOS/Example-iOS.xcodeproj/project.pbxproj)
  2. Create AppDelegate.swift and main UI ViewControllers, importing KeychainAccess framework (Examples/Example-iOS/Example-iOS/AppDelegate.swift)
  3. Add example usage patterns (read, write, delete) mirroring Examples/Example-iOS/Example-iOS/AccountsViewController.swift (Examples/Example-iOS/Example-iOS/AccountsViewController.swift)
  4. Include .entitlements file with keychain-access-groups if using shared credentials (AutoFill) (Examples/Example-iOS/Example-iOS/Example-iOS.entitlements)

🔧Why these technologies

  • Swift — Modern, type-safe language matching Apple's native ecosystem; enables compile-time safety over raw C Keychain APIs
  • Security.framework — OS-provided keychain abstraction with hardware-backed encryption on supported devices; only secure choice for credential storage
  • Swift Package Manager + CocoaPods + Carthage — Multiple distribution channels maximize adoption across different dependency managers and legacy projects
  • XCTest — Native Apple testing framework integrated with Xcode; enables test execution across all supported platforms

⚖️Trade-offs already made

  • Thin wrapper around Security.framework rather than custom encryption

    • Why: Leverages OS-level security, Hardware Security Module (HSM) on newer devices, and automatic iCloud Keychain sync
    • Consequence: Limited to iOS/macOS/watchOS/tvOS; no cross-platform desktop support, but gains maximum security guarantees
  • Generic subscript<T>() syntax with type inference over explicit typed methods

    • Why: Reduces API surface area and improves ergonomics for common cases (strings, data)
    • Consequence: Requires developers to explicitly specify types (keychain["key"] as String?); may be less discoverable than explicit methods
  • Support both SPM and CocoaPods/Carthage from single source

    • Why: Maximizes compatibility with diverse legacy and modern projects
    • Consequence: Dual source trees (Sources/ and Lib/KeychainAccess/) increase maintenance burden for consistency
  • No async/await variants despite Security.framework supporting async queries

    • Why: Keychain operations are I/O-bound but typically fast enough on main thread; keeps API simple
    • Consequence: Long-running operations block the main thread; not suitable for very high-volume batch operations

🚫Non-goals (don't propose these)

  • Real-time synchronization of credentials across multiple devices (relies on iCloud Keychain when available)
  • Cross-platform support beyond Apple platforms (Windows, Linux, Android)
  • Replacing enterprise key management or HSM systems
  • Supporting custom encryption algorithms or key derivation functions
  • High-throughput credential streaming or batch operations

🪤Traps & gotchas

Entitlements required: iOS/macOS apps using this library must include com.apple.security.application-groups and com.apple.developer.associated-domains in their entitlements for access groups and shared credentials to function. Simulator limitations: Keychain on iOS Simulator stores data plaintext and does not persist across simulator resets; test on real device for production code. Mac Catalyst quirks: Keychain behavior differs slightly from native macOS (documented in Security framework docs). No error recovery: the wrapper doesn't retry failed queries; calling code must handle transient Keychain unavailability (rare but can happen during device lock transitions).

🏗️Architecture

💡Concepts to learn

  • Keychain Services / Security Framework — KeychainAccess is fundamentally a wrapper around Apple's Security framework; understanding how SecItem queries, attribute dictionaries, and access control lists work is essential to debug or extend the library.
  • Subscript Operator Overloading (Swift) — The library's core appeal is its natural keychain["key"] = value syntax, achieved through Swift's subscript protocol; understanding this pattern is key to extending the API.
  • Conditional Compilation (Platform-specific Code) — KeychainAccess supports iOS, macOS, watchOS, tvOS, and Mac Catalyst using #if os(...) preprocessor directives; grasping this is necessary for any platform-specific bug fixes.
  • Keychain Access Groups — The library exposes accessGroup parameter for sharing credentials across multiple apps; this requires understanding App Groups entitlements and Keychain query scoping.
  • TouchID / Biometric Authentication Integration — KeychainAccess supports TouchID and Keychain integration (iOS 8+) via SecAccessControl; this pattern is for users storing high-value secrets requiring biometric unlock.
  • Shared Web Credentials (iCloud Keychain) — The library exposes iCloud Keychain syncing and shared web credentials; this is essential for cross-device auth flows and automatic password fill.
  • Error Type Abstraction — KeychainAccess wraps low-level OSStatus error codes in a Swift Error enum (see ErrorTypeTests.swift); understanding error mapping patterns helps diagnose why Keychain calls fail.
  • SwiftyKeychainKit/SwiftyKeychainKit — Direct competitor providing similar Keychain abstraction with slightly different API design; useful for comparing wrapper philosophies.
  • apple/swift-package-manager — Defines the SPM specification used by KeychainAccess; necessary for understanding package metadata and dependency resolution.
  • auth0/Auth0.swift — Real-world consumer of Keychain wrappers for OAuth token storage; reference for how KeychainAccess fits into larger auth flows.
  • firebase/firebase-ios-sdk — Competitor ecosystem showing how enterprise frameworks implement secure credential storage on iOS/macOS.
  • apple/swift-corelibs-foundation — Upstream Swift Foundation implementation; relevant for understanding platform-specific compilation conditionals used in KeychainAccess.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive watchOS and tvOS integration tests

The README claims KeychainAccess works on iOS, watchOS, tvOS and macOS, but the test suite in Lib/KeychainAccessTests only contains generic tests. There are no platform-specific test schemes or configurations for watchOS and tvOS. Adding dedicated test targets would ensure the library functions correctly across all advertised platforms.

  • [ ] Create Lib/KeychainAccessTests-watchOS directory with watchOS-specific test target
  • [ ] Create Lib/KeychainAccessTests-tvOS directory with tvOS-specific test target
  • [ ] Add watchOS and tvOS test schemes to Lib/KeychainAccess.xcodeproj/xcshareddata/xcschemes/
  • [ ] Update .github/workflows/test.yml to run tests on watchOS and tvOS simulators
  • [ ] Verify SharedCredentialTests.swift behavior on watchOS (which has limitations on shared credentials)

Add Swift Package Manager (SPM) integration tests in CI

The repo supports SPM (badge in README and .swiftpm directory exists) but there's no CI workflow testing the package via SPM. Currently only Xcode project tests run. Add GitHub Actions workflow to verify the package integrates correctly via Swift Package Manager across platforms.

  • [ ] Create .github/workflows/spm-test.yml to test package resolution and compilation
  • [ ] Include matrix strategy for iOS, macOS, tvOS, and watchOS in SPM tests
  • [ ] Test building example projects with SPM integration (Examples/Example-iOS or create new SPM example)
  • [ ] Verify Package.swift manifest is correct and complete for all platforms

Add CocoaPods validation to CI pipeline

The repo has KeychainAccess.podspec and displays CocoaPods badges, but there's no CI validation that the podspec is valid or that installation via CocoaPods works. The .github/workflows/test.yml only tests Xcode projects. This leaves the pod distribution untested.

  • [ ] Create .github/workflows/cocoapods-test.yml with pod repo update and pod lib lint
  • [ ] Add pod spec validation for all supported platforms (iOS, macOS, tvOS, watchOS) in the workflow
  • [ ] Optionally test pod installation in a test project to ensure transitive dependencies work
  • [ ] Document CocoaPods installation steps in README if not already present

🌿Good first issues

  • Add comprehensive docstring coverage to all public methods in Lib/KeychainAccess/Keychain.swift; currently many query-building methods lack examples or parameter documentation.
  • Write platform-specific test cases for watchOS and tvOS in Lib/KeychainAccessTests/ (only iOS/macOS examples visible in test file structure).
  • Create a migration guide documenting how to switch from raw Security framework code to KeychainAccess (identify common pain points in the iOS example's AccountsViewController.swift and extract best practices).

Top contributors

Click to expand

📝Recent commits

Click to expand
  • e0c7eeb — Remove ruby related files. (kishikawakatsumi)
  • 6df250d — Merge pull request #586 from kishikawakatsumi/remove-screenshots (kishikawakatsumi)
  • ac72b0b — Remove screenshots (kishikawakatsumi)
  • 2b4b209 — Merge pull request #585 from kishikawakatsumi/travis (kishikawakatsumi)
  • 28055c5 — Merge pull request #584 from kishikawakatsumi/osxmacos (kishikawakatsumi)
  • 5cac110 — Merge branch 'master' into osxmacos (kishikawakatsumi)
  • 6511d2a — Merge pull request #582 from kishikawakatsumi/github-actions (kishikawakatsumi)
  • 77207cc — Merge pull request #566 from ilendemli/accessGroup (kishikawakatsumi)
  • 89d13bb — Merge branch 'master' into accessGroup (kishikawakatsumi)
  • 80baa60 — Add GitHub Actions (kishikawakatsumi)

🔒Security observations

The KeychainAccess library demonstrates a strong security posture as a specialized wrapper for iOS/macOS Keychain operations. No critical or high-severity vulnerabilities were identified in the provided file structure. The codebase appropriately focuses on wrapping secure system APIs rather than implementing custom cryptographic operations. Primary recommendations include: (1) establishing a formal security reporting process via SECURITY.md, (2) ensuring dependency vulnerability scanning is in place, (3) auditing example code for hardcoded credentials, and (4) documenting required entitlements for developers. The library's design pattern of wrapping native Keychain APIs is a security-positive approach, avoiding common pitfalls of custom encryption implementations.

  • Medium · Missing dependency vulnerability scanning — Package.swift, Package@swift-5.3.swift, KeychainAccess.podspec. No dependency lock file (Package.resolved, Podfile.lock, or Carthage.lock) was provided in the analysis. This makes it impossible to verify if the project uses vulnerable versions of its dependencies. Fix: Ensure Package.resolved is committed to version control for SPM projects, Podfile.lock for CocoaPods, and Carthage.lock for Carthage. Regularly run dependency vulnerability scanners like swift package audit or similar tools.
  • Low · No explicit security policy documentation — Repository root. The repository does not appear to have a SECURITY.md file or documented security policy for reporting vulnerabilities. This is a best practice for open-source projects handling sensitive operations like Keychain access. Fix: Create a SECURITY.md file following the GitHub security advisory guidelines. Include instructions for responsible disclosure of security vulnerabilities.
  • Low · Test credentials potentially in example code — Examples/Example-iOS/Example-iOS/AccountsViewController.swift, Examples/Example-iOS/Example-iOS/InputViewController.swift. Example applications (Examples/Example-iOS) may contain hardcoded test accounts or credentials for demonstration purposes. While intentional for examples, this could be a security concern if real credentials are used. Fix: Audit example code to ensure no real credentials are included. Use clearly marked placeholder credentials and document the need to replace them with test values.
  • Low · Missing code signing requirements specification — Examples and test host entitlements files. Entitlements files are present (Example-iOS.entitlements, TestHost-MacCatalyst.entitlements, TestHost.entitlements) but there's no visible documentation of required capabilities or security entitlements needed when using this library. Fix: Document required entitlements and capabilities in README.md. Clearly specify if Keychain access group entitlements are needed for app extensions or shared functionality.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · kishikawakatsumi/KeychainAccess — RepoPilot