sparrowcode/PermissionsKit
Universal API for request permission and get its statuses.
Stale — last commit 1y ago
worst of 4 axeslast commit was 1y ago; no tests detected…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 1y ago; no CI workflows detected
- ✓21+ active contributors
- ✓MIT licensed
- ⚠Stale — last commit 1y ago
Show 3 more →Show less
- ⚠Concentrated ownership — top contributor handles 71% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: 1 commit in the last 365 days; add a test suite
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
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 "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/sparrowcode/permissionskit)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/sparrowcode/permissionskit on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: sparrowcode/PermissionsKit
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/sparrowcode/PermissionsKit 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
WAIT — Stale — last commit 1y ago
- 21+ active contributors
- MIT licensed
- ⚠ Stale — last commit 1y ago
- ⚠ Concentrated ownership — top contributor handles 71% of recent commits
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<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 sparrowcode/PermissionsKit
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/sparrowcode/PermissionsKit.
What it runs against: a local clone of sparrowcode/PermissionsKit — 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 sparrowcode/PermissionsKit | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 438 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sparrowcode/PermissionsKit. If you don't
# have one yet, run these first:
#
# git clone https://github.com/sparrowcode/PermissionsKit.git
# cd PermissionsKit
#
# 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 sparrowcode/PermissionsKit and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sparrowcode/PermissionsKit(\\.git)?\\b" \\
&& ok "origin remote is sparrowcode/PermissionsKit" \\
|| miss "origin remote is not sparrowcode/PermissionsKit (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 main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Sources/PermissionsKit/Permission.swift" \\
&& ok "Sources/PermissionsKit/Permission.swift" \\
|| miss "missing critical file: Sources/PermissionsKit/Permission.swift"
test -f "Sources/CameraPermission/CameraPermission.swift" \\
&& ok "Sources/CameraPermission/CameraPermission.swift" \\
|| miss "missing critical file: Sources/CameraPermission/CameraPermission.swift"
test -f "Sources/LocationPermission/LocationPermission.swift" \\
&& ok "Sources/LocationPermission/LocationPermission.swift" \\
|| miss "missing critical file: Sources/LocationPermission/LocationPermission.swift"
test -f "Sources/NotificationPermission/NotificationPermission.swift" \\
&& ok "Sources/NotificationPermission/NotificationPermission.swift" \\
|| miss "missing critical file: Sources/NotificationPermission/NotificationPermission.swift"
test -f "Sources/PermissionsKit/Data/Text.swift" \\
&& ok "Sources/PermissionsKit/Data/Text.swift" \\
|| miss "missing critical file: Sources/PermissionsKit/Data/Text.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 438 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~408d)"
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/sparrowcode/PermissionsKit"
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
PermissionsKit is a unified Swift framework that abstracts iOS system permission requests (Camera, Location, Bluetooth, Health, Notifications, etc.) behind a single API. Rather than writing boilerplate code for each permission type's framework (AVFoundation, CoreLocation, HealthKit), developers call a single request() method and check status with .authorized, .denied, or .notDetermined states across 16+ permission types. Modular architecture: core abstraction in Sources/PermissionsKit/ (Permission.swift as the base protocol, Data/Text.swift for strings), with one folder per permission type (BluetoothPermission/, CameraPermission/, LocationPermission/, etc.). LocationPermission is most complex, splitting logic into Handlers/ (LocationAlwaysHandler.swift, LocationWhenInUseHandler.swift) to handle iOS 11+ authorization levels. Localizations centralized in Sources/PermissionsKit/Resources/Localization/ with language-specific .strings files.
👥Who it's for
iOS app developers building features that need user permissions (camera, location tracking, health data access, notifications). They want to avoid learning each framework's idiosyncrasies and prefer a lightweight abstraction layer that handles permission dialogs consistently across their codebase.
🌱Maturity & risk
Production-ready and actively maintained. The codebase spans 74K+ lines of Swift across modular permission handlers, supports multiple languages (en, de, es, fr, ar, fa localizations in Sources/PermissionsKit/Resources/Localization/), and is packaged via both SPM (Package.swift) and CocoaPods (PermissionsKit.podspec). No visible test suite in the file list suggests some risk; commit recency unknown from provided data.
Moderate risk: the repository shows no automated test files in the provided structure, making regressions harder to catch as new iOS versions ship. Single-maintainer risk (sparrowcode organization) means dependency on one person for bug fixes and iOS API compatibility updates. Permission frameworks are tightly coupled to iOS SDK versions, requiring active maintenance when Apple changes permission request flows.
Active areas of work
No specific commit history visible in provided data. The file structure suggests active support for modern iOS (FaceIDPermission, HealthPermission present), but without recent PR or issue data, ongoing development status is unclear.
🚀Get running
Clone via git clone https://github.com/sparrowcode/PermissionsKit.git && cd PermissionsKit. Install dependencies with swift build (SPM) or pod install if using CocoaPods. The repo is a library, not a runnable app—see the README for integration examples into your own iOS project.
Daily commands:
This is a library, not a runnable application. To integrate: add SPM dependency: .package(url: "https://github.com/sparrowcode/PermissionsKit.git", from: "3.0.0") to Package.swift, or pod 'PermissionsKit' to Podfile. Then import specific permission modules (e.g., import CameraPermission) in your app code.
🗺️Map of the codebase
Sources/PermissionsKit/Permission.swift— Core protocol defining the universal permission API that all specific permissions must implement—this is the architectural anchor.Sources/CameraPermission/CameraPermission.swift— Reference implementation of Permission protocol showing the canonical pattern for wrapping iOS permission frameworks.Sources/LocationPermission/LocationPermission.swift— Complex permission handler with dual modes (always/whenInUse) demonstrating how to manage permission variants and state.Sources/NotificationPermission/NotificationPermission.swift— Shows how to bridge multiple frameworks (UserNotifications, PushKit) and handle authorization options conversion.Sources/PermissionsKit/Data/Text.swift— Localization and messaging layer that powers permission request UI strings across 12+ languages.Package.swift— Defines SPM targets and platform support—essential for understanding multi-target architecture.PermissionsKit.podspec— CocoaPods configuration specifying public headers and resource bundles for localization distribution.
🧩Components & responsibilities
- Permission (protocol) (Swift Protocol, associated types) — Defines contract: async request method + sync status property. Enforces consistent API shape.
- Failure mode: If status property blocks (should never), UI freezes. If request completion never fires, app hangs.
- Concrete Permission (e.g., CameraPermission) (AVFoundation, CoreLocation, HealthKit, etc.) — Wraps single iOS framework (AVFoundation). Translates framework auth status → PermissionStatus enum.
- Failure mode: If framework import fails, module compilation fails. If request() crashes, app crashes on permission call.
- Handler classes (e.g., LocationAlwaysHandler) (CoreLocation, delegation patterns) — Extract complex permission logic (multi-mode, conditional requests) into reusable helpers.
- Failure mode: If handler retains permission object, circular reference leaks memory.
- Text/Localization layer — Central source for user-facing strings; maps
🛠️How to make changes
Add a new permission type
- Create new directory Sources/NewPermission/ (
Sources/NewPermission/NewPermission.swift) - Implement struct conforming to Permission protocol with status and request(completion:) methods (
Sources/NewPermission/NewPermission.swift) - Import required framework (e.g., CoreLocation, AVFoundation) and call native permission APIs (
Sources/NewPermission/NewPermission.swift) - Add localization strings for this permission to all .lproj/Localizable.strings files (
Sources/PermissionsKit/Resources/Localization/en.lproj/Localizable.strings) - Update Package.swift to include new target as .target(name: 'NewPermission', ...) (
Package.swift) - Update PermissionsKit.podspec to register new subspec if using CocoaPods (
PermissionsKit.podspec)
Add support for new language/locale
- Create new locale directory Sources/PermissionsKit/Resources/Localization/[locale].lproj/ (
Sources/PermissionsKit/Resources/Localization/[locale].lproj/Localizable.strings) - Copy English Localizable.strings as template and translate all keys (
Sources/PermissionsKit/Resources/Localization/en.lproj/Localizable.strings) - Verify all permission types have translated strings for new locale (
Sources/PermissionsKit/Resources/Localization/[locale].lproj/Localizable.strings)
Customize permission status check logic for a permission
- Open target permission file (e.g., CameraPermission.swift) (
Sources/CameraPermission/CameraPermission.swift) - Override the status computed property to add custom logic for edge cases or multiple frameworks (
Sources/CameraPermission/CameraPermission.swift) - For complex handlers, extract logic into separate Handler class (see LocationAlwaysHandler pattern) (
Sources/LocationPermission/Handlers/LocationAlwaysHandler.swift)
🔧Why these technologies
- Swift (pure, no Objective-C) — Modern type-safe language; protocol-oriented design eliminates boilerplate and enables universal API
- Multiple iOS frameworks (AVFoundation, CoreLocation, HealthKit, UserNotifications, etc.) — Each permission type requires its own native framework; abstraction layer provides unified interface
- Swift Package Manager + CocoaPods dual support — Maximizes adoption by supporting both modern (SPM) and legacy (CocoaPods) dependency systems
- Localization via .strings files (12 languages) — Standard iOS approach; enables community translation contributions and app-level localization
⚖️Trade-offs already made
-
Single unified Permission protocol vs. framework-specific types
- Why: Simplifies API surface; developers don't learn 15 different permission patterns
- Consequence: Some framework-specific capabilities (e.g., location accuracy) require permission-specific extensions
-
Synchronous status property + async request(completion:) methods
- Why: Status queries are instant (cached); requests require async for dialog/system interaction
- Consequence: Developers must handle two patterns; completion-based rather than async/await (iOS 13+ compatibility)
-
Modular targets per permission type vs. monolithic framework
- Why: Reduces app bundle size; developers link only permissions they use
- Consequence: Requires Package.swift/podspec coordination; more moving parts
-
No automatic re-checking on app foreground
- Why: Avoids continuous permission state polling; reduces battery/performance impact
- Consequence: Apps must manually call status queries when needed; can miss permission changes while backgrounded
🚫Non-goals (don't propose these)
- Real-time permission change notifications (use AppDelegate/Scene callbacks instead)
- Custom permission UI (framework is system dialog only)
- Permission scheduling or batching
- Handling of restricted/unavailable permissions (returns .denied; no distinction)
🪤Traps & gotchas
Info.plist configuration is mandatory—each permission type requires specific keys (NSCameraUsageDescription, NSLocationWhenInUseUsageDescription, etc.) or the app will crash on permission request; the README table lists these but they are easy to forget. Bluetooth and Location permissions require special handling for iOS 13+ background modes (must set NSBluetoothPeripheralUsageDescription and location background mode in Xcode). Health permission requires explicit entitlements setup in Xcode, not just Info.plist. No obvious CI/CD config (.github/ has templates but no .yml workflows shown) suggests manual testing burden falls on maintainers.
🏗️Architecture
💡Concepts to learn
- iOS Permission Model (Authorization Status Lifecycle) — PermissionsKit's core abstraction (.authorized, .denied, .notDetermined) maps directly to iOS's AVAuthorizationStatus, CLAuthorizationStatus, etc.; understanding this lifecycle prevents race conditions and improper state handling.
- Handler Pattern — PermissionsKit uses handlers (LocationAlwaysHandler, LocationWhenInUseHandler) to encapsulate framework-specific logic; this pattern keeps the Permission protocol clean and lets complex permissions like Location have multiple request flows.
- Protocol-Oriented Programming (Swift Protocols) — The entire framework is built on Swift protocols (Permission, PermissionStatus); mastering protocol conformance and generic constraints is essential to extending or modifying PermissionsKit.
- iOS Background Modes & Entitlements — Certain permissions (Location, Bluetooth) require entitlements and background mode configuration in Xcode; misconfiguration silently breaks permission requests at runtime.
- Localization (Strings Files & NSLocalizedString) — PermissionsKit ships with 6 language localizations using .strings files; understanding the localization workflow is critical when adding new permission messages or supporting additional languages.
- Info.plist Permission Declarations — iOS requires explicit NSUsageDescription keys in Info.plist for every permission; missing entries cause crashes. PermissionsKit abstracts the request, but the plist setup is the developer's responsibility.
🔗Related repos
ashleymills/Reachability.swift— Complementary iOS utility for checking network reachability status; often used alongside PermissionsKit in apps needing both permission and connectivity checks.devicekit/DeviceKit— Abstracts device detection and iOS version checks; useful in PermissionsKit-based apps to gate features by device capability.apple/swift-nio— Foundational Swift async/concurrency patterns; relevant as PermissionsKit could benefit from Swift Concurrency (async/await) for modern request flows.pointfreeco/swift-composable-architecture— State management framework that pairs well with PermissionsKit in SwiftUI apps needing to manage permission state alongside app state.
🪄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 unit tests for Permission status handlers
The repo has 11 permission modules (Camera, Location, Bluetooth, etc.) but no visible test directory. Each permission handler should have unit tests covering the three status states (.authorized, .denied, .notDetermined). This is critical for a permission library where correctness directly impacts app security.
- [ ] Create Tests/ directory structure mirroring Sources/ (e.g., Tests/CameraPermission/, Tests/LocationPermission/)
- [ ] Add unit tests for each permission's status checking logic in handlers like Sources/LocationPermission/Handlers/LocationAlwaysHandler.swift and Sources/BluetoothPermission/BluetoothHandler.swift
- [ ] Test the Permission.swift protocol implementation across all concrete permission types
- [ ] Add tests for the NotificationAccess+userNotifcationAuthorizationOptions.swift conversion logic with various authorization option combinations
Create GitHub Actions workflow for iOS permission testing across multiple iOS versions
The repo has .github/ISSUE_TEMPLATE and .github/PULL_REQUEST_TEMPLATE.md but no visible CI workflow. Permission APIs differ significantly across iOS versions (e.g., location accuracy, health permissions). Adding a matrix test across iOS 13-17 ensures compatibility and prevents regressions.
- [ ] Create .github/workflows/test.yml to run on push and PR events
- [ ] Configure matrix strategy to test against multiple iOS SDK versions (minimum deployment target through latest)
- [ ] Add build and test steps for both SPM (Package.swift) and CocoaPods (PermissionsKit.podspec) configurations
- [ ] Include linting checks for the localization files in Sources/PermissionsKit/Resources/Localization/
Add missing localization for incomplete string translations and document localization contributor guidelines
The repo supports 12 languages (ar, de, en, es, fa, fr, it, nl, pl, pt, ru, uk, zh variants) in Sources/PermissionsKit/Resources/Localization/, but there's no documented process for translators or validation that all .strings files have equivalent keys. The README is truncated mid-sentence and doesn't mention localization.
- [ ] Add a script in Sources/PermissionsKit/Resources/Localization/ to validate all language files have matching keys (catch missing translations early)
- [ ] Create LOCALIZATION.md documenting how to contribute translations and the required keys in Localizable.strings
- [ ] Add a GitHub Action workflow that runs the validation script on PRs modifying localization files
- [ ] Complete and document the truncated README.md with the full list of supported permissions and localization information
🌿Good first issues
- Add unit tests for each permission handler—create Tests/CameraPermissionTests.swift mirroring Sources/CameraPermission/CameraPermission.swift to validate .request() and .status paths.
- Expand localization: add Russian (ru.lproj) and Japanese (ja.lproj) folders under Sources/PermissionsKit/Resources/Localization/ following the pattern of existing .strings files.
- Document the handler pattern in CONTRIBUTING.md with a step-by-step example of adding a new permission type (e.g., a hypothetical VideoRecording permission), including required Info.plist keys.
⭐Top contributors
Click to expand
Top contributors
- @ivanvorobei — 71 commits
- @Oggerschummer — 4 commits
- @alexanderpuchta — 3 commits
- @zshannon — 2 commits
- @jonasrichardrichter — 2 commits
📝Recent commits
Click to expand
Recent commits
bc20d72— Merge pull request #354 from zshannon/main (ivanvorobei)8832904— expose SpeechPermission for macOS (zshannon)e449e39— Add macOS support to MicrophonePermission.swift (zshannon)5e59359— Updated doc for permissions accesses. (ivanvorobei)80a04a4— Merge pull request #353 from jonasrichardrichter/main (ivanvorobei)430dba4— Merge branch 'sparrowcode:main' into main (jonasrichardrichter)7fd4d6c— Merge pull request #352 from EchoLunar/EchoLunar-patch-1 (ivanvorobei)e6a501b— Adapt ContactsPermission to iOS 18, changing the limited status to return as authorized. (EchoLunar)982bb42— Merge pull request #348 from cs4alhaider/patch-1 (ivanvorobei)c0f8a1c— Fix typo in README.md (cs4alhaider)
🔒Security observations
PermissionsKit appears to be a well-structured iOS permissions abstraction library with no critical vulnerabilities evident from the file structure analysis. However, a complete security assessment requires examination of the actual Swift source code, especially the permission request implementations and status handling. The primary security dependencies are on Apple's native permission APIs, which are inherently secure when used correctly. The main recommendation is to ensure comprehensive security documentation for library users to prevent misuse. The score reflects good practices observed (modular structure, no obvious hardcoded credentials) balanced against incomplete code visibility.
- Medium · Missing dependency information in static analysis —
Package.swift. The Package.swift file content is not provided for analysis. Dependency vulnerabilities cannot be assessed without examining the actual package dependencies and their versions. Fix: Provide the Package.swift file content for dependency version analysis. Regularly audit dependencies using tools likeswift package show-dependenciesand check for known vulnerabilities using security advisories. - Low · Localization files may contain sensitive information —
Sources/PermissionsKit/Resources/Localization/*/Localizable.strings. Multiple localization files (.strings) are present across different languages. While typically harmless, these files could potentially contain hardcoded user messages that reveal system behavior or error details. Fix: Review localization strings to ensure they do not expose sensitive information, implementation details, or error messages that could aid attackers. Avoid including system paths, API endpoints, or debugging information. - Low · Permission framework handling without explicit security review —
Sources/*/[Permission].swift (all permission modules). The codebase handles multiple sensitive iOS permissions (Camera, Location, Contacts, Health, Photos, Microphone, etc.). While the framework itself manages permission requests through official APIs, improper implementation by developers using this library could lead to unauthorized access. Fix: Include comprehensive security documentation in README and code comments. Emphasize the importance of proper info.plist entries, user consent flows, and principle of least privilege. Consider adding warnings for sensitive permissions like Location Always or Health data. - Low · No visible input validation mechanisms —
Sources/PermissionsKit/. The file structure suggests this is primarily a permission request framework, but without examining actual code, potential input validation issues in permission callbacks or status checks cannot be assessed. Fix: Ensure all permission status callbacks and responses are validated. Implement defensive programming to handle unexpected permission states returned by the OS.
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.