Skip to content
Mobile
Skill

/axiom-audit-swiftui-architecture

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

From plugin
axiom
1.3k71 skills44 agents18 commands1 MCP

Claude Code

$ npx -y skills add charleswiltgen/axiom --skill axiom-audit-swiftui-architecture --agent claude-code

SKILL.md

axiom-audit-swiftui-architecture.SKILL.md
name: axiom-audit-swiftui-architecture
description: Use when the user mentions SwiftUI architecture review, separation of concerns, testability issues, or "logic in view" problems.
license: MIT

SwiftUI 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` — modern observable models (the `class` or `final class` is often on the line after the attribute; read before counting)
  - `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 {`, `.task {` in files with `var body` — async work in views
  - `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 { }` or a `.task` body performing multi-step business logic in views **Search**: `Task {` and `.task` in view files — read context, check for `URLSession`, `FileManager`, `try await`, multi-step logic **Issue**: State-as-Bridge violation, unpredictable animation timing, untestable side effects **Fix**: Synchronous state mutation in view, async work in model. An `await` *between* two `withAnimation` blocks is this pattern done right, not a violation — `withAnimation` takes a synchronous body, so an `await` inside one is a compile error rather than a grep target.

3. Property Wrapper Misuse (HIGH)

**Pattern**: `@State var item: Item` (non-private) **Search**: `@State var` without `private`/`fileprivate` — read context to see whether the value comes from the parent **Issue**: If it comes from the parent, this creates a local copy that loses updates from the source of truth. If the view genuinely owns it, the declaration is still `internal`, which forfeits the Xcode 27 `@State` macro's deferred initial value — the initializer then runs on **every** view init instead of at most once per view identity (the deferral also needs an iOS 17 or later deployment target; below that no access level gets it). `private(set)` does not help; its getter is internal. **Fix**: Parent-owned → `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. View-owned → add `private`.

4. God ViewModel (MEDIUM)

**Pattern**: `@Observable` or `ObservableObject` class with >20 stored properties or mixing unrelated domains **Search**: `@Observable`, `ObservableObject` — read the class (the `class` keyword may be on the next line), 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

Read more
@charleswiltgen
Ships withaxiom

Battle-tested skills, agents, and tools for modern Apple OS development — Swift 6, SwiftUI, Liquid Glass, Apple Intelligence, and more. Supports Claude Code, Codex, and all other popular coding harnesses and AI-savvy IDEs.

1.3k71 skills44 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.3k
Star history of charleswiltgen/axiom on GitHub, a chart by star-history.com

Other skills on axiom.

axiom-accessibility

axiom-accessibility

Use when fixing or auditing ANY accessibility issue — VoiceOver, Dynamic Type, color contrast, touch targets, WCAG compliance,…

axiom-ai

axiom-ai

Use when implementing, testing, or evaluating ANY Apple Intelligence, on-device AI, or speech-to-text feature. Covers Foundation…

axiom-analyze-crash

axiom-analyze-crash

Use when the user has a crash log (.ips, MetricKit JSON, legacy .crash text, .xccrashpoint bundle, or pasted text) that needs…

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo4d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens3w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about axiom-audit-swiftui-architecture.

Which coding agents can use axiom-audit-swiftui-architecture?
axiom-audit-swiftui-architecture installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.