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 (claude command 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 \
  build

Claude 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:

  1. Session Detail - Fixture Max
  2. Session Detail - Fixture Short
  3. Session Detail - Empty Timeline
  4. Session Detail - Text Heavy
  5. Session Detail - Tool Heavy
  6. Session 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.swift
  • apps/macos/unbound-macos/Components/ToolViews/StandaloneToolCallsView.swift
  • apps/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

SettingValue
Bundle Identifiercom.arni.unbound-macos
Development TeamLLC6TV7P6M
Code Sign StyleAutomatic
App SandboxDisabled

Entitlements

The app requires these entitlements (unbound-macos.entitlements):

com.apple.security.app-sandbox = false
com.apple.security.cs.allow-unsigned-executable-memory = true

Sandbox 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.

VariableDebug DefaultRelease Default
RELAY_URLws://localhost:8080wss://unbound-computer.fly.dev
API_URLhttp://localhost:3000https://unbound.computer
SUPABASE_URLhttp://127.0.0.1:54321(requires configuration)
SUPABASE_PUBLISHABLE_KEYLocal 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.xcconfig

To apply these values in Xcode:

  1. Open unbound-macos.xcodeproj
  2. Select the project in Navigator
  3. Go to Info tab > Configurations
  4. Under Debug, set the configuration file to Config/Debug.xcconfig

Or set environment variables directly in the scheme:

  1. Product > Scheme > Edit Scheme...
  2. Select Run > Arguments
  3. Add variables under Environment Variables:
    • RELAY_URL = ws://localhost:8080
    • API_URL = http://localhost:3000
    • SUPABASE_URL = http://127.0.0.1:54321

Keychain Storage

Service identifier: com.unbound.macos

Stored keys:

KeyPurpose
com.unbound.device.privateKeyX25519 private key (32 bytes)
com.unbound.device.publicKeyX25519 public key (32 bytes)
com.unbound.device.idDevice UUID
com.unbound.api.keyAPI authentication key
com.unbound.trusted.devicesTrusted devices list (JSON)

Cryptographic Configuration

AlgorithmPurpose
X25519Key exchange (ECDH)
HKDF-SHA256Key derivation
ChaCha20-Poly1305AEAD encryption

Key derivation contexts:

  • unbound-session-v1 - Session keys
  • unbound-message-v1 - Message encryption
  • unbound-web-session-v1 - Web viewer sessions

Device Roles

RoleDescription
trust_rootiOS device (controller)
trusted_executorMac device (this app)
temporary_viewerWeb 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

  1. Open the app and go to Settings → Devices
  2. Click "Show QR Code"
  3. Scan with Unbound iOS app
  4. QR code valid for 5 minutes

External Tools Required

The following must be installed on the system:

  1. Claude CLI - claude command must be in PATH
  2. Git - For version control operations
  3. Shell - Uses /bin/zsh (falls back to $SHELL)

Production Configuration

For release builds, you must configure:

  1. Valid Supabase production URL
  2. Supabase anonymous key (via environment or build settings)
  3. Valid Apple Developer signing certificate
Unbound macOS App