kishikawakatsumi/KeychainAccess
Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓16 active contributors
- ✓MIT licensed
- ✓CI configured
Show 3 more →Show less
- ✓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.
[](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:
- 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. - 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.
- 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 |
#!/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).
⚡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
- Open Sources/Keychain.swift and locate the main Keychain class definition (
Sources/Keychain.swift) - Add a new computed property or method following the pattern: subscript(key: String) -> T? { get set } for type-safe access (
Sources/Keychain.swift) - Use SecItemCopyMatching or SecItemAdd for retrieval, wrapping in error handling with KeychainAccessError (
Sources/Keychain.swift) - Add corresponding test case in KeychainAccessTests.swift to validate read/write/delete flows (
Lib/KeychainAccessTests/KeychainAccessTests.swift)
Support a new Apple platform
- Update Package.swift to add the new platform in the platforms array (e.g., .macOS(.v10_15)) (
Package.swift) - Add #if os(NewPlatform) / #endif conditional compilation blocks in Keychain.swift if platform-specific APIs are needed (
Sources/Keychain.swift) - Create a corresponding test host project under Lib/ with entitlements matching the new platform's keychain requirements (
Lib/TestHost/TestHost.entitlements) - Update .github/workflows/test.yml to run tests on the new platform in CI/CD (
.github/workflows/test.yml)
Add a new example app
- Create a new folder under Examples/ with platform name (e.g., Examples/Example-macOS) (
Examples/Example-iOS/Example-iOS.xcodeproj/project.pbxproj) - Create AppDelegate.swift and main UI ViewControllers, importing KeychainAccess framework (
Examples/Example-iOS/Example-iOS/AppDelegate.swift) - Add example usage patterns (read, write, delete) mirroring Examples/Example-iOS/Example-iOS/AccountsViewController.swift (
Examples/Example-iOS/Example-iOS/AccountsViewController.swift) - 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"] = valuesyntax, achieved through Swift'ssubscriptprotocol; 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
accessGroupparameter 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
OSStatuserror codes in a SwiftErrorenum (seeErrorTypeTests.swift); understanding error mapping patterns helps diagnose why Keychain calls fail.
🔗Related repos
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.swiftand extract best practices).
⭐Top contributors
Click to expand
Top contributors
- @kishikawakatsumi — 81 commits
- @lpuentes19 — 4 commits
- @Marcocanc — 2 commits
- @ilendemli — 1 commits
- @zunda-pixel — 1 commits
📝Recent commits
Click to expand
Recent commits
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 likeswift package auditor 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.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.