Xcode Bridge Service for containerized iOS development.
xcbridge is a lightweight HTTP service that runs on macOS and provides a REST API for Xcode operations. It enables AI agents running in Linux containers to access iOS build tooling that requires macOS and Xcode.
iOS development requires Xcode, which only runs on macOS. When AI agents run in containerized environments (typically Linux), they cannot directly access Xcode. xcbridge solves this by:
- Running as a service on the macOS host
- Exposing Xcode operations via REST API
- Allowing containers to connect via
http://host.docker.internal:9090
- Build Management: Trigger builds, stream logs, track status
- Test Execution: Run tests with real-time log streaming
- Simulator Control: Boot, shutdown, install apps, launch
- Device Management: List and interact with physical iOS devices
- Authentication: Optional API key protection
- Streaming Logs: Server-Sent Events (SSE) for real-time output
# Install globally
npm install -g @aptove/xcbridge
# Or run directly with npx
npx @aptove/xcbridge --port 9090- macOS 13 or later
- Xcode 15 or later (with command line tools)
Requires Rust 1.75+
# Clone the repository
git clone https://github.com/Aptove/xcbridge.git
cd xcbridge
# Build release binary
cargo build --release
# Install as launchd service
./scripts/install.sh# Custom port
./scripts/install.sh --port 8080
# With API key authentication
./scripts/install.sh --api-key my-secret-key
# Both
./scripts/install.sh --port 8080 --api-key my-secret-key./scripts/uninstall.sh# Default settings (port 9090)
xcbridge
# Custom port
xcbridge --port 8080
# With API key
xcbridge --api-key your-secret-key
# Verbose logging
xcbridge --log-level debug# Check status
curl http://host.docker.internal:9090/status
# Start a build
curl -X POST http://host.docker.internal:9090/build \
-H "Content-Type: application/json" \
-d '{"project_path": "/path/to/project", "scheme": "MyApp"}'
# Stream build logs
curl http://host.docker.internal:9090/build/{build_id}/logsGET /status
Returns service status and Xcode version.
Response:
{
"status": "healthy",
"version": "0.1.0",
"xcode_version": "15.2"
}POST /build
Request Body:
{
"project_path": "/path/to/MyApp.xcodeproj",
"scheme": "MyApp",
"configuration": "Debug",
"destination": "platform=iOS Simulator,name=iPhone 15",
"derived_data_path": "/tmp/DerivedData"
}Response:
{
"build_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "running",
"started_at": "2024-01-15T10:30:00Z"
}GET /build/{build_id}
GET /build/{build_id}/logs
DELETE /build/{build_id}
POST /test
Request Body:
{
"project_path": "/path/to/MyApp.xcodeproj",
"scheme": "MyAppTests",
"destination": "platform=iOS Simulator,name=iPhone 15"
}GET /test/{test_id}
GET /test/{test_id}/logs
GET /simulator/list
Response:
{
"simulators": [
{
"udid": "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
"name": "iPhone 15",
"state": "Shutdown",
"runtime": "iOS 17.2"
}
]
}POST /simulator/boot
Request Body:
{
"udid": "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"
}POST /simulator/shutdown
POST /simulator/install
Request Body:
{
"udid": "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
"app_path": "/path/to/MyApp.app"
}POST /simulator/launch
Request Body:
{
"udid": "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE",
"bundle_id": "com.example.MyApp"
}POST /simulator/uninstall
GET /device/list
POST /device/install
POST /device/launch
POST /device/uninstall
When running with --api-key, all requests must include the X-API-Key header:
curl -H "X-API-Key: your-secret-key" http://localhost:9090/status| Option | Environment Variable | Default | Description |
|---|---|---|---|
--port |
XCBRIDGE_PORT |
9090 | Port to listen on |
--host |
XCBRIDGE_HOST |
127.0.0.1 | Host to bind to |
--api-key |
XCBRIDGE_API_KEY |
- | API key for authentication |
--log-level |
XCBRIDGE_LOG_LEVEL |
info | Log level (trace, debug, info, warn, error) |
When using Docker, access xcbridge from containers using host.docker.internal:
# docker-compose.yml
services:
agent:
image: swift:5.9-jammy
environment:
XCBRIDGE_URL: http://host.docker.internal:9090
extra_hosts:
- "host.docker.internal:host-gateway"- Network Binding: By default, xcbridge binds to
127.0.0.1(localhost only) - API Key: Use
--api-keyin production environments - Path Restrictions: Consider using
--allowed-pathsto restrict file system access
Check logs:
tail -f ~/Library/Logs/xcbridge.log
tail -f ~/Library/Logs/xcbridge.error.logEnsure Xcode is installed and command line tools are configured:
xcode-select -p
xcodebuild -versionVerify the service is running:
curl http://localhost:9090/statusCheck Docker networking:
# From inside container
curl http://host.docker.internal:9090/statuscargo testcargo build --releaseThe binary will be at target/release/xcbridge.
Apache License 2.0. See LICENSE for details.
Contributions are welcome! Please read our contributing guidelines before submitting PRs.