devicekit/DeviceKit
DeviceKit is a value-type replacement of UIDevice.
Healthy across the board
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.
- ✓Last commit 5w ago
- ✓22+ active contributors
- ✓MIT licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 58% 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/devicekit/devicekit)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/devicekit/devicekit on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: devicekit/DeviceKit
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/devicekit/DeviceKit 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 the board
- Last commit 5w ago
- 22+ active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 58% 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 devicekit/DeviceKit
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/devicekit/DeviceKit.
What it runs against: a local clone of devicekit/DeviceKit — 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 devicekit/DeviceKit | 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 ≤ 62 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of devicekit/DeviceKit. If you don't
# have one yet, run these first:
#
# git clone https://github.com/devicekit/DeviceKit.git
# cd DeviceKit
#
# 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 devicekit/DeviceKit and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "devicekit/DeviceKit(\\.git)?\\b" \\
&& ok "origin remote is devicekit/DeviceKit" \\
|| miss "origin remote is not devicekit/DeviceKit (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 "Source/Device.swift.gyb" \\
&& ok "Source/Device.swift.gyb" \\
|| miss "missing critical file: Source/Device.swift.gyb"
test -f "Source/Device.generated.swift" \\
&& ok "Source/Device.generated.swift" \\
|| miss "missing critical file: Source/Device.generated.swift"
test -f "Package.swift" \\
&& ok "Package.swift" \\
|| miss "missing critical file: Package.swift"
test -f "DeviceKit.podspec" \\
&& ok "DeviceKit.podspec" \\
|| miss "missing critical file: DeviceKit.podspec"
test -f "Tests/Tests.swift" \\
&& ok "Tests/Tests.swift" \\
|| miss "missing critical file: Tests/Tests.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 62 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~32d)"
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/devicekit/DeviceKit"
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
DeviceKit is a Swift library that provides a modern, value-type replacement for UIDevice with device identification, hardware capability detection, and system metrics across iOS, tvOS, and watchOS. It abstracts away the complexity of detecting specific iPhone, iPad, Apple Watch, and Apple TV models, along with capabilities like Face ID, Touch ID, battery state, disk space, and screen properties. Single-package structure: Source/Device.swift.gyb is a template that generates Source/Device.generated.swift containing all device enumeration cases and logic. Tests/Tests.swift contains the test suite. Example/DeviceKitPlayground.playground provides interactive examples. The build system supports SPM (Package.swift), CocoaPods (DeviceKit.podspec), and Carthage.
👥Who it's for
iOS/tvOS/watchOS developers who need reliable device detection and hardware capability queries without dealing with raw model identifiers and UIDevice's reference semantics. Particularly useful for feature-gating, device-specific UI adaptation, and analytics teams building device telemetry.
🌱Maturity & risk
Production-ready and actively maintained. Current version 5.8.0 with comprehensive test coverage in Tests/Tests.swift, CI/CD pipeline via GitHub Actions (.github/workflows/main.yml), and well-documented changelog. The repository shows consistent maintenance with support across multiple Swift versions (4.x through current) and deployment targets (iOS 11.0+).
Low risk: single-language codebase (Swift) with no external dependencies beyond Apple frameworks, reducing supply chain concerns. However, the library requires frequent updates when Apple releases new device models—this is managed via the gyb code generator (Utils/gyb.py) that updates Source/Device.generated.swift, but additions are manual. No apparent single-maintainer risk given GitHub organization ownership.
Active areas of work
Version 5.8.0 is current with recent device model support (inferred from version bump). The codebase maintains compatibility across Swift 4.x and 5.x tracks. GitHub Actions workflows run on each commit, suggesting active CI/CD. See CHANGELOG.md for specific recent features and fixes.
🚀Get running
git clone https://github.com/devicekit/DeviceKit.git && cd DeviceKit && open DeviceKit.xcworkspace (for Xcode). Or use SPM: add to Package.swift dependencies. For CocoaPods: pod install with DeviceKit podspec.
Daily commands: Open DeviceKit.xcworkspace in Xcode and select the DeviceKit scheme, then build (⌘B). Run tests with ⌘U. For playground: open Example/DeviceKitPlayground.playground/playground.xcworkspace and run Contents.swift. No external services or build steps required.
🗺️Map of the codebase
Source/Device.swift.gyb— Template file that generates Device.generated.swift; contains all device model definitions and must be edited to add new device support.Source/Device.generated.swift— Auto-generated core enum and extensions defining all supported device models—the entry point for any device detection logic.Package.swift— Swift Package Manager manifest defining library dependencies and module exports; required for package distribution.DeviceKit.podspec— CocoaPods specification defining versioning, dependencies, and installation rules; used by Carthage and CocoaPods consumers.Tests/Tests.swift— Comprehensive test suite validating device detection logic and enum behavior across all supported models..github/workflows/main.yml— CI/CD pipeline orchestrating builds, tests, and code quality checks on every commit.Utils/gyb.py— Python script that processes .gyb template files to generate Device.generated.swift; required for the build system.
🧩Components & responsibilities
- Device enum (Swift enum, UIDevice interop) — Central value type holding all 100+ supported device cases; provides computed properties (name, diagonal, isPhone, etc.) and version checking.
- Failure mode: Unknown device returns .unknown case with safe fallback properties; never crashes on unrecognized identifiers
- Device.current static property (UIDevice.current, lazy static) — Entry point for library; queries UIDevice.current.model once and returns appropriate Device enum case.
- Failure mode: On identifier mismatch, returns .unknown rather than throwing, ensuring graceful degradation
- Code generator (gyb.py) (Python, Jinja2-style templating) — Build-time tool converting Device.swift.gyb template into Device.generated.swift; enables single-source device definitions.
- Failure mode: Template errors prevent build; mitigated by test validation of generated code
- Test suite (XCTest, Swift 5.3+) — Validates device detection, property correctness, and enum exhaustiveness across all 100+ cases.
- Failure mode: Test failures block CI; catch generation errors and API regressions before release
🔀Data flow
App→Device.current— Developer calls Device.current to retrieve the current device as a static propertyDevice.current→UIDevice.current.model— Queries native OS identifier string (e.g., 'iPhone14,2')UIDevice identifier→Device enum— Identifier mapped to Device case via match statement in initializerDevice enum case→Computed properties— Properties (diagonal, RAM, cameras, etc.) calculated from case on accessApp→Computed properties— Developer accesses properties like device.diagonal, device.isPhone, device.hasUltraWideCamera
🛠️How to make changes
Add a New Device Model
- Edit the .gyb template to add the device case to the Device enum with its identifier string mapping (
Source/Device.swift.gyb) - Run gyb.py or the build system to regenerate Device.generated.swift from the template (
Utils/gyb.py) - Add a test case in Tests.swift to validate device detection for the new model (
Tests/Tests.swift) - Update CHANGELOG.md to document the new device support (
CHANGELOG.md)
Add a New Computed Property to Device
- Add a new var or func extension in Device.swift.gyb with the desired logic (
Source/Device.swift.gyb) - Run gyb.py to regenerate Device.generated.swift (
Utils/gyb.py) - Add test cases in Tests.swift validating the new property across device models (
Tests/Tests.swift)
Update Build & Distribution Configuration
- Update version string and supported platforms in DeviceKit.podspec (
DeviceKit.podspec) - Bump version in Package.swift for SPM consumers (
Package.swift) - Update Source/Info.plist with matching version metadata (
Source/Info.plist) - Document changes in CHANGELOG.md (
CHANGELOG.md)
🔧Why these technologies
- Swift value types (enum) — Provides lightweight, thread-safe device detection without mutable state; replaces UIDevice's singleton reference semantics.
- Code generation (.gyb templates) — Maintains a single source of truth for device definitions while avoiding repetitive boilerplate across multiple properties and platform checks.
- CocoaPods + Carthage + SPM — Supports multiple package managers, maximizing adoption across iOS ecosystems with minimal overhead.
- GitHub Actions CI/CD — Automates testing, linting, and code quality gates on every commit without external service dependencies.
⚖️Trade-offs already made
-
Enum-based device representation instead of a class hierarchy
- Why: Simplicity and performance: avoids heap allocation, inheritance complexity, and enables exhaustive switching.
- Consequence: Adding properties requires template changes affecting all cases; no subclassing extensibility but cleaner API surface.
-
Client-side device detection via machine identifier strings
- Why: No network dependency; instant identification; works offline.
- Consequence: Must maintain and update device mappings as new models release; cannot use Apple's official device database.
-
Code generation over hand-written enum
- Why: DRY principle; reduces boilerplate when scaling to 100+ device models.
- Consequence: Build system dependency on gyb.py; template edits risk generation errors if not validated by tests.
-
Pure computed properties, no caching
- Why: Device never changes at runtime; computed properties cost negligible compared to first app launch.
- Consequence: Minor redundant calculations per property access; negligible in practice for library performance.
🚫Non-goals (don't propose these)
- Does not support Linux or non-Apple platforms
- Does not provide hardware sensor access (cameras, gyros, etc.); only device model and OS metadata
- Does not replace UIDevice for low-level system queries like battery level or locale
- Does not provide real-time device state tracking (e.g., orientation events)
⚠️Anti-patterns to avoid
- UIDevice singleton dependency (Low) —
Source/Device.swift.gyb: Device.current accesses UIDevice.current, a global singleton; acceptable here but couples library to Apple's implementation. - Hardcoded device identifier strings (Medium) —
Source/Device.swift.gyb: Device cases map manually to identifier strings ('iPhone14,2'); no validation that new strings are added when Apple releases devices. - Code generation without versioning —
Utils/gyb.py: undefined
🪤Traps & gotchas
- Device.generated.swift must be regenerated after editing Device.swift.gyb—do not manually edit Device.generated.swift as changes will be overwritten. 2) New device models require manual addition to the gyb template; Apple's simulator model names may differ from real device identifiers. 3) Some hardware capabilities (Face ID, Touch ID) depend on runtime availability checks beyond model detection. 4) Testing new models requires either actual devices or simulator model overrides; see Tests/Tests.swift for simulator simulation patterns.
🏗️Architecture
💡Concepts to learn
- Code generation via Jinja2 templates (Gyb) — DeviceKit uses Utils/gyb.py to generate boilerplate Device.generated.swift from a single Device.swift.gyb template, ensuring consistency and maintainability as Apple releases new devices—understanding this pattern is essential for adding new models
- Value semantics and equatable enums — Device is a value-type enum (not a reference-type class like UIDevice), enabling safer threading, easier testing, and predictable copying—this is the core design philosophy replacing UIDevice
- sysctl hardware model introspection — DeviceKit queries system control interface (sysctl) to read hw.machine identifiers (e.g., 'iPhone15,2') to determine exact device model at runtime—this is how it distinguishes between subtle variants
- Capability-based feature detection — Instead of requiring version checks or model lists, DeviceKit exposes boolean properties like hasFaceID, hasTouchID, hasNotch to enable safe feature-gating across hardware generations
- Cross-platform conditional compilation (#if os) — DeviceKit maintains a single codebase for iOS, tvOS, and watchOS using Swift's platform-specific conditional compilation—critical for avoiding runtime crashes on unsupported platforms
- Device family and group abstractions — Beyond individual model detection, DeviceKit groups devices into families (iPhone, iPad, Apple Watch) and logical groups (iPhone Pro, iPhone Pro Max)—useful for UI/UX decisions that apply to device classes rather than specific models
- Battery and Low Power Mode state queries — DeviceKit wraps UIDevice battery APIs with value semantics and adds Low Power Mode detection, enabling energy-aware app behavior without coupling to UIDevice's reference semantics
🔗Related repos
apple/swift-foundation— Official Apple Foundation framework that DeviceKit builds upon for device queries and system property accessAlamofire/Alamofire— Popular Swift HTTP client library often paired with DeviceKit for device-aware analytics and feature telemetry reportingpointfreeco/swift-composable-architecture— Modern Swift architecture framework that integrates well with DeviceKit for state management of device-dependent featuresonevcat/Kingfisher— Image caching library that leverages DeviceKit's available disk space detection for optimization decisionsrealm/realm-swift— Database framework that can use DeviceKit's storage metrics to optimize sync and cache strategies per device model
🪄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 device detection tests for iOS 18+ models
The Tests/Tests.swift file likely has gaps in coverage for the newest iPhone/iPad models. Since Source/Device.generated.swift is auto-generated from Source/Device.swift.gyb, there are probably new 2024 Apple devices (iPhone 16 series, iPad Pro M4, etc.) that need test cases added. This ensures the generator template and tests stay in sync as Apple releases new hardware.
- [ ] Review Source/Device.swift.gyb to identify all device cases defined
- [ ] Check Tests/Tests.swift for missing test assertions covering all device models
- [ ] Add test cases for each device variant (standard, Plus, Pro, Max, Ultra variants)
- [ ] Add tests verifying device.identifier correctly maps to Device enum cases
- [ ] Run test suite to ensure 100% coverage of Source/Device.generated.swift device detection logic
Set up GitHub Actions workflow for Swift Package Manager compatibility testing
The repo uses Package.swift for SPM support but .github/workflows/main.yml likely only tests CocoaPods/Carthage. New contributors should add a dedicated SPM test workflow to catch integration issues early. This is critical since many modern Swift projects use SPM exclusively.
- [ ] Review .github/workflows/main.yml to see what platforms are currently tested
- [ ] Create .github/workflows/spm-test.yml that runs 'swift build' and 'swift test'
- [ ] Add matrix testing across multiple Swift versions (5.7, 5.8, 5.9+)
- [ ] Test on both macOS and Linux runners (if applicable to DeviceKit's scope)
- [ ] Verify the workflow runs on pull requests and commits to master
Add privacy manifest validation and documentation for Source/PrivacyInfo.xcprivacy
The repo has Source/PrivacyInfo.xcprivacy (Apple's privacy manifest file) but there's no documentation in README.md explaining what data categories DeviceKit declares or why. Additionally, there's likely no CI check ensuring the privacy manifest stays valid and documented as the project evolves.
- [ ] Review Source/PrivacyInfo.xcprivacy and document which privacy categories are declared
- [ ] Add a 'Privacy' section to README.md explaining DeviceKit's privacy stance and manifest contents
- [ ] Create a lint script in Scripts/ to validate PrivacyInfo.xcprivacy XML structure and required keys
- [ ] Add the validation script to .github/workflows/main.yml to prevent invalid manifests in PRs
- [ ] Document in CHANGELOG.md any privacy-relevant changes going forward
🌿Good first issues
- Add exhaustive tests for newly announced Apple Watch Series models (e.g., Series 10, Ultra 2) by extending Tests/Tests.swift with specific model assertions for capabilities like battery, screen size, and sensor availability—requires adding test cases matching entries in Device.swift.gyb
- Expand documentation in README.md for the gyb code generation workflow: explain how to add a new device model, what fields in Device.swift.gyb must be updated, and how to verify the generated code—currently undocumented for contributors
- Create a Python script (or enhance Utils/gyb.py) to validate that Device.generated.swift stays in sync with Device.swift.gyb and warn if regeneration is needed before committing—useful for CI/pre-commit hooks
⭐Top contributors
Click to expand
Top contributors
- @Zandor300 — 58 commits
- @denisenepraunig — 13 commits
- @Copilot — 6 commits
- @dependabot[bot] — 2 commits
- @arindamxd — 2 commits
📝Recent commits
Click to expand
Recent commits
56b997e— Version bump. (v5.8.0) (Zandor300)3d2a7bd— fix M5 iPad Pro models (#480) (metal-president)6baf21a— Bump git from 1.9.1 to 1.13.1 (#348) (dependabot[bot])43fedd8— Fix Danger plist warning being triggered on every PR (#489) (Zandor300)92f1800— Update GitHub Actions to macOS 15 with Xcode 26.2 (#487) (Zandor300)ee6239c— Rename iPad Mini to iPad mini for Apple naming consistency (#478) (Copilot)5314fea— Fix Apple Pencil compatibility for M4 iPad Pro and M2/M3 iPad Air models (#474) (Copilot)d07d19c— Add changelog entry for PR #484 (Zandor300)584ec1a— Exclude unhandled files (#484) (klaaspieter)354737a— Add iPhone 17e and iPad Air (M4) support (#486) (Zandor300)
🔒Security observations
DeviceKit appears to be a well-maintained iOS/Swift library with no critical security vulnerabilities visible from the file structure analysis. As a device information abstraction library, it has minimal attack surface. Primary concerns are: (1) unverified dependency security due to missing Package.swift content, (2) custom code generation tool (gyb) that requires validation, and (3) general best practices for script security. The codebase shows good practices with privacy manifest file (PrivacyInfo.xcprivacy) and CI/CD workflow integration. Recommend dependency auditing and periodic security reviews of the code generation pipeline.
- Medium · Missing dependency lock file visibility —
Package.swift. The Package.swift file content was not provided for analysis. Without examining the Swift Package Manager configuration, potential vulnerable dependencies cannot be identified. DeviceKit may have transitive dependencies with known CVEs. Fix: Provide Package.swift content for analysis. Regularly audit dependencies using tools likeswift package diagnoseand maintain an updated dependency inventory. Consider using dependency scanning tools in CI/CD pipeline. - Low · Script execution without validation —
Scripts/push.sh. The Scripts/push.sh file is present but content not provided. Shell scripts, if not properly validated, could pose risks if they execute unvalidated input or use insecure patterns. Fix: Review push.sh for: 1) Proper input validation, 2) Use ofset -eandset -uflags, 3) Avoidance of eval() and dynamic code execution, 4) Secure credential handling. Ensure scripts are code-reviewed before merging. - Low · Code generation tool without explicit validation —
Utils/gyb.py, Source/Device.generated.swift, Source/Device.swift.gyb. The project uses a custom gyb.py code generation tool (Utils/gyb.py). Code generation tools can introduce vulnerabilities if they process untrusted input or have logic errors. The Device.generated.swift is auto-generated and may be difficult to audit. Fix: 1) Document the gyb tool's purpose and validate its implementation, 2) Include generated code in version control with clear marking, 3) Implement automated testing of generated code, 4) Consider using established code generation tools if possible. - Low · Potential information disclosure in example files —
Example/DeviceKitPlayground.playground/Contents.swift. Playground files (Example/DeviceKitPlayground.playground) may contain sensitive examples or test data that could be exposed if accidentally committed. Fix: Ensure example code does not contain: 1) API keys or tokens, 2) Real device identifiers, 3) Hardcoded credentials. Use placeholder values in examples and document security best practices for library users.
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.