Orbit is a CLI tool that orchestrates AI coding agents to implement spec phases sequentially. It handles session lifecycle, error recovery, and log management.
Orbit solves the problem of running AI coding agents through multiple implementation phases without manual intervention. It:
- Supports multiple AI agents: Claude Code, OpenAI Codex, AWS Kiro, GitHub Copilot, and OpenCode
- Automatically detects tasks from your git branch
- Runs agents in non-interactive mode for each phase
- Handles rate limits and connection errors with appropriate retries
- Saves session logs for debugging and auditing
- Supports multi-variant comparison runs to evaluate different implementations
go install github.com/arjenschwarz/orbit/cmd/orbit@latest- At least one AI coding agent installed and authenticated:
- Claude Code CLI (default)
- OpenAI Codex
- AWS Kiro
- GitHub Copilot CLI
- OpenCode - open-source AI coding agent supporting multiple LLM providers
- rune CLI installed
- Git repository with a spec containing a tasks file
# From project root on a feature branch (auto-detects tasks file)
cd /path/to/project
git checkout feature/my-feature
orbit # Detects specs/my-feature/tasks.md automatically
# With explicit tasks file
orbit --tasks-file specs/my-feature/tasks.md
# With options
orbit --verbose --log-dir ./logs
# Preview without executing
orbit --dry-run
# With custom commands
orbit --command "Run /next-task --phase" --post-command "Run all tests"
# Skip the post-completion review
orbit --no-post-command| Flag | Default | Description |
|---|---|---|
--tasks-file |
auto-detect | Path to rune tasks file |
--log-dir |
.orbit next to tasks file |
Base directory for session logs |
--verbose |
false |
Enable verbose output |
--debug |
false |
Enable debug logging (detailed CLI execution info) |
--dry-run |
false |
Show what would be executed without running |
--command |
see below | Custom prompt for agent phases |
--post-command |
see below | Command to run after all tasks complete |
--no-post-command |
false |
Skip the post-completion command |
--date-subdirs |
false |
Use date-based subdirectories for logs |
--no-continue-session |
false |
Start fresh sessions instead of resuming |
--version |
- | Show version and exit |
| Flag | Default | Description |
|---|---|---|
--agent |
claude-code |
Agent to use: claude-code, codex, kiro, copilot, opencode |
| Flag | Default | Description |
|---|---|---|
--variants |
0 |
Number of implementation variants to run (0 = single-run mode) |
--variant-agents |
- | Comma-separated agent list for variants (cycles if fewer than variants) |
--parallel |
false |
Run variants in parallel |
--max-parallel |
3 |
Maximum concurrent variants |
--branch-prefix |
orbit-impl |
Branch naming prefix for variants |
--guidance-file |
- | YAML file with per-variant guidance |
--compare-command |
- | Custom comparison command |
The default phase command is:
Run /next-task --phase and when complete run /commit
The default post-completion command is:
Review the implementation to verify it meets the requirements and all tests pass. If issues are found, fix them.
Orbit supports configuration via YAML files and environment variables.
Orbit loads configuration from two locations (in order of priority):
- Project config:
.orbit.yamlin the current directory - Home config:
~/.orbit.yamlin your home directory
Create a default configuration with:
orbit initExample .orbit.yaml:
command: "Run /next-task --phase and when complete run /commit"
post-command: "Run tests and verify everything works"
date_subdirs: false # Use flat .orbit/ directory (default)
continue_session: true # Resume unfinished sessions (default)
agent: claude-code # Default agent alias
# Agent aliases - each combines an agent type with configuration
agents:
claude-code:
type: claude-code # Required: underlying agent type
auto-approve: true # Tool approval behavior (default: true)
timeout: 30m # Execution timeout
codex:
type: codex # Required: underlying agent type
timeout: 1h
kiro:
type: kiro # Required: underlying agent type
timeout: 1h
copilot:
type: copilot # Required: underlying agent type
# Agent aliases can also specify models for per-variant model selection
# claude-sonnet:
# type: claude-code
# model: claude-sonnet-4-20250514
# claude-opus:
# type: claude-code
# model: claude-opus-4-20250514By default, auto-approve is enabled (true) for all agents. This allows Orbit to run agents non-interactively without prompting for tool approvals.
Each agent uses its equivalent auto-approval flag:
| Agent | Flag Used |
|---|---|
| Claude Code | --dangerously-skip-permissions |
| Codex | --full-auto |
| Kiro | --trust-all-tools |
| Copilot | --yolo (equivalent to --allow-all-tools --allow-all-paths --allow-all-url) |
| OpenCode | N/A (works non-interactively without explicit flag) |
To disable auto-approval for a specific agent (requiring manual tool approval):
agents:
claude-code:
auto-approve: falseTo disable the post-completion command in config, set it to an empty string:
post-command: ""To use date-based subdirectories (legacy mode):
date_subdirs: true| Variable | Description |
|---|---|
ORBIT_COMMAND |
Override the phase command |
ORBIT_POST_COMMAND |
Override the post-completion command (empty string disables) |
ORBIT_DATE_SUBDIRS |
Use date-based subdirectories (true/false) |
ORBIT_CONTINUE_SESSION |
Enable session continuation (true/false) |
ORBIT_AGENT |
Default agent to use |
Setting an environment variable to an empty string explicitly overrides config file values:
# Disable post-command even if config files set one
ORBIT_POST_COMMAND="" orbit
# Use empty command (not recommended, but supported)
ORBIT_COMMAND="" orbitConfiguration is resolved in this order (highest priority first):
- CLI flags (
--command,--post-command,--no-post-command) - Environment variables (
ORBIT_COMMAND,ORBIT_POST_COMMAND) - Project config (
.orbit.yamlin working directory) - Home config (
~/.orbit.yaml) - Built-in defaults
- Check Tasks: Orbit queries
rune list --filter pendingto find remaining tasks - Run Phase: Executes the configured agent with the phase prompt (e.g.,
/next-task --phase then /commit) - Handle Errors: Classifies errors per-agent and retries appropriately:
- Connection errors: Exponential backoff (1s, 2s, 4s, 8s, 16s)
- Rate limits: Wait for retry-after duration or 60s default
- API overload: Wait 30s and retry
- Session invalid: Retry with fresh session
- Other errors: Stop and preserve state
- Save Logs: Stores session output and transcripts
- Repeat: Loops until all tasks are complete
Logs are saved to .orbit/ next to the tasks file (e.g., specs/my-feature/.orbit/).
specs/my-feature/.orbit/
├── summary.json # Persistent run summary with session tracking
├── phase-1-run-1-session.json # Full Claude output for phase 1, run 1
├── phase-1-run-1-session.txt # Human-readable transcript
├── phase-2-run-1-session.json
├── phase-2-run-1-session.txt
├── ...
├── post-completion-run-1-session.json
└── post-completion-run-1-session.txt
When you run Orbit multiple times, files are numbered by run (e.g., phase-1-run-2-session.json).
specs/my-feature/.orbit/
└── 2025-01-15-143022-feature-branch/
├── summary.json # Run summary for this session
├── phase-1-session.json
├── phase-1-session.txt
└── ...
Orbit tracks session IDs to enable crash recovery and session continuation across all supported agents.
- Session ID Generation: Before each phase, Orbit generates a UUID session ID
- Persistence: The session ID is saved to
summary.jsonbefore invoking the agent - Resume on Restart: If Orbit is interrupted mid-phase, it detects the unfinished phase and resumes using agent-specific resume mechanisms
- Session Export: Some agents (like Kiro) require explicit session export, which Orbit handles automatically
- Fallback: If session resume fails (e.g., session expired), Orbit automatically starts a fresh session
To always start fresh sessions instead of resuming:
orbit run --no-continue-sessionOr in .orbit.yaml:
continue_session: falseOrbit is inherently resumable. Since task state is tracked in the rune tasks file, you can:
- Stop Orbit at any time (Ctrl+C)
- Complete tasks manually in interactive mode
- Run Orbit again to continue from where you left off
With session continuation enabled (default), Orbit will also resume the agent session context, allowing it to remember what it was working on.
Orbit supports running multiple implementation variants using different agents or guidance, then comparing the results to choose the best implementation. This section provides a complete guide to the variants workflow.
flowchart TD
A[Start: orbit run --variants N] --> B[Setup Phase]
B --> C{Parallel?}
C -->|Yes| D[Run variants concurrently]
C -->|No| E[Run variants sequentially]
D --> F[All variants complete]
E --> F
F --> G{≥2 succeeded?}
G -->|Yes| H[Generate comparison report]
G -->|No| I[Skip comparison]
H --> J[Review comparison report]
I --> J
J --> K[orbit status]
K --> L{Choose variant}
L --> M{Want improvements<br>from other variants?}
M -->|Yes| N[orbit consolidate --variant N]
M -->|No| O[orbit finalize --variant N]
N --> O
O --> P[Done]
style A fill:#e1f5fe
style P fill:#c8e6c9
style H fill:#fff3e0
style O fill:#fce4ec
The variants workflow consists of five main phases:
flowchart TB
subgraph Phase1[1. Setup]
direction LR
A1[Create branches] --> A2[Create worktrees] --> A3[Initialize metadata]
end
subgraph Phase2[2. Execution]
direction LR
B1[Run agent in each worktree] --> B2[Track status & metrics]
end
subgraph Phase3[3. Comparison]
direction LR
C1[Gather diffs] --> C2[AI analysis] --> C3[Generate report]
end
subgraph Phase4[4. Consolidation]
direction LR
D1[Review report] --> D2[Merge improvements from other variants]
end
subgraph Phase5[5. Finalization]
direction LR
E1[Choose variant] --> E2[Adopt & cleanup]
end
Phase1 --> Phase2 --> Phase3 --> Phase4 --> Phase5
Start a multi-variant run to create and execute multiple implementations:
# Run 3 variants with the default agent
orbit run --variants 3
# Run 2 variants in parallel (faster)
orbit run --variants 2 --parallel
# Limit concurrent variants
orbit run --variants 5 --parallel --max-parallel 2
# Compare different agents
orbit run --variants 3 --variant-agents claude-code,codex,kiro
# Compare different models of the same agent (requires agent aliases in config)
orbit run --variants 2 --variant-agents claude-sonnet,claude-opus
# Use per-variant guidance
orbit run --variants 2 --guidance-file guidance.yaml
# Combine options
orbit run --variants 3 --variant-agents claude-code,codex --parallel --guidance-file guidance.yamlWhat happens during setup:
sequenceDiagram
participant User
participant Orbit
participant Git
participant Worktree
User->>Orbit: orbit run --variants 3
Orbit->>Git: Check working directory clean
Git-->>Orbit: OK
Orbit->>Git: Get current branch & HEAD
loop For each variant (1 to N)
Orbit->>Git: Create branch orbit-impl-{id}/{spec}
Git->>Worktree: Create worktree in .orbit/worktrees/
Worktree-->>Orbit: Worktree ready
end
Orbit->>Orbit: Save variants.json
Orbit->>Orbit: Create .gitignore for worktrees/
loop For each variant
Orbit->>Worktree: Run agent with phases
Worktree-->>Orbit: Update status & metrics
end
Orbit->>Orbit: Generate comparison report
Orbit-->>User: Variants complete
| Flag | Default | Description |
|---|---|---|
--variants |
0 |
Number of implementation variants to create |
--parallel |
false |
Run variants concurrently |
--max-parallel |
3 |
Maximum concurrent variants when parallel |
--branch-prefix |
orbit-impl |
Prefix for variant branch names |
--variant-agents |
- | Comma-separated agent list (cycles if fewer than variants) |
--guidance-file |
- | YAML file with per-variant instructions |
Provide different instructions to each variant:
global_guidance: |
Focus on performance and code readability.
Ensure comprehensive test coverage.
variants:
- id: 1
guidance: "Use a functional programming approach with immutable data structures"
- id: 2
guidance: "Use an object-oriented approach with design patterns"
- id: 3
guidance: "Prioritize simplicity and minimize dependencies"When using --variant-agents, agents are assigned in a cycling pattern:
# Example: 4 variants with 2 agents
orbit run --variants 4 --variant-agents claude-code,codex
# Result:
# Variant 1: claude-code
# Variant 2: codex
# Variant 3: claude-code
# Variant 4: codexCheck the status of running or completed variants:
orbit status my-featureExample output:
Variant Status: my-feature
Base Commit: abc1234567
Original Branch: main
Started: 2025-01-25 10:00:00
Variant 2: orbit-impl-2/my-feature [running (dirty)]
Commits:
a1b2c3d Add user authentication handler
e4f5g6h Implement token validation
i7j8k9l Add unit tests for auth
Last Action:
fs_write: internal/auth/handler.go
Tasks:
→ Phase 2: Implementation: 3/5
Phase 3: Testing: 0/2
---
Variant 1: orbit-impl-1/my-feature [completed]
Variant 3: orbit-impl-3/my-feature [pending]
The enhanced status command shows detailed information for active variants (running/failed):
- Recent commits: Last 3 commits made by the agent
- Git state: Whether the worktree has uncommitted changes (clean/dirty)
- Last action: Most recent agent activity (Claude Code only)
- Task progress: Phase-by-phase completion status with active phase indicator (→)
Variant States:
stateDiagram-v2
[*] --> pending: Created
pending --> running: Agent starts
running --> completed: All phases done
running --> failed: Error occurred
running --> canceled: User canceled
completed --> [*]
failed --> [*]
canceled --> [*]
After variants complete, Orbit automatically generates a comparison report (if ≥2 variants succeeded). The report is saved to specs/{spec}/comparison-report/.
# Regenerate comparison report (if needed)
orbit compare my-featureReport contents:
| File | Description |
|---|---|
index.html |
Interactive HTML report with styling |
comparison-report.md |
Markdown report (AI-agent friendly) |
variant-{id}.diff |
Full diffs for each variant (if large) |
Report sections:
- Recommendation - Which variant to choose and why
- Confidence Level - High, medium, or low confidence
- Per-Variant Summary - Key characteristics of each implementation
- File-Level Analysis - Detailed comparison of individual files
- Documentation Assessment - Quality of docs/comments per variant
- Cross-Variant Improvements - Good ideas from non-recommended variants
flowchart TD
A[Gather Data] --> B{Diffs < 150k tokens?}
B -->|Yes| C[Use full diffs]
B -->|No| D[Use summaries]
C --> E[Build comparison prompt]
D --> E
E --> F[Claude analyzes variants]
F --> G[Generate structured result]
G --> H[Create HTML report]
G --> I[Create Markdown report]
G --> J[Save large diffs separately]
H --> K[comparison-report/index.html]
I --> L[comparison-report/comparison-report.md]
J --> M[comparison-report/variant-N.diff]
Before finalizing, you can merge good ideas from other variants into your chosen one. This must be done before finalize, as finalize removes all variant worktrees.
# Apply improvements from other variants to chosen variant 1
orbit consolidate my-feature --variant 1
# With custom instructions
orbit consolidate my-feature --variant 1 --prompt "Focus on error handling improvements"
# Rollback if consolidation didn't work well
orbit consolidate my-feature --rollbackWhat consolidate does:
- Reads the comparison report for cross-variant improvements
- Provides an AI agent with access to all variant worktrees
- Agent analyzes and applies beneficial changes to the chosen variant
- Creates a consolidation commit
- Runs tests to verify the changes
flowchart TD
A[orbit consolidate --variant N] --> B[Load comparison report]
B --> C[Identify cross-variant improvements]
C --> D[Agent analyzes all worktrees]
D --> E[Apply improvements to chosen variant]
E --> F[Run tests & validation]
F --> G{Tests pass?}
G -->|Yes| H[Create consolidation commit]
G -->|No| I[Agent fixes issues]
I --> F
H --> J[Log consolidation details]
J --> K[Done]
L[orbit consolidate --rollback] --> M[Revert last consolidation commit]
M --> K
Consolidate flags:
| Flag | Description |
|---|---|
--variant N |
Which variant is the target (required unless --rollback) |
--prompt |
Additional instructions for consolidation |
--allow-dirty |
Allow consolidation with uncommitted changes |
--rollback |
Revert the last consolidation commit |
--force |
Force consolidation even if report is stale |
After reviewing the comparison (and optionally consolidating improvements), adopt your chosen variant:
# Adopt variant 1 as the final implementation
orbit finalize my-feature --variant 1What finalize does:
- Validates the original branch hasn't diverged (no new commits)
- Rebases the chosen variant onto the original branch
- Removes all variant worktrees
- Deletes all variant branches
- Cleans up
variants.jsonand worktree directory
sequenceDiagram
participant User
participant Orbit
participant Git
User->>Orbit: orbit finalize my-feature --variant 1
Orbit->>Git: Check original branch hasn't diverged
Git-->>Orbit: OK (no new commits)
Orbit->>Git: Checkout original branch
Orbit->>Git: Merge --ff-only orbit-impl-1/my-feature
Git-->>Orbit: Fast-forward successful
loop For each variant
Orbit->>Git: Remove worktree
Orbit->>Git: Delete branch
end
Orbit->>Orbit: Delete variants.json
Orbit->>Orbit: Clean up .orbit/worktrees/
Orbit-->>User: Finalization complete
Finalize flags:
| Flag | Description |
|---|---|
--variant N |
Which variant to adopt (required) |
--force |
Force finalization even if branch diverged |
--dry-run |
Show what would happen without making changes |
If you want to abandon all variants without adopting any:
# Remove all variants
orbit cleanup my-feature
# Keep one variant for manual inspection
orbit cleanup my-feature --keep 2
# Preview cleanup without executing
orbit cleanup my-feature --dry-runDuring a multi-variant run, Orbit creates the following structure:
specs/my-feature/
├── tasks.md # Original tasks file
├── requirements.md # Spec requirements
├── design.md # Spec design
├── .orbit/
│ ├── variants.json # Variant metadata & status
│ ├── .gitignore # Excludes worktrees/
│ ├── worktrees/
│ │ ├── orbit-impl-1-my-feature/ # Variant 1 worktree (full repo)
│ │ ├── orbit-impl-2-my-feature/ # Variant 2 worktree
│ │ └── orbit-impl-3-my-feature/ # Variant 3 worktree
│ ├── logs/
│ │ ├── variant-1/
│ │ │ ├── summary.json # Run summary for variant 1
│ │ │ ├── phase-1-run-1-session.json
│ │ │ └── phase-1-run-1-session.txt
│ │ └── variant-2/
│ │ └── ...
│ ├── consolidation-log.json # Consolidation history
│ └── consolidation-*.md # Agent reports
└── comparison-report/
├── index.html # HTML comparison report
├── comparison-report.md # Markdown report
├── variant-1.diff # Full diff for variant 1
└── variant-2.diff # Full diff for variant 2
Git branch structure:
main
├── feature/my-feature # Original working branch
├── orbit-impl-1/my-feature # Variant 1 branch
├── orbit-impl-2/my-feature # Variant 2 branch
└── orbit-impl-3/my-feature # Variant 3 branch
Here's a complete example of using the variants workflow:
# 1. Start on your feature branch
git checkout feature/user-auth
cd /path/to/project
# 2. Run 3 variants with different agents in parallel
orbit run --variants 3 \
--variant-agents claude-code,codex,claude-code \
--parallel \
--guidance-file auth-guidance.yaml
# 3. Monitor progress (in another terminal)
watch -n 30 orbit status user-auth
# 4. Once complete, review the comparison report
open specs/user-auth/comparison-report/index.html
# or
cat specs/user-auth/comparison-report/comparison-report.md
# 5. (Optional) If variant 1 had some good error handling, consolidate it
# Note: Must be done BEFORE finalize, as finalize removes worktrees
orbit consolidate user-auth --variant 2 \
--prompt "Apply the error handling patterns from variant 1"
# 6. Finalize the best variant (cleans up all worktrees)
orbit finalize user-auth --variant 2
# 7. Continue development on your feature branch
git log --oneline -5 # See the variant commits merged inflowchart LR
subgraph Commands
A[orbit run --variants N]
B[orbit status]
C[orbit compare]
D[orbit consolidate --variant N]
E[orbit finalize --variant N]
F[orbit cleanup]
end
A -->|creates variants| B
B -->|check progress| C
C -->|regenerate report| D
D -.->|optional: merge improvements| E
E -->|adopt variant & cleanup| F
F -.->|alternative to finalize| A
| Command | Purpose | When to Use |
|---|---|---|
orbit run --variants N |
Create and run N variants | Start of workflow |
orbit status <spec> |
Check variant status | Monitor progress |
orbit compare <spec> |
Regenerate comparison | Report outdated or missing |
orbit consolidate <spec> --variant N |
Merge improvements | Before finalize, want ideas from other variants |
orbit finalize <spec> --variant N |
Adopt a variant | Choose final implementation, cleans up worktrees |
orbit cleanup <spec> |
Remove all variants | Abandon without adopting |
Orbit includes a built-in web interface for viewing runs and transcripts.
# Start on default port (8080)
orbit serve
# Start on custom port
orbit serve --port 3000
# Bind to all interfaces (not just localhost)
orbit serve --bind 0.0.0.0- Dashboard: View all runs grouped by repository
- Run Details: See phase status, duration, and summary
- Transcript Viewer: Read transcripts with syntax highlighting and navigation
- Live Updates: Auto-refresh for running sessions via HTMX
- Mobile Responsive: Works on phones and tablets
- Dark Mode: Follows system preference
Orbit automatically registers runs when orchestrating. Runs are tracked in ~/.orbit/runs/ and persist across sessions.
To manually register an existing orbit log directory:
# Register from current directory (auto-detects .orbit/)
orbit register
# Register a specific path
orbit register specs/my-feature
# Register with a custom name
orbit register --name "My Feature" specs/my-feature/.orbitThe web interface shows all registered runs, their status, and provides links to view transcripts.
Apsis is a CLI tool for converting Claude Code session transcripts from JSONL format to readable Markdown or HTML.
go install github.com/arjenschwarz/orbit/cmd/apsis@latest# Convert session by ID (looks in ~/.claude/projects)
apsis 550e8400-e29b-41d4-a716-446655440000
# Convert from file path
apsis /path/to/session.jsonl
# Convert from stdin
cat session.jsonl | apsis
# Follow mode: watch a live session (like tail -f)
apsis -F session-id
apsis --follow /path/to/session.jsonl
# Save to file
apsis -o transcript.md session-id
# Export as HTML
apsis -f html -o transcript.html session-id
# List available sessions for current project
apsis --list
# List sessions for a different project
apsis --list -p /path/to/project| Flag | Description |
|---|---|
-l, --list |
List available sessions for the project |
-o, --output <file> |
Write output to file (default: stdout) |
-p, --project <path> |
Project directory (default: current directory) |
-f, --format <format> |
Output format: md, markdown, html (default: md) |
-F, --follow |
Follow mode: continuously monitor file for new entries (stdout only, markdown only) |
-v, --version |
Show version |
-h, --help |
Show help |
Generates a Markdown document with:
- Session header with ID
- User messages with 👤 icon
- Assistant messages with 🤖 icon
- Collapsible thinking blocks using
<details>tags - Tool usage with JSON input
- Tool results with success/error indicators
Generates a styled HTML document with:
- Embedded CSS (no external dependencies)
- Dark mode support (follows system preference)
- Responsive layout for mobile viewing
- Collapsible thinking blocks
- Syntax-highlighted code blocks
- Color-coded success/error indicators
MIT