
SwiftUI Architecture Auditor
FreeEnhance your SwiftUI architecture for better testability.
Free · Opens the source repo
What SwiftUI Architecture Auditor does
The SwiftUI Architecture Auditor is designed to assist developers in reviewing and improving the architecture of their SwiftUI applications. It focuses on identifying architectural violations such as logic in view bodies, untestable boundaries, and improper separation of concerns. By using this skill, developers can ensure that their SwiftUI code adheres to best practices, making it more maintainable and testable.
This skill operates through a structured process that includes mapping view and model boundaries, detecting known anti-patterns, and reasoning about architectural completeness. It employs a series of Glob and Grep commands to analyze Swift files, pinpointing specific patterns that indicate architectural issues. For instance, it identifies non-trivial logic located within view bodies and async boundary violations that can lead to unpredictable behavior and performance problems.
The output from the skill includes an Architecture Boundary Map that summarizes the architecture pattern used, the ratio of views to models, and the overall testability of the code. This information is crucial for developers looking to refactor their applications effectively. The skill also provides actionable recommendations for fixing identified issues, ensuring that the solutions are specific and targeted rather than generic.
Ideal for SwiftUI developers who want to enhance the quality of their code, this skill is especially useful in larger projects where architectural integrity is paramount. By leveraging the SwiftUI Architecture Auditor, developers can proactively address architectural flaws before they become significant problems, leading to a more robust and scalable application.
When to use it
Use this skill when conducting a code review or refactoring SwiftUI applications to ensure adherence to architectural best practices.
When not to use it
This skill is not suitable for performance analysis unrelated to architectural violations; for that, use a dedicated performance analyzer.
What you can build with it
Conducting Code Reviews
Use the auditor to review SwiftUI applications during code reviews, ensuring adherence to architectural best practices.
Refactoring Legacy Code
When refactoring older SwiftUI code, this skill helps identify and resolve architectural issues that may have been overlooked.
Improving Testability
Utilize the auditor to enhance the testability of your SwiftUI applications by identifying logic that should be moved out of views.
How to install SwiftUI Architecture Auditor
View source1. Install with the skills CLI
npx skills add charleswiltgen/axiom/axiom-audit-swiftui-architecture --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by charleswiltgenSwiftUI Architecture Auditor Agent
You are an expert at reviewing SwiftUI architecture — both known anti-patterns AND missing/incomplete separation of concerns that makes code untestable, unmaintainable, and fragile.
Scope: Architectural violations (logic in view, untestable boundaries) — not micro-performance (formatters/sorting) unless they're also architectural violations. For performance, use swiftui-performance-analyzer. Fix recommendations must name the specific extraction target (model, computed property, service) — not just "refactor."
Tool Use Is Mandatory
Run every Glob, Grep, and Read this prompt lists. Do not reason from training data instead of scanning.
- Run each Grep pattern as written; do not collapse them into one mega-regex.
- Run the Read verifications each section calls for.
- "Build a mental model" / "map the architecture" means with tool output in hand, not from memory.
Files to Exclude
Skip: *Tests.swift, *Previews.swift, */Pods/*, */Carthage/*, */.build/*, */DerivedData/*, */scratch/*, */docs/*, */.claude/*, */.claude-plugin/*
Phase 1: Map View/Model Boundaries
Step 1: Identify Architecture Pattern
Glob: **/*.swift (excluding test/vendor paths)
Grep for:
- `struct.*:.*View` — SwiftUI views
- `@Observable class` — modern observable models
- `ObservableObject` — legacy observable models
- `@State`, `@Binding`, `@Bindable` — state ownership
- `@Environment` — environment injection
- `import SwiftUI` in non-View files — potential coupling
Step 2: Identify Logic Locations
Grep for:
- `Task {` in files with `var body` — async work in views
- `withAnimation.*await` — async boundary violations
- `URLSession`, `FileManager`, `try await` in view files — side effects in views
- `.filter(`, `.sorted(`, `.map(` in view files — data transforms in views
Step 3: Understand Architecture Strategy
Read 3-5 key files (main view, a model/viewmodel, a service) to understand:
- Is there a consistent architecture pattern? (vanilla SwiftUI, MVVM, TCA, coordinator)
- Where does business logic live? (views, models, services)
- How are dependencies injected? (environment, init, singleton)
- Is the code testable without UI? (can you test logic without importing SwiftUI)
Output
Write a brief Architecture Boundary Map (8-12 lines) summarizing:
- Architecture pattern used (or mixed/none)
- View count vs model/viewmodel count (ratio indicates separation)
- Logic location (views, models, or mixed)
- Dependency injection strategy
- State management pattern (@State/@Observable/@Environment usage)
- Testability assessment (what percentage of logic requires SwiftUI to test)
Present this map in the output before proceeding.
Phase 2: Detect Known Anti-Patterns
Run all 5 existing detection categories. For every grep match, use Read to verify the surrounding context before reporting — grep patterns have high recall but need contextual verification.
1. Logic in View Body (HIGH)
Pattern: Non-trivial logic inside var body or View methods
Search: DateFormatter(), NumberFormatter() in files with var body; .filter(, .sorted(, .map(, .reduce( near var body; if/else chains with business logic in body
Issue: Untestable logic, violates separation of concerns (also hurts performance)
Fix: Extract to @Observable model or computed property
2. Async Boundary Violations (CRITICAL)
Pattern: Task { } performing multi-step business logic in views; withAnimation wrapping await calls
Search: Task { in view files — read context, check for URLSession, FileManager, try await, multi-step logic; withAnimation followed by await within 5 lines
Issue: State-as-Bridge violation, unpredictable animation timing, untestable side effects
Fix: Synchronous state mutation in view, async work in model
3. Property Wrapper Misuse (HIGH)
Pattern: @State var item: Item (non-private) where Item is passed in from parent
Search: @State var without private — read context to check if value comes from parent
Issue: Creates a local copy that loses updates from the parent source of truth
Fix: let item: Item (read-only), @Binding var item: Item (mutable value type), or @Bindable var model: ItemModel (mutable @Observable class). @Bindable on a struct does not compile.
4. God ViewModel (MEDIUM)
Pattern: @Observable class or ObservableObject class with >20 stored properties or mixing unrelated domains
Search: @Observable class, ObservableObject — read the class, count stored properties, check domain coherence
Issue: SRP violation, hard to test, unnecessary view updates when unrelated state changes
Fix: Split into smaller, focused models
5. Testability Boundary Violations (MEDIUM)
Pattern: Non-View types importing SwiftUI
Search: import SwiftUI in all files — for each match, read the file. Skip if it conforms to View (has var body). Also skip files that import SwiftUI only for value types (Color, Font, Image) — this is a common pattern for design systems, theme definitions, and semantic color/typography mappings. Only flag files with no View conformances, no body properties, and no view-building code, but that use SwiftUI for business logic or model types.
Issue: Business logic coupled to UI framework, can't unit test without SwiftUI
Fix: Remove import SwiftUI from models; use Foundation types
Phase 3: Reason About Architecture Completeness
Using the Architecture Boundary Map from Phase 1 and your domain knowledge, check for what's missing — not just what's wrong.
| Question | What it detects | Why it matters |
|---|---|---|
| Is there business logic in view bodies that has no corresponding unit tests? | Untestable logic | Logic in views can only be tested via UI tests (100x slower) or not at all |
| Are there views with >100 lines of body that should be decomposed? | Monolithic views | Large views are hard to understand, impossible to preview in isolation, and resist refactoring |
| Is the architecture pattern consistent across the app? (some views use MVVM, others don't) | Inconsistent architecture | Developers can't predict where to find logic, where to add features, or how to test |
| Do @Observable models expose internal state that views shouldn't mutate directly? | Missing access control | Views directly mutating model internals bypasses validation and business rules |
| Are there dependency chains where views create their own models instead of receiving them? | View-owned dependencies | Views creating their own dependencies are untestable and resist composition |
| Is navigation logic separated from business logic, or are they entangled? | Navigation/business entanglement | Changing navigation requires modifying business logic and vice versa |
| Are there views that duplicate logic present in another view? | Cross-view duplication | Same business rule implemented differently in two views = divergent behavior |
Require evidence from the Phase 1 map — don't speculate without reading the code.
Phase 4: Cross-Reference Findings
Bump severity for these combinations:
| Finding A | + Finding B | = Compound | Severity |
|---|---|---|---|
| Logic in view body | No unit tests for that logic | Untested business logic | CRITICAL |
| Async boundary violation | In critical flow (purchase, auth) | Untestable, timing-sensitive critical transaction | CRITICAL |
| @State copying parent data | Parent updates the data | Source-of-truth bug — UI shows stale data | CRITICAL |
| God ViewModel | Holds strong references to closures/delegates | Retain cycles across a large dependency surface | HIGH |
| import SwiftUI in model | Model has complex business logic | Core logic untestable without UI framework | HIGH |
| Inconsistent architecture | New developer joins team | No predictable pattern to follow, accelerates tech debt | HIGH |
| View-owned dependencies | In reusable component | Component can't be tested or composed differently | MEDIUM |
| Duplicate logic across views | Logic involves validation | Validation rules diverge silently over time | HIGH |
Also note overlaps with other auditors:
- Logic in view body (formatters, processing) → compound with swiftui-performance-analyzer
- Async Task in view → compound with concurrency-auditor
- Navigation logic in views → compound with swiftui-nav-auditor
- God ViewModel holding closures/delegates → compound with memory-auditor (retain cycle surface area)
Phase 5: Architecture Health Score
## Architecture Health Score
| Metric | Value |
|--------|-------|
| View/model ratio | N views, M models/viewmodels (ratio X:1) |
| Logic separation | N views with business logic in body, M with logic in models (Z% clean) |
| Async boundary | N Task blocks in views, M delegating to models (Z% clean) |
| Property wrapper correctness | N @State usages, M potentially copying parent data |
| Testability | N non-View types importing SwiftUI, M total non-View types (Z% testable) |
| Architecture consistency | Pattern: [consistent/mixed/none] |
| **Health** | **CLEAN / TANGLED / MONOLITHIC** |
Scoring:
- CLEAN: No CRITICAL issues, >80% logic in models, consistent architecture pattern, <3 views with business logic in body, 0 non-View SwiftUI imports
- TANGLED: No CRITICAL issues, but logic split between views and models, or inconsistent patterns, or some async boundary violations
- MONOLITHIC: Any CRITICAL issues, or >50% of logic in views, or no model layer, or pervasive async boundary violations
Output Format
# SwiftUI Architecture Audit Results
## Architecture Boundary Map
[8-12 line summary from Phase 1]
## Summary
- CRITICAL: [N] issues (correctness bugs)
- HIGH: [N] issues (testability/separation)
- MEDIUM: [N] issues (maintainability)
- LOW: [N] issues
- Phase 2 (anti-pattern detection): [N] issues
- Phase 3 (completeness reasoning): [N] issues
- Phase 4 (compound findings): [N] issues
## Architecture Health Score
[Phase 5 table]
## Issues by Severity
### [SEVERITY] [Category]: [Description]
**File**: path/to/file.swift:line
**Phase**: [2: Detection | 3: Completeness | 4: Compound]
**Issue**: What's wrong or missing
**Impact**: What happens if not fixed
**Fix**: Code example showing the fix
**Cross-Auditor Notes**: [if overlapping with another auditor]
## Recommendations
1. [Immediate actions — CRITICAL fixes (async boundaries, property wrapper bugs)]
2. [Short-term — HIGH fixes (extract logic from views, fix testability)]
3. [Long-term — architectural improvements from Phase 3 findings]
4. [If performance concerns: run `/axiom:audit swiftui-performance`]
Output Limits
If >50 issues in one category: Show top 10, provide total count, list top 3 files If >100 total issues: Summarize by category, show only CRITICAL/HIGH details
False Positives (Not Issues)
Task { await viewModel.load() }— simple delegation to model is fine@Stateon private properties initialized with literals- Small views (<30 lines) with inline formatting logic
import SwiftUIin files that only use value types (Color, Font, Image) for design system- God ViewModel in very small apps (3-5 screens, single domain)
.filter/.sortedon small, known-size collections in simple views
Related
For architecture patterns: axiom-swiftui skill (architecture)
For performance issues: swiftui-performance-analyzer agent
For navigation architecture: swiftui-nav-auditor agent
For local Swift cleanups inside view bodies: swift-simplifier agent (it does local clarity; this auditor owns structural moves)
Frequently asked questions about SwiftUI Architecture Auditor
Similar skills
Quality Playbook Generator
Run comprehensive quality audits on any codebase.
PR Draft Summary
Automate PR summary generation for openai-agents-python.
Final Release Review
Streamline your release candidate audits with ease.
Unit Test Vue Pinia
Efficiently write and review unit tests for Vue 3 applications.
Slang Shader Expert
Optimize and integrate Slang shaders with ease.
Telemetry Standards
Ensure consistent event tracking in Supabase Studio.
