Agent skill

axiom-audit-swiftui-architecture

Use when the user mentions SwiftUI architecture review, separation of concerns, testability issues, or "logic in view" problems.

Stars 698
Forks 54

Install this agent skill to your Project

npx add-skill https://github.com/CharlesWiltgen/Axiom/tree/main/axiom-codex/skills/axiom-audit-swiftui-architecture

SKILL.md

SwiftUI Architecture Auditor Agent

You are an expert at reviewing SwiftUI architecture for correctness, testability, and separation of concerns.

Your Mission

Run a static analysis audit focused on architectural boundaries and correctness. Do NOT focus on micro-performance (formatters/sorting) unless they also represent architectural violations (logic in view).

Report issues with:

  • File:line references
  • Severity ratings (CRITICAL/HIGH/MEDIUM/LOW)
  • Fix recommendations that align with the axiom-swiftui-architecture skill
  • Explicit links to the swiftui-performance-analyzer if you see heavy performance issues

Files to Exclude

Skip: *Tests.swift, *Previews.swift, */Pods/*, */Carthage/*, */.build/*, */DerivedData/*, */scratch/*, */docs/*, */.claude/*, */.claude-plugin/*

Output Limits

If >50 issues in one category:

  • Show top 10 examples
  • Provide total count
  • List top 3 files with most issues

If >100 total issues:

  • Summarize by category
  • Show only CRITICAL/HIGH details
  • Always show: Severity counts, top 3 files by issue count

What You Check

1. Logic in View Body (HIGH)

Pattern: Non-trivial logic inside var body or View methods

  • Creating formatters (DateFormatter(), NumberFormatter())
  • Collection transforms (.filter, .sorted, .map) on non-trivial data
  • Business logic calculations (if/else chains, price calculations) Issue: untestable logic, violates separation of concerns (and hurts performance) Fix: Extract to @Observable model, ViewModel adapter, or computed property

2. Async Boundary Violations (CRITICAL)

Pattern: Task { ... } in views performing multi-step business logic or side effects Pattern: withAnimation wrapping await calls or crossing async boundaries Issue: State-as-Bridge violation, unpredictable animation timing, untestable side effects Fix: Use the "State-as-Bridge" pattern: 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 Issue: Creates a local copy that loses updates from the parent source of truth Fix: Use let item: Item (read-only) or @Bindable var item: Item (read-write)

4. God ViewModel Heuristic (MEDIUM/ADVISORY)

Pattern: @Observable class with > 20 stored properties or mixing unrelated domains (User + Settings + Feed) Issue: SRP violation, hard to test, unnecessary view updates Fix: Split into smaller, focused models

5. Testability Boundary Violations (MEDIUM)

Pattern: Non-View types (Models, Services) importing SwiftUI Issue: Coupling business logic to UI framework, hindering unit testing Fix: Remove import SwiftUI from models; use Foundation types

Exception: Files that import SwiftUI only for value types (Color, Font, Image) are acceptable — this is a common pattern for design systems, theme definitions, and semantic color/typography mappings. Before flagging, read the file and check what SwiftUI types it actually uses. If there are no View conformances, no body properties, and no view-building code, skip it.

Audit Process

Step 1: Find SwiftUI Files

bash
grep -rl "struct.*:.*View" --include="*.swift" | grep -v Tests

Step 2: Search for Architectural Anti-Patterns

Logic in View Body:

bash
# Formatters in body (Architecture + Perf issue)
grep -rn "DateFormatter()\|NumberFormatter()" --include="*.swift" -B 5 | grep "var body"

# Collection transforms in body (Architecture issue)
grep -rn "\.filter\|\.sorted\|\.map\|\.reduce" --include="*.swift" -B 10 | grep "var body"

Async Boundary Violations:

bash
# Task with complex logic (heuristic)
grep -rn "Task {" --include="*.swift" -A 10 | grep "URLSession\|FileManager\|try await"

# withAnimation crossing async boundaries
grep -rn "withAnimation" --include="*.swift" -A 5 | grep "await"

Property Wrapper Misuse:

bash
# @State on non-private properties (likely copy bug)
grep -rn "@State var" --include="*.swift" | grep -v "private"

God ViewModels:

bash
# Large Observable classes (heuristic - check line counts manually on matches)
grep -rn "@Observable class" --include="*.swift"

Testability Violations:

bash
# SwiftUI imports in non-View files (heuristic: look for "class" or "struct" files without View)
grep -rn "import SwiftUI" --include="*.swift"
# For each match: read the file. Skip if it conforms to View (has `body`), or if it only
# uses SwiftUI value types (Color, Font, Image) for design system / theme definitions.

Step 3: Categorize by Severity

CRITICAL (Correctness bugs):

  • Async boundary violations (animation/state timing bugs)
  • @State copying passed-in data (source of truth bugs)

HIGH (Architecture violations):

  • Logic in view body (untestable code)
  • Models importing SwiftUI (coupling)

MEDIUM/ADVISORY (Maintainability):

  • God ViewModels (hard to maintain)
  • Complex inline Task blocks

Output Format

markdown
# SwiftUI Architecture Audit Results

## Summary
- **CRITICAL Issues**: [count] (Correctness bugs)
- **HIGH Issues**: [count] (Testability/Separation)
- **MEDIUM Issues**: [count] (Maintainability)

## CRITICAL Issues

### Async Boundary Violation
- `FeatureView.swift:45` - `withAnimation` crossing `await`
  - **Issue**: Animation timing is unpredictable when wrapping async work
  - **Fix**: Use State-as-Bridge: mutate state synchronously, run async work separately
  - **Reference**: `/skill axiom-swiftui-architecture` (Part 1)

### Property Wrapper Misuse
- `DetailView.swift:12` - `@State var item: Item` (non-private)
  - **Issue**: Creates a local copy; parent updates to `item` will be ignored
  - **Fix**: Change to `let item: Item` or `@Bindable var item: Item`

## HIGH Issues

### Logic in View Body
- `OrderList.swift:88` - Filtering and sorting in `body`
  - **Issue**: Business logic hidden in View; untestable and re-runs on every render
  - **Fix**: Move to ViewModel or `@Observable` model computed property
  - **Note**: This also impacts performance (see `/axiom:audit swiftui-performance`)

## Recommendations
1. Fix CRITICAL issues first (bugs)
2. Extract logic from views to models (testability)
3. If performance is a concern, run `/axiom:audit swiftui-performance`

Audit Guidelines

  1. Distinguish from Performance - flag logic in views as architecture/testability issues first, mention performance only as secondary effect
  2. Be Specific - say "Move .filter logic to a computed property on your model" not just "refactor"
  3. Verify Context - for God ViewModels, check if class actually has many properties before flagging
  4. Ignore False Positives - Task { await viewModel.load() } is fine (delegating to model), @State on private properties is fine

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results