Unbound macOS App
Unbound macOS App
Native macOS application for running Claude Code sessions with remote viewing capabilities.
Prerequisites
- Xcode 15.1+
- macOS 15.7+ (deployment target)
- Claude CLI installed (
claudecommand in PATH) - Git installed
Build & Run
# Open in Xcode
open unbound-macos.xcodeproj
# Or build from command line
xcodebuild -project unbound-macos.xcodeproj \
-scheme unbound-macos \
-configuration Debug \
buildClaude Parser Contract
Canonical parser + live-stream behavior is documented in:
apps/macos/unbound-macos/Services/Session/PARSER_CONTRACT.md
Use that document for:
- behavior matrix and parser invariants
- historical/live parity expectations
- typed state to UI component mapping
- fixture and preview validation workflow
Session Detail Canvas Previews
SessionDetailView includes six Xcode Canvas previews:
Session Detail - Fixture MaxSession Detail - Fixture ShortSession Detail - Empty TimelineSession Detail - Text HeavySession Detail - Tool HeavySession Detail - Status Variants
The preview suite keeps one exported fixture and derives short/empty/status variants in Swift, while text/tool-heavy scenarios use synthetic preview data.
Tool/sub-agent component preview matrices are maintained in:
apps/macos/unbound-macos/Components/ToolViews/SubAgentView.swiftapps/macos/unbound-macos/Components/ToolViews/StandaloneToolCallsView.swiftapps/macos/unbound-macos/Components/ToolUseView.swift
The base fixture-backed scenarios use:
unbound-macos/Resources/PreviewFixtures/session-detail-max-messages.json
Regenerate the fixture from the macOS SQLite database (run from repository root):
./apps/ios/scripts/export_max_session_fixture.sh \
"<db-path>" \
"apps/macos/unbound-macos/Resources/PreviewFixtures/session-detail-max-messages.json"Example with the default local database path:
./apps/ios/scripts/export_max_session_fixture.sh \
"$HOME/Library/Application Support/com.unbound.macos/unbound.sqlite" \
"apps/macos/unbound-macos/Resources/PreviewFixtures/session-detail-max-messages.json"Bundle Configuration
| Setting | Value |
|---|---|
| Bundle Identifier | com.arni.unbound-macos |
| Development Team | LLC6TV7P6M |
| Code Sign Style | Automatic |
| App Sandbox | Disabled |
Entitlements
The app requires these entitlements (unbound-macos.entitlements):
com.apple.security.app-sandbox = false
com.apple.security.cs.allow-unsigned-executable-memory = trueSandbox is disabled to allow:
- Shell execution for Claude CLI
- Process spawning
- File system access for git operations
Environment Variables (Runtime)
Set these to override default URLs. Can be configured in Xcode scheme or system environment.
| Variable | Debug Default | Release Default |
|---|---|---|
RELAY_URL | ws://localhost:8080 | wss://unbound-computer.fly.dev |
API_URL | http://localhost:3000 | https://unbound.computer |
SUPABASE_URL | http://127.0.0.1:54321 | (requires configuration) |
SUPABASE_PUBLISHABLE_KEY | Local demo key | (requires configuration) |
Local Development Configuration
For easy local configuration, use the xcconfig template:
# Copy the template
cp Config/Debug.xcconfig.template Config/Debug.xcconfig
# Edit with your local values
open Config/Debug.xcconfigTo apply these values in Xcode:
- Open
unbound-macos.xcodeproj - Select the project in Navigator
- Go to Info tab > Configurations
- Under Debug, set the configuration file to
Config/Debug.xcconfig
Or set environment variables directly in the scheme:
- Product > Scheme > Edit Scheme...
- Select Run > Arguments
- Add variables under Environment Variables:
RELAY_URL=ws://localhost:8080API_URL=http://localhost:3000SUPABASE_URL=http://127.0.0.1:54321
Keychain Storage
Service identifier: com.unbound.macos
Stored keys:
| Key | Purpose |
|---|---|
com.unbound.device.privateKey | X25519 private key (32 bytes) |
com.unbound.device.publicKey | X25519 public key (32 bytes) |
com.unbound.device.id | Device UUID |
com.unbound.api.key | API authentication key |
com.unbound.trusted.devices | Trusted devices list (JSON) |
Cryptographic Configuration
| Algorithm | Purpose |
|---|---|
| X25519 | Key exchange (ECDH) |
| HKDF-SHA256 | Key derivation |
| ChaCha20-Poly1305 | AEAD encryption |
Key derivation contexts:
unbound-session-v1- Session keysunbound-message-v1- Message encryptionunbound-web-session-v1- Web viewer sessions
Device Roles
| Role | Description |
|---|---|
trust_root | iOS device (controller) |
trusted_executor | Mac device (this app) |
temporary_viewer | Web browser viewers |
Dependencies
System Frameworks:
- Foundation, SwiftUI, AppKit
- CryptoKit (encryption)
- Security (Keychain)
- CoreImage (QR code generation)
- Combine (reactive programming)
Third-party (Swift Package Manager):
- SwiftTerm - Terminal emulation
Pairing with iOS
- Open the app and go to Settings → Devices
- Click "Show QR Code"
- Scan with Unbound iOS app
- QR code valid for 5 minutes
External Tools Required
The following must be installed on the system:
- Claude CLI -
claudecommand must be in PATH - Git - For version control operations
- Shell - Uses
/bin/zsh(falls back to$SHELL)
Production Configuration
For release builds, you must configure:
- Valid Supabase production URL
- Supabase anonymous key (via environment or build settings)
- Valid Apple Developer signing certificate