xcode-build-queue
v0.6.0
Published
Serial build queue for Xcode projects with git worktrees
Maintainers
Readme
xbq — Xcode Build Queue
Serial build queue for Xcode projects with git worktrees.
Problem
Running multiple Claude Code sessions on the same Xcode project requires separate repos, each needing its own SPM resolution and DerivedData (~8GB+ per copy). This tool eliminates that duplication by routing all builds through a single "main" repo.
How It Works
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Claude Code │ │ Claude Code │ │ Claude Code │
│ (worktree A) │ │ (worktree B) │ │ (worktree C) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ snapshot │ snapshot │ snapshot
└──────────────────┼───────────────────┘
▼
┌────────────────────┐
│ xbq (serial queue) │
│ │
│ checkout snapshot │
│ (detached HEAD) │
│ build/test via │
│ Xcode MCP or │
│ xcodebuild │
└────────┬───────────┘
▼
┌───────────┐
│ Main Repo │ ← single DerivedData
│ (warm) │ ← SPM already resolved
└───────────┘- Claude Code sessions edit code in lightweight git worktrees (code only, no builds)
- When they need to build/test, they run
xbq buildorxbq test xbqcreates a snapshot commit of all changes and checks it out via detached HEAD in the main repo- Jobs run serially to prevent DerivedData corruption
- Results are returned to the requesting session
- Each worktree gets a
CLAUDE.mdthat tells Claude Code to usexbq
Installation
npm (recommended)
npm install -g xcode-build-queueFrom GitHub
npm install -g github:a-ulkhan/xbqFrom source
git clone https://github.com/a-ulkhan/xbq.git
cd xbq
make installSetup
# Configure (point to your main Xcode repo)
xbq init ~/path/to/your/project
# Start the daemon
xbq daemon startOptional: git-restore-mtime
For best incremental build performance after branch switches:
pip3 install git-restore-mtimeFleet Management
Manage multiple parallel Claude sessions across worktrees with templates and session tracking.
# Launch a code-review session for an MR
xbq fleet launch -t code-review --mr 4521
# Launch a feature session for a Jira ticket
xbq fleet launch -t feature --ticket MOBI-12345
# Launch with a custom name and prompt
xbq fleet launch my-experiment -p "refactor the auth module"
# Check all fleet sessions
xbq fleet status
# WORKTREE STATUS TASK SINCE
# code-review-mr-4521 active Review MR !4521 12m
# feature-mobi-12345 active feature MOBI-12345 8m
# Stop a session
xbq fleet stop code-review-mr-4521Templates
Templates are user-managed JSON files in ~/.bq/fleet/templates/. Three defaults are seeded on xbq init:
| Template | Use case | Placeholders |
|----------|----------|--------------|
| code-review | MR review | {mr} |
| feature | New feature | {ticket} |
| bugfix | Bug fix | {ticket} |
Manage templates via CLI:
# List all templates
xbq fleet templates list
# Create a custom template
xbq fleet templates create refactor --prompt "Refactor {ticket}: ..."
# Edit an existing template in $EDITOR
xbq fleet templates edit bugfix
# Delete a template
xbq fleet templates delete refactor
# Re-seed defaults (only if templates directory is empty)
xbq fleet templates seedTemplate JSON format (~/.bq/fleet/templates/bugfix.json):
{
"name": "bugfix",
"prompt_prefix": "Fix Jira ticket {ticket}:\n1) Fetch ticket\n2) Trace root cause\n3) Fix\n4) Build + test\n5) Commit",
"permissions": ["Read", "Grep", "Glob"]
}Use {ticket} and {mr} as placeholders — they are substituted from --ticket and --mr flags. The permissions field is optional.
Quick Start
Start a new parallel session
# Create a worktree + launch Claude Code (all-in-one)
xbq session my-feature
# With an initial prompt (auto-submitted to Claude Code)
xbq session my-feature -p "implement login screen"
# Or create worktree only (e.g. to open in a new terminal)
xbq worktree new my-feature
# Auto-named session (timestamp-based)
xbq sessionxbq session / xbq worktree new:
- Creates a git worktree branching from the default branch
- Auto-injects
xbqinstructions into the worktree'sCLAUDE.md - Optionally launches Claude Code in the worktree
- With
-p, passes the prompt directly to Claude Code so it starts working immediately
Build and test from a worktree
# Build (changes are captured automatically via diff — no commit needed)
xbq build
# Run tests
xbq test
# With specific destination
xbq build --destination "platform=iOS Simulator,name=iPhone 16,OS=26.2"
# Specific scheme/test plan
xbq test --scheme MyScheme --test-plan All
# Run only specific test classes
xbq test --only-testing PayseraUnitTests/BankDetailsPresenterTests
# Run specific test methods
xbq test --only-testing PayseraUnitTests/BankDetailsPresenterTests/testValidInput
# Multiple targeted tests
xbq test --only-testing PayseraUnitTests/BankDetailsPresenterTests PayseraTransferSDKTests/IBANGeneratorTests
# Force xcodebuild backend
xbq build --backend xcodebuild
# Legacy branch mode (for pushed branches)
xbq build --branch feature/my-branchWorktree Management
# List all worktrees
xbq worktree list
# Clean up merged and stale worktrees (>7 days, no uncommitted changes)
xbq worktree clean
# Force remove all non-main worktrees
xbq worktree clean --force
# Custom age threshold
xbq worktree clean --days 3Cleanup rules
| Condition | Action |
|-----------|--------|
| Branch merged into default branch | Removed automatically |
| Stale (>7d) with no uncommitted changes | Removed automatically |
| Active with uncommitted work | Kept (unless --force) |
Tip: add to crontab for automatic cleanup:
0 9 * * * xbq worktree cleanClaude Code Integration
Every worktree created by xbq gets a CLAUDE.md that instructs Claude Code to:
- NEVER run
xcodebuilddirectly in the worktree - NEVER use Xcode MCP build/test tools directly
- ALWAYS use
xbq build/xbq test(changes are captured automatically)
This is automatic — no manual setup needed per session.
To manually manage the Claude integration:
# Inject xbq instructions into an existing project's CLAUDE.md
xbq setup-claude /path/to/worktree
# Remove xbq instructions
xbq setup-claude --remove /path/to/worktreeThe injection is idempotent (safe to run multiple times) and uses HTML markers to update in place.
Queue Management
# Check daemon and queue status
xbq status
# View recent job results
xbq logs
# View a specific job's full log
xbq logs 20260323-101530-abc123
# Clean old results and logs (default: 7 days)
xbq cleanDaemon
xbq daemon start # Start in background
xbq daemon stop # Stop
xbq daemon status # Check status + queue info
xbq daemon start -f # Foreground (for debugging)The daemon auto-starts when you enqueue a job if it's not already running.
Backends
Xcode MCP (default)
Uses Xcode 26.3+'s native MCP server (xcrun mcpbridge). Requires Xcode to be running with the project open. Provides richer diagnostics.
xcodebuild (fallback)
Standard CLI build tool. Works headless, no Xcode GUI needed. Auto-selected when mcpbridge is unavailable.
If MCP fails, xbq automatically falls back to xcodebuild (configurable).
Configuration
Manage settings via xbq config:
# List all settings
xbq config list
# Get a specific value
xbq config get backend
# Set a value
xbq config set backend xcodebuild
xbq config set default_destination "platform=iOS Simulator,name=iPhone 16,OS=18.0"
xbq config set xcodebuild_fallback falseAvailable keys
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| main_repo | string | "" | Path to main Xcode repo |
| workspace | string | "" | Xcode workspace name |
| default_scheme | string | "" | Default build scheme |
| default_test_scheme | string | "" | Scheme for test jobs (falls back to default_scheme if empty) |
| default_test_plan | string | "" | Default test plan |
| default_destination | string | platform=iOS Simulator,name=iPhone 16 | Simulator destination |
| backend | mcp | xcodebuild | mcp | Build backend |
| xcodebuild_fallback | boolean | true | Fall back to xcodebuild if MCP fails |
| git_restore_mtime | boolean | true | Restore file timestamps for incremental builds |
Config is stored at ~/.bq/config.json. Workspace, scheme, and backend are auto-detected during xbq init.
All Commands
| Command | Description |
|---------|-------------|
| xbq init [path] | First-time setup — set main repo path |
| xbq session [name] [-p prompt] | Create worktree + start Claude Code |
| xbq worktree new [name] | Create a new worktree |
| xbq worktree list | List all worktrees |
| xbq worktree clean | Remove merged/stale worktrees |
| xbq fleet status | Show all fleet sessions and their state |
| xbq fleet launch [name] | Create a tracked worktree session from a template |
| xbq fleet stop <name> | Mark a fleet session as stopped |
| xbq fleet templates list | List available fleet templates |
| xbq fleet templates create <name> | Create a new template |
| xbq fleet templates edit <name> | Open a template in $EDITOR |
| xbq fleet templates delete <name> | Delete a template |
| xbq fleet templates seed | Seed default templates |
| xbq build | Enqueue a build job |
| xbq test | Enqueue a test job |
| xbq status | Show daemon + queue status |
| xbq logs [job-id] | View build logs / recent results |
| xbq daemon start\|stop\|status | Manage the queue daemon |
| xbq setup-claude [dir] | Inject/update xbq instructions in CLAUDE.md |
| xbq config list | Show all config values |
| xbq config get <key> | Get a config value |
| xbq config set <key> <value> | Set a config value |
| xbq clean | Clean old results and logs |
Common flags
| Flag | Commands | Description |
|------|----------|-------------|
| -p, --prompt <prompt> | session, fleet launch | Initial prompt for Claude Code |
| -t, --template <name> | fleet launch | Template: code-review, feature, bugfix |
| --mr <iid> | fleet launch | GitLab MR IID (for code-review template) |
| --ticket <key> | fleet launch | Jira ticket key (for feature/bugfix template) |
| -b, --branch <branch> | build, test | Branch to build (optional in worktree) |
| -s, --scheme <scheme> | build, test | Xcode scheme override |
| -d, --destination <dest> | build, test | Simulator destination |
| --test-plan <plan> | test | Test plan name |
| -o, --only-testing <ids...> | test | Run only specific test identifiers (Target/Class or Target/Class/method) |
| --backend <backend> | build, test | Force mcp or xcodebuild |
| --timeout <seconds> | build, test | Job timeout (default: 1800) |
Requirements
- Node.js >= 18
- Xcode 26.3+ (for MCP backend) or any Xcode (for xcodebuild backend)
- git
- Optional:
git-restore-mtime(pip3 install git-restore-mtime)
