Help us improve
Share bugs, ideas, or general feedback.
From apple-dev
Use when the user says 'code audit', 'audit code', '代码审计', 'report card', 'security scan', or wants a comprehensive code quality assessment. Scans for security issues, concurrency safety, accessibility gaps, performance anti-patterns, and SwiftUI anti-patterns in iOS/macOS Swift projects.
npx claudepluginhub n0rvyn/indie-toolkit --plugin apple-devHow this skill is triggered — by the user, by Claude, or both
Slash command
/apple-dev:code-auditThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Comprehensive code quality audit for iOS/macOS Swift projects across 5 categories.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
Comprehensive code quality audit for iOS/macOS Swift projects across 5 categories.
Ask user or auto-detect:
.swift files under project rootExclude: Pods/, .build/, DerivedData/, *.generated.swift, test targets (unless user requests test audit).
Record file count for final summary.
Grep for patterns:
"sk-[a-zA-Z0-9]{20,}" — API keyspassword\s*[:=]\s*"[^"]{8,}" — hardcoded passwords (exclude test fixtures and placeholders like "password123" in test targets)AKIA[0-9A-Z]{16} — AWS access keys-----BEGIN.*PRIVATE KEY----- — embedded private keysapi[_-]?key\s*[:=]\s*"[^"]{8,}" — generic API keys[2.1] Hardcoded secrets — 🔴 {pattern} at {file:line} / ✅ none
Grep for:
http:// in URL strings (excluding localhost, 127.0.0.1, 0.0.0.0)allowsArbitraryLoads.*true in Info.plistServerTrust without certificate pinningURLSession custom configurations without TLS minimum version[2.2] Network security — 🔴/🟡 {issue} at {file:line} / ✅ clean
Grep for:
"\(.*)" near SELECT|INSERT|UPDATE|DELETENSPredicate(format: with \( interpolation (should use %@ arguments)WKWebView loading user-provided URLs without scheme validation[2.3] Input validation — 🔴 {issue} at {file:line} / ✅ clean
Check storage patterns:
UserDefaults storing tokens/passwords/keys → 🔴 (should use Keychain)SecItem, KeychainAccess, or custom)[2.4] Sensitive storage — 🔴 UserDefaults for secrets at {file:line} / ✅ Keychain used
Grep for:
Sendable conformance@unchecked Sendable usage → 🟡 flag for manual reviewvar properties in Sendable types without synchronization[3.1] Sendable — 🟡 @unchecked Sendable at {file:line} / 🔴 non-Sendable crossing at {file:line} / ✅ clean
Grep for:
DispatchQueue.main.async in SwiftUI context (should use @MainActor)@MainActor that update UI-bound propertiesnonisolated on properties that access mutable state[3.2] Actor isolation — 🟡/🔴 {issue} at {file:line} / ✅ clean
Grep for:
var properties on non-actor classes accessed from multiple Task {} blocksTask.detached capturing mutable variables[3.3] Data races — 🔴 {issue} at {file:line} / ✅ none detected
Grep for:
Image( without .accessibilityLabel (unless .accessibilityHidden(true)).onTapGesture, .gesture(TapGesture) without accessibility traits[4.1] Accessibility labels — 🟡 missing label at {file:line} / ✅ covered
Check for:
.accessibilityElement(children: .combine) on logical groups.accessibilityAction for custom gestures.accessibilityValue for stateful controls (toggles, sliders, steppers)[4.2] VoiceOver — 🟡 {issue} at {file:line} / ✅ adequate
Grep for:
.font(.system(size: — hardcoded font sizes break Dynamic Type → 🟡.frame(height: on text containers → 🟡.minimumScaleFactor on critical text[4.3] Dynamic Type — 🟡 fixed font size at {file:line} / ✅ dynamic fonts used
Grep for:
DispatchQueue.main.sync — deadlock risk → 🔴Thread.sleep / usleep on main thread → 🔴Data(contentsOf:), String(contentsOfFile:)) in body or @MainActor context[5.1] Main thread — 🔴 blocking at {file:line} / ✅ clean
Grep for:
@ObservedObject used where @StateObject is appropriate (object recreated every parent redraw)@State initialized with expensive computation (runs every view init)body that could benefit from extraction[5.2] Redraws — 🟡 {issue} at {file:line} / ✅ clean
Grep for:
self strongly in long-lived contexts (NotificationCenter.addObserver, Timer.scheduledTimer, stored closures)[weak self] in escaping closures stored as propertiesTimer.publish without cancellation in onDisappear/task[5.3] Memory leaks — 🔴 strong self in {context} at {file:line} / ✅ clean
Grep for:
.onAppear used for async work → 🟡 (should use .task for auto-cancellation).task { } with network calls that don't check Task.isCancelled → 🟡[6.1] Task cancellation — 🟡 .onAppear async at {file:line} / ✅ .task used
Check for:
@ObservedObject for owned objects → should be @StateObject@StateObject in non-View types → invalid@State for reference types without @Observable@EnvironmentObject without .environmentObject() in preview providers[6.2] Property wrappers — 🟡 {issue} at {file:line} / ✅ correct
Check for:
NavigationView (deprecated) → use NavigationStack → 🟡NavigationPath[6.3] Navigation — 🟡 deprecated NavigationView at {file:line} / ✅ modern patterns
Write report to .claude/reviews/audit-{YYYY-MM-DD}.md:
# Code Audit Report
**Date**: {YYYY-MM-DD}
**Scope**: {N} files audited
**Commit**: {HEAD SHA short}
## 🔴 Critical ({N})
- [{category}] {issue}
File: {file:line}
Evidence: {code snippet}
Fix: {specific recommendation}
## 🟡 Warning ({N})
- [{category}] {issue}
File: {file:line}
Evidence: {code snippet}
Fix: {specific recommendation}
## 🟢 Clean ({N} categories)
- {category}: {summary}
## Summary
| Category | 🔴 | 🟡 | 🟢 |
|----------|-----|-----|-----|
| Security | X | Y | Z |
| Concurrency | X | Y | Z |
| Accessibility | X | Y | Z |
| Performance | X | Y | Z |
| SwiftUI | X | Y | Z |
| **Total** | **X** | **Y** | **Z** |
After report is written:
git rev-parse HEAD > .claude/last-audit-commit
This enables the staleness reminder in dev-workflow/hooks/suggest-skills.sh. After 20+ commits, users running /commit, /write-plan, or /write-dev-guide will see a reminder to re-run /code-audit.
file:line and a code snippet. No vague warnings..claude/reviews/audit-{date}.md.claude/last-audit-commit updated with current HEAD SHA