A native macOS and iOS client for OpenCode, providing a SwiftUI-based interface for AI-powered coding assistance with real-time streaming, session management, and project-aware interactions.
- Cross-Platform: Native support for both macOS (14.0+) and iOS (17.0+)
- Real-Time Streaming: Server-Sent Events (SSE) for live updates
- Session Management: Create, manage, and navigate between multiple chat sessions
- Project-Aware: Directory-based context with automatic file tracking
- Agent Selection: Switch between different AI agents and models
- Task Management: Inline TODO task tracking and management
- Permissions System: Granular control over file operations and command execution
- Background Support: Notifications and background processing for long-running operations
- macOS: 14.0 (Sonoma) or later
- iOS: 17.0 or later
- Xcode: 15.0 or later (for Xcode-based workflows)
- Swift: 6.2 or later
- XcodeGen: For generating Xcode projects (install via Homebrew:
brew install xcodegen) - OpenCode: A running OpenCode server and CLI instance
-
Clone the repository:
git clone https://github.com/Qard/opencode-swift.git cd opencode-swift -
Resolve dependencies:
swift package resolve
-
Build the project:
swift build
Note: The .xcodeproj file is not tracked in git. Use XcodeGen to generate it when needed (see below).
This project uses XcodeGen to generate the Xcode project from project.yml. The .xcodeproj file is gitignored to avoid merge conflicts.
-
Install XcodeGen (if not already installed):
brew install xcodegen
-
Generate the Xcode project:
xcodegen
-
Open the generated project:
open OpenCode.xcodeproj
Build the macOS app using xcodebuild:
# Generate Xcode project first (if needed)
xcodegen
# Build for macOS
xcodebuild -project OpenCode.xcodeproj \
-scheme "OpenCode macOS" \
-configuration Debug \
-derivedDataPath .build
# The app bundle will be at:
# .build/Build/Products/Debug/OpenCode.appRun the development build:
open .build/Build/Products/Debug/OpenCode.appOr install to Applications:
cp -r .build/Build/Products/Debug/OpenCode.app /Applications/First, create ExportOptions-macOS.plist with your team ID:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>developer-id</string>
<key>teamID</key>
<string>YOUR_TEAM_ID</string>
</dict>
</plist>For Mac App Store distribution, use <string>app-store</string> instead of developer-id.
Then build and export the release version:
xcodebuild -project OpenCode.xcodeproj \
-scheme "OpenCode macOS" \
-configuration Release \
-derivedDataPath .build \
archive \
-archivePath .build/OpenCode-macOS.xcarchive
# Export the archive
xcodebuild -exportArchive \
-archivePath .build/OpenCode-macOS.xcarchive \
-exportPath .build/Release \
-exportOptionsPlist ExportOptions-macOS.plist# Install create-dmg if needed
brew install create-dmg
# Create DMG from built app
create-dmg \
--volname "OpenCode" \
--window-pos 200 120 \
--window-size 600 400 \
--icon-size 100 \
--icon "OpenCode.app" 175 190 \
--app-drop-link 425 185 \
"OpenCode.dmg" \
".build/Build/Products/Release/OpenCode.app"If you prefer using Xcode:
- Generate the project:
xcodegen - Open
OpenCode.xcodeproj - Select "OpenCode macOS" scheme
- Choose "My Mac" as the destination
- Press Cmd+R to build and run
Build for iOS simulator:
# Generate Xcode project first (if needed)
xcodegen
# Build for iOS Simulator
xcodebuild -project OpenCode.xcodeproj \
-scheme "OpenCode iOS" \
-configuration Debug \
-sdk iphonesimulator \
-derivedDataPath .build
# Install to simulator
xcrun simctl install booted .build/Build/Products/Debug-iphonesimulator/OpenCode.app
# Launch the app
xcrun simctl launch booted com.opencode.app.iosBuild for physical device:
# Build for device
xcodebuild -project OpenCode.xcodeproj \
-scheme "OpenCode iOS" \
-configuration Debug \
-sdk iphoneos \
-derivedDataPath .build \
CODE_SIGN_IDENTITY="iPhone Developer" \
DEVELOPMENT_TEAM="YOUR_TEAM_ID"
# Install via command line (requires device connected)
ios-deploy --bundle .build/Build/Products/Debug-iphoneos/OpenCode.appNote: ios-deploy can be installed via Homebrew: brew install ios-deploy
First, create ExportOptions-iOS.plist with your team ID:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<key>teamID</key>
<string>YOUR_TEAM_ID</string>
<key>uploadSymbols</key>
<true/>
</dict>
</plist>For TestFlight distribution, use <string>ad-hoc</string> or <string>enterprise</string> as appropriate.
Then archive and export for App Store:
# Archive
xcodebuild -project OpenCode.xcodeproj \
-scheme "OpenCode iOS" \
-configuration Release \
-sdk iphoneos \
-derivedDataPath .build \
archive \
-archivePath .build/OpenCode-iOS.xcarchive
# Export for App Store
xcodebuild -exportArchive \
-archivePath .build/OpenCode-iOS.xcarchive \
-exportPath .build/Release \
-exportOptionsPlist ExportOptions-iOS.plistUpload to App Store Connect:
# Upload the IPA
xcrun altool --upload-app \
--type ios \
--file .build/Release/OpenCode.ipa \
--username "YOUR_APPLE_ID" \
--password "@keychain:AC_PASSWORD"If you prefer using Xcode:
- Generate the project:
xcodegen - Open
OpenCode.xcodeproj - Select "OpenCode iOS" scheme
- Choose your iOS device or simulator
- Press Cmd+R to build and run
Run all tests:
swift testRun tests for a specific platform using xcodebuild:
# macOS tests
xcodebuild test -project OpenCode.xcodeproj \
-scheme "OpenCode macOS" \
-destination 'platform=macOS'
# iOS tests (simulator)
xcodebuild test -project OpenCode.xcodeproj \
-scheme "OpenCode iOS" \
-destination 'platform=iOS Simulator,name=iPhone 15'Press Cmd+U to run tests in Xcode.
On first launch, configure your OpenCode server:
- Open the app
- Navigate to Settings (macOS: Cmd+,, iOS: tap gear icon)
- Add a new server configuration:
- Display Name: Friendly name for your server
- Host: Server hostname or IP address
- Port: Server port (default: 3000)
- Use HTTPS: Enable if server uses SSL/TLS
- Password: Optional server password
Each session can be associated with a specific working directory:
- Create a new session
- Specify the directory path when prompted
- The app will use this directory for file operations and context
- AppState: Central state management for connections, sessions, and events
- SSEClient: Real-time event streaming from the server
- OpenCodeAPIClient: REST API client for server communication
- SessionTasksManager: Background task coordination
- NotificationService: User notifications for background events
- ChatSession: Conversation sessions with message history
- ServerConfiguration: Server connection settings
- UserMessage/AssistantMessage: Message types with rich content
- TodoTask: Task tracking with status and priority
- PermissionRequest: File and command permission requests
- RootView: Main application entry point
- MainNavigationView: Primary navigation and layout
- ChatView: Message display and interaction
- ConfigurationView: Server and settings management
OpenCode/
├── OpenCodeApp.swift # App entry point
├── Models/ # Data models and types
│ ├── API/ # API request/response types
│ ├── Parts/ # Message part types
│ └── *.swift # Core models
├── ViewModels/ # State management
│ ├── AppState.swift # Main app state
│ ├── ChatViewModel.swift # Chat logic
│ └── *.swift # Other view models
├── Views/ # SwiftUI views
│ ├── Chat/ # Chat interface
│ ├── Configuration/ # Settings UI
│ ├── Screens/ # Main screens
│ └── Shared/ # Reusable components
├── Services/ # API and services
│ ├── OpenCodeAPIClient.swift
│ ├── SSEClient.swift
│ └── *.swift
└── Utilities/ # Helper functions
OpenCodeTests/ # Unit tests
project.yml # XcodeGen project configuration
Package.swift # Swift Package Manager manifest
The project uses project.yml to define:
- Build settings and Swift 6 features
- Platform-specific targets (iOS and macOS)
- Dependencies and frameworks
- Info.plist and entitlements
- Test targets and schemes
To regenerate the Xcode project after modifying project.yml:
xcodegenThis project follows standard Swift conventions:
- Use SwiftFormat for formatting:
swiftformat . - Use SwiftLint for linting:
swiftlint - Follow the one-type-per-file structure (see CLAUDE.md)
- EventSource: SSE client for real-time events
- SwiftTreeSitter: Syntax tree parsing library
- TreeSitterLanguages: Language-specific Tree-sitter grammars
Dependencies are managed via Swift Package Manager and declared in both Package.swift and project.yml.
If you encounter build issues:
# Clean Swift Package Manager build
rm -rf .build
# Clean derived data (if using Xcode)
rm -rf ~/Library/Developer/Xcode/DerivedData
# Regenerate Xcode project
xcodegen
# Re-resolve dependencies
swift package resolveContributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes with clear messages
- Push to your branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Write tests for new functionality
- Follow the existing code organization patterns
- Update documentation for API changes
- Ensure builds pass on both macOS and iOS
- Run SwiftLint before committing
- Regenerate the Xcode project if modifying
project.yml
- Verify the server is running and accessible
- Check firewall settings allow connections
- Ensure the server URL and port are correct
- Try disabling HTTPS if using a local server
- Ensure XcodeGen is installed:
brew install xcodegen - Regenerate the Xcode project:
xcodegen - Clean build folder:
rm -rf .build - Delete derived data:
rm -rf ~/Library/Developer/Xcode/DerivedData - Update dependencies:
swift package update - Ensure Xcode and Swift are up to date
The .xcodeproj file is not tracked in git. Generate it with:
xcodegen- Check that the app has necessary permissions in System Settings (macOS)
- Verify server permissions for file operations
- Review permission prompts in the app
This project is licensed under the MIT License - see the LICENSE file for details.
- OpenCode - The OpenCode server and CLI
For issues, questions, or contributions:
- Open an issue on GitHub
- Check existing issues for known problems
- Review the OpenCode server documentation for API details