Swift · SwiftUI

SwiftUI (iOS) rules for Cursor

Observation, navigation and concurrency rules that stop agents from writing outdated SwiftUI.

The rule

Save as .cursor/rules/swiftui.mdc. Cursor picks it up on the next request.

.cursor/rules/swiftui.mdc

---
description: SwiftUI app conventions
globs: **/*.swift
alwaysApply: false
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.

How Cursor loads this rule

Read from the frontmatter above, per Cursor's rules documentation.

  • alwaysApply: false with globs: **/*.swift: attached automatically when a matching file is in context.
  • Keep the .mdc extension. A plain .md file in .cursor/rules is ignored by the rules system.
  • Prefer to generate your own? Type /create-rule in Agent and describe what you want; Cursor saves the file to .cursor/rules.
  • Team Rules come first, then Project Rules like this one, then User Rules. Earlier sources win when guidance conflicts.

Cursor rules setup guideCursor Team RulesLet Cursor run commands without asking

SwiftUI (iOS) rules for Claude Code, Copilot, Kiro and other agents

The same instructions work as plain Markdown in AGENTS.md, which Codex, Gemini CLI, GitHub Copilot and most other coding agents read.

AGENTS.md (section)

## SwiftUI (iOS)

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for Claude Code.claude/rules/swiftui.md

.claude/rules/swiftui.md

---
paths:
  - "**/*.swift"
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for GitHub Copilot.github/instructions/swiftui.instructions.md

.github/instructions/swiftui.instructions.md

---
applyTo: "**/*.swift"
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for Kiro.kiro/steering/swiftui.md

.kiro/steering/swiftui.md

---
inclusion: fileMatch
fileMatchPattern: ["**/*.swift"]
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for Antigravity.agents/rules/swiftui.md

.agents/rules/swiftui.md

---
trigger: glob
globs: "**/*.swift"
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for Devin Desktop (Windsurf).devin/rules/swiftui.md

.devin/rules/swiftui.md

---
trigger: glob
globs: **/*.swift
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for Cline.clinerules/swiftui.md

.clinerules/swiftui.md

---
paths:
  - "**/*.swift"
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.
SwiftUI (iOS) rules for Continue.continue/rules/swiftui.md

.continue/rules/swiftui.md

---
name: "swiftui"
globs: ["**/*.swift"]
---

- Use the @Observable macro for model classes instead of ObservableObject and @Published.
- Own observable models with @State, pass them down as plain properties, and use @Bindable when a child needs bindings.
- Use NavigationStack (or NavigationSplitView) with value-based navigationDestination, never NavigationView.
- Use .foregroundStyle instead of .foregroundColor.
- Start async work with the .task modifier, not Task inside onAppear; it cancels when the view disappears.
- Use async/await instead of completion handlers, and keep UI state updates on the main actor.
- Keep views small and extract subviews; avoid AnyView.
- Use SF Symbols, Dynamic Type text styles and accessibility labels on icon-only buttons.
- Write new tests with Swift Testing (@Test, #expect) unless the project uses XCTest.

Edit this rule and convert it for 11 agents →

More templates

Get Cursor rules and settings changes by email

When Cursor changes how rules, run modes or settings work, we update these templates from the docs and send a short note. One email a week at most.

Reviewed Oct 20, 2026. Written by AgentAtlas. Adapt it to your codebase before relying on it.