Plug-in for Leio iOS apps: shared AI coding guidelines and a reusable quality gate (SwiftLint, SwiftFormat, Periphery).
See the rules in rules/always.md. Quality scripts live under quality/.
New apps: use the ios-bootstrap agent skill (XcodeGen starter + this plug-in + warnings-as-errors). Ongoing work: ios-quality-gate.
| Tool | Config Location |
|---|---|
| Augment | .augment/rules/always.md |
| Cursor | .cursor/rules/always.mdc |
| Windsurf | .windsurfrules |
| Cline | .clinerules |
| GitHub Copilot | .github/copilot-instructions.md |
| Claude Code | .claude/rules/always.md |
| Any agent | AGENTS.md (tool-neutral) |
From your app repo root:
curl -fsSL https://raw.githubusercontent.com/dbmrq/ai-rules-ios/main/install.sh | bash -s -- --non-interactive --no-commitThis will:
- Add ai-rules-ios as a git subtree at
.ai-rules/ - Copy rules into all supported tool locations (read-only copies)
- Create thin
scripts/check.sh,format.sh,deadcode.sh,check-all.shwrappers - Seed
.swiftlint.yml(parent config),.swiftformat,.periphery.ymltemplate, andAGENTS.md - Install a pre-commit hook that re-syncs on commit
Then:
- Edit
.periphery.ymlfor your scheme/project (nobaseline:) - Set
SWIFT_TREAT_WARNINGS_AS_ERRORS: YESon every Swift target (seequality/xcodegen/settings-strict.yml) - Wire Quality Check
preBuildScripts+ENABLE_USER_SCRIPT_SANDBOXING: NOon the app target - Run:
./scripts/format.sh --fix
./scripts/check.sh
# after an Xcode build:
./scripts/deadcode.shcurl -fsSL …/install.sh | bash -s -- --dry-run
curl -fsSL …/install.sh | bash -s -- --non-interactive --no-commit- Warnings as errors — compiler (
SWIFT_TREAT_WARNINGS_AS_ERRORS) and SwiftLint (all curated rules areerrorseverity). - No Periphery baselines —
./scripts/deadcode.shruns with--strict; delete unused code instead of suppressing. - No force unwraps —
force_unwrapping,force_try,force_cast,implicitly_unwrapped_optionalare errors. - One shared config —
quality/.swiftlint.yml; apps only setparent_config+ paths.
| Family | Rules |
|---|---|
| Foot-guns | force_cast, force_try, force_unwrapping, implicitly_unwrapped_optional |
| Size | file_length (400), type_body_length (250), function_body_length (50), function_parameter_count (7), cyclomatic_complexity (15), nesting |
| Empty / redundancy | empty_count, empty_string, redundant_nil_coalescing, unused_optional_binding, contains_over_filter_count, first_where |
| Idioms | unavailable_condition, optional_data_string_conversion |
| Custom | no_observable_object |
| Path | Role |
|---|---|
quality/.swiftlint.yml |
Shared lint rules (apps use parent_config; all errors) |
quality/.swiftformat |
Shared formatting |
quality/scripts/* |
Canonical check / format / deadcode / debt-report scripts |
quality/debt/RATCHET.md |
Zero-suppression checklist (historical debt only) |
quality/templates/* |
.periphery.yml + AGENTS.md seeds |
quality/xcodegen/* |
preBuild, strict settings snippets |
quality/ci/* |
Xcode Cloud pre/post fragments |
Apps keep thin overlays only (scheme-specific Periphery config, optional lint path tweaks).
curl -fsSL https://raw.githubusercontent.com/dbmrq/ai-rules-ios/main/install.sh | bash -s -- --non-interactive --no-commitOr:
git subtree pull --prefix=.ai-rules https://github.com/dbmrq/ai-rules-ios.git main --squash
.ai-rules/sync.shEdit only .ai-rules/rules/always.md (or this upstream repo). Tool-specific files are read-only copies — run .ai-rules/sync.command or sync.sh after edits.
curl -fsSL https://raw.githubusercontent.com/dbmrq/ai-rules-ios/main/uninstall.sh | bash