rshankras/code-size
Enforce complexity and size limits on Swift code with SwiftLint threshold rules — cyclomatic complexity, function/type/file length, parameter count — adopted via a violations baseline so existing code never blocks. Use when agent-written code needs deterministic size constraints.
npx skills add https://github.com/rshankras/claude-code-apple-skills --skill code-size
Complexity is the strongest single predictor of defect density, and code written *by agents* balloons fastest — an agent under pressure adds one more branch to an existing function far more readily than it extracts a new one. These five SwiftLint threshold rules are the deterministic cap: they keep functions small enough that tests can actually cover their branches, and they keep agents from wrangling with their own tangles.
Use this skill when:
testing/fitness-functions/)The fragment at rules/swiftlint.yml configures five built-in SwiftLint rules (all enabled by default in SwiftLint — this fragment sets the thresholds):
| Rule | Warning | Error | What it caps |
|---|---|---|---|
| cyclomatic_complexity | 10 | 20 | Independent paths through one function |
| function_body_length | 50 | 100 | Lines per function body |
| type_body_length | 300 | 500 | Lines per type body |
| file_length | 500 | 1000 | Lines per file |
| function_parameter_count | 5 | 8 | Parameters per function |
Merge the fragment into the project's .swiftlint.yml (alongside any opt_in_rules/custom_rules fragments already adopted).
Turning these rules on in an existing codebase must not trigger a refactoring spree — bulk rewrites to satisfy a linter are how working code gets broken. Freeze today's violations and gate only *new* ones:
# One-time: record existing violations (SwiftLint 0.55+)
swiftlint lint --write-baseline .swiftlint-baseline.json
# The gate from then on — fails only on NEW violations
swiftlint lint --strict --baseline .swiftlint-baseline.json
Commit .swiftlint-baseline.json. Shrink it opportunistically: when touching a baselined function for other reasons, fix its violation and regenerate the baseline in the same commit.
Fallback for older SwiftLint (before 0.55, no baseline support): record the violation count instead —
swiftlint lint --quiet | wc -l > .swiftlint-count
# Gate: current count must not exceed the committed count
The fix is structural, not suppressive:
cyclomatic_complexity / function_body_length → extract the branches into named functions, or replace the branch ladder with a table/enum dispatchtype_body_length / file_length → split by responsibility (extensions in separate files count separately)function_parameter_count → introduce a parameter struct// swiftlint:disable is not a fix. The rare legitimate exemption (a generated file, a big-but-flat data table) belongs in .swiftlint.yml's excluded: list with a comment — visible in one place, not scattered through source.
| Pitfall | Problem | Solution |
|---------|---------|----------|
| Enabling without a baseline | Day-one wall of violations, gate ignored | --write-baseline first, gate on new only |
| Mass-refactoring to satisfy thresholds | Working code broken for a number | Freeze old violations; fix opportunistically |
| Inline swiftlint:disable comments | Exemptions scattered and invisible | excluded: list in config, with reasons |
| Thresholds loosened per-project | Cap quietly stops capping | Change thresholds only with a written reason |
testing/fitness-functions/ — set/count invariants a per-line rule can't expresstesting/coverage-ratchet/ — the coverage half of the metrics gauntletios/coding-best-practices/ — iOS-specific lint fragment (style/API rules)generators/ci-cd-setup/ — base .swiftlint.yml template these fragments merge intoTake rshankras/code-size from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.