opencode is a coding agent you start with opencode in your Swift or iOS project root. It reads project instructions from AGENTS.md and can edit SwiftUI, UIKit, Swift Package Manager manifests, and XCTest files directly. This guide covers setup, prompts, testing, and multi-agent workflows for production iOS code. See opencode for the agent itself.
Why opencode fits Swift and iOS development
Unlike a GUI-only assistant, opencode works in the terminal next to your Xcode project, so it can use the same build and test commands you already run. That matters for iOS because xcodebuild, xcrun simctl, swift test, and SwiftLint give reproducible verification without clicking through Xcode. It reads and writes plain Swift files, including SwiftUI view builders, UIKit view controllers, actors, and async/await code, and it can reason about module boundaries and access control. Because it works from the project root, it also sees Package.swift, test targets, and asset catalogs, making it feasible to ask for a full change and have it run the relevant XCTest suite.
Making AGENTS.md work for an iOS project
The single highest-leverage step is a project-specific AGENTS.md. Keep it short and concrete: build commands, test commands, lint commands, folder layout, and rules that prevent it from damaging .xcodeproj files or violating your iOS target.
A realistic AGENTS.md for a SwiftUI app using SPM looks like this:
# AGENTS.md
## Build and test
- Build: xcodebuild -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16' build
- Run tests: xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16'
- Swift package tests: swift test
- Lint: swiftlint --strict
## Folder conventions
- MyApp/Sources/Features/ for SwiftUI screens and view models
- MyApp/Sources/Services/ for networking, persistence, and system integrations
- MyApp/Sources/Models/ for value types and domain models
- MyAppTests/ for XCTest unit tests
## Rules
- Target iOS 16 or later unless asked otherwise
- Use async/await and actors; do not introduce new callback-based APIs
- Keep SwiftUI views in their own files, named after the view
- Do not modify MyApp.xcodeproj/project.pbxproj directly; if a project file change is needed, list it in the response and wait for approval
- Before finishing a change, run the smallest relevant test target and include the command output
This file removes ambiguity about simulator destination, test scope, and coding style. If you use Tuist or XcodeGen, point the agent to the generated project and tell it to edit the YAML or Swift generator instead of the .xcodeproj file. For the agent’s general workflow, see How to use opencode: a step-by-step guide.
Working loop and example prompts for Swift and iOS tasks
Use the same loop as a careful coworker: agree on the change, make a small edit, run the focused test or build command, review the diff, then iterate. Do not ask for broad rewrites of both SwiftUI and UIKit code in one prompt.
Example prompts:
In MyApp/Sources/Features/ProfileView.swift, add a loading state driven by an async function that fetches a profile from the existing ProfileService protocol. Keep the current SwiftUI layout and add a retry button that calls the same function. Do not change navigation.Refactor MyApp/Sources/Services/APIClient.swift to use async/await. Replace the completion handlers in the three call sites under MyApp/Sources/Features/ and update their tests. Keep the public method names unless a rename is clearly safer.Add unit tests for OrderCalculator in MyAppTests/OrderCalculatorTests.swift. Cover an empty order, one item, multiple items with discounts, and rounding. Run swift test and fix any failures.Fix the retain cycle in MyApp/Sources/Services/LiveLocationService.swift. Use [weak self] where appropriate and confirm no other closure captures self strongly. Run xcodebuild test -scheme MyApp and report warnings.
After each prompt, review git diff for changes to .pbxproj, Info.plist, or entitlements before accepting.
Where opencode excels and where it struggles in Swift and iOS
The agent handles many changes well: adding SwiftUI screens, converting callback APIs to async/await, writing XCTest cases, adding SPM dependencies, moving files between targets, and fixing compiler errors. It is less reliable on Xcode project file edits, storyboard XML, code signing, and changes that depend on simulator state.
| Task | Good prompt focus | What to review closely |
|---|---|---|
| Add a SwiftUI view | Give exact file, model or service contract, iOS target | Ensure the view compiles with previews; avoid accidental ObservableObject misuse |
| Refactor to async/await | Point to call sites and tests | Check actor isolation, cancellation, and error mapping |
| Add XCTest coverage | Specify edge cases and target | Confirm tests are in the right target and use @MainActor only when needed |
| Add an SPM dependency | Give package URL and target | Review Package.resolved and version pinning; ensure no duplicate module |
| Modify UIKit code | Include file and behavior; mention Auto Layout constraints | Look for missing translatesAutoresizingMaskIntoConstraints, retain cycles, and main-thread assumptions |
Pitfalls specific to Swift and iOS:
.xcodeprojdiffs from the agent are hard to review; restrict direct edits.- SwiftUI previews may fail in CI because the agent drops
#Previewor uses unavailable APIs. - Availability: the agent may use iOS 17+ APIs when your target is iOS 16. State the minimum target.
- Concurrency: it sometimes marks types
@MainActortoo broadly, causing deadlocks or over-isolation. - ARC: closure captures can create retain cycles, especially in UIKit delegates and service callbacks.
- Tests: async tests need proper
awaitand may require@MainActorif touching SwiftUI state.
Testing and verification with XCTest and xcodebuild
Make the agent own verification, not just code generation. In the prompt, require the exact command: xcodebuild test, swift test, or swiftlint --strict. Ask it to include the command output in its response and to stop on the first failure instead of generating more changes.
For an app target, use xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16'. For SPM packages, swift test is faster and avoids simulator boot. If the project uses async/await, have the agent run tests that cover cancellation and actor isolation, not only happy paths.
Review the diff for anything that touches code signing, entitlements, Info.plist, or the .xcodeproj. Prefer git diff --stat first, then git diff for source files.
Running multiple agents on one Swift and iOS repo with AgentVera
When a single opencode session is too slow for parallel work, AgentVera runs multiple coding agents’ real command line tools, including opencode, side by side in separate terminal panels. For Swift and iOS, the most useful parts are separate git worktrees so agents do not overwrite each other’s project files, automatic code review that links findings to file:line, and checkpoints that let you undo one agent’s turn and replay it. Token budgets also help because Xcode builds and simulator tests can consume many turns quickly.
Wrap up: keeping opencode productive in an iOS team
opencode becomes a reliable Swift and iOS contributor when you give it a precise AGENTS.md, small prompts, and a hard rule to run XCTest or xcodebuild after each change. Review diffs carefully around project files and concurrency code, and use parallel agents with separate worktrees when you need more throughput. With that loop, it fits into an existing Xcode team without replacing the human review step.