Arbor is a fully native app for agentic coding built with Rust and GPUI. It gives you one place to manage repositories, issue-driven worktrees, embedded terminals, managed processes, diffs, PR context, AI coding agent activity, and a shared daemon that also powers Arbor's web UI, CLI, and MCP server.
- Fully native desktop app, UI and terminal stack included, optimized for long-running local workflows
- One daemon-backed model for the desktop app, web UI, CLI, and MCP server
- Built for parallel coding sessions across local repos, issue queues, and remote outposts
- List, create, and delete worktrees across multiple repositories
- Create managed worktrees directly from GitHub or GitLab issues
- Preview sanitized worktree names, branch names, and target paths before creation
- Repo-local branch naming rules via
[branch]inarbor.toml - Delete confirmation with unpushed commit detection
- Optional branch cleanup on worktree deletion
- Worktree navigation history (back/forward)
- Last git activity timestamp per worktree
- Automatic issue linking to existing branches and open PRs / MRs
- Built-in PTY terminal with truecolor and
xterm-256colorsupport - Multiple terminal tabs per worktree
- Experimental embedded
libghostty-vtengine behind a compile-time feature flag, used by default when available - Persistent daemon-based sessions (survive app restarts)
- Session attach/detach and signals (interrupt/terminate/kill)
- Managed processes from both
Procfileandarbor.toml - Process restart state, memory metrics, and terminal-session linkage
- Scheduled
[[tasks]]fromarbor.toml, with optional Claude or Codex triggers - Bell-aware terminal activity and completion notifications
- Side-by-side diff display with addition/deletion line counts
- Changed file listing per worktree
- File tree browsing with directory expand/collapse
- Multi-tab diff sessions
- PR summary and detail cards in the changes pane
- Native inline PR comment actions and review-comment refresh support
- Interactive chat sessions with ACP agents (Claude, Codex, Pi, Gemini, and more via acpx)
- OpenAI-compatible provider support: Ollama, LM Studio, OpenRouter, OpenAI, and any
/v1/chat/completionsendpoint - Streaming responses via SSE for OpenAI-compatible providers and JSONL for ACP agents
- Automatic model discovery: probes
/v1/modelsat startup for configured providers - Model selector with per-provider sections and distinct icons (ACP vs API)
- Provider configuration via
~/.config/arbor/config.toml[[providers]]sections - Session persistence across daemon restarts
- Token usage tracking and display
- Detects running coding agents: Claude Code, Codex, OpenCode
- Working/waiting state indicators with color-coded dots
- Real-time updates over WebSocket streaming in both the desktop and web UI
- Legacy session compatibility and targeted clear events for long-lived daemon sessions
arbor-httpdserves the remote daemon API and bundled web UIarbor-cliexposes daemon-backed health, repo, worktree, terminal, process, and task commands- Dedicated
arbor-mcpbinary backed by Arbor's daemon API - Structured MCP tools for repositories, worktrees, terminals, processes, tasks, and agent activity
- MCP resources for daemon snapshots and prompts for common Arbor workflows
- Supports
ARBOR_DAEMON_URLandARBOR_DAEMON_AUTH_TOKENfor remote authenticated daemons - Create and manage remote worktrees over SSH
- Multi-host configuration with custom ports and identity files
- Mosh support for better connectivity
- Remote terminal sessions via
arbor-httpd - Outpost status tracking (available, unreachable, provisioning)
- Optional Symphony runtime endpoints when the feature is enabled
- Automatic PR detection and linking per worktree
- Git actions in the UI: commit, push
- Three-pane layout across
arbor-guiandarbor-web-ui - Command palette coverage for actions, repos, worktrees, issues, presets, and task templates
- Resizable panes, collapsible sidebar, desktop notifications
- 38 themes shared between the desktop app and web UI, with live sync when switching themes
- Branch-aware window titles and daemon / rate-limit status polish
- TOML config at
~/.config/arbor/config.tomlwith hot reload
brew install penso/arbor/arborDownload the latest build from Releases.
Release bundles ship the desktop app plus arbor-httpd, arbor-mcp, and arbor-cli.
git clone https://github.com/penso/arbor
cd arbor
just runTo run the MCP server against a local dev daemon:
just run-mcpThe live docs site is available at penso.github.io/arbor/docs.
The in-repo mdBook sources live under docs/src, and you can build them locally with:
just docs-build| Crate | Description |
|---|---|
arbor-benchmarks |
CodSpeed and local benchmark targets |
arbor-cli |
CLI for Arbor's daemon API (arbor-cli binary) |
arbor-daemon-client |
Typed client and shared API DTOs for arbor-httpd |
arbor-core |
Worktree primitives, change detection, agent hooks |
arbor-gui |
GPUI desktop app (arbor binary) |
arbor-httpd |
Remote HTTP daemon (arbor-httpd binary) |
arbor-mcp |
MCP server exposing Arbor via stdio (arbor-mcp binary) |
arbor-mosh |
Mosh transport for remote outposts |
arbor-ssh |
SSH transport for remote outposts |
arbor-symphony |
Optional workflow orchestration runtime |
arbor-terminal-emulator |
Embedded terminal engine glue and Ghostty integration |
arbor-web-ui |
TypeScript dashboard assets + helper crate |
Repo-local behavior is configured with <repo>/arbor.toml.
Arbor currently reads repo presets, managed processes, worktree scripts, scheduled tasks, branch naming rules, agent defaults, and notification routing from that file.
Example:
[[presets]]
name = "Review"
icon = "R"
command = "codex --prompt-file .arbor/tasks/review.md"
[[processes]]
name = "web"
command = "npm run dev"
working_dir = "app"
auto_start = true
auto_restart = true
restart_delay_ms = 2000
[scripts]
setup = ["cp .env.example .env"]
teardown = ["rm -f .env"]
[branch]
prefix_mode = "github-user"
[agent]
default_preset = "codex"
auto_checkpoint = true
[notifications]
desktop = true
events = ["agent_started", "agent_finished", "agent_error"]
webhook_urls = ["https://example.com/hook"]
[[tasks]]
name = "triage-prs"
schedule = "0 */30 * * * * *"
command = "./scripts/triage-prs"
enabled = true
[tasks.trigger]
on_exit_code = 0
on_stdout = true
agent = "codex"
prompt_template = "Review this output and prepare a follow-up plan:\n\n{stdout}"Task templates for the command palette default to <repo>/.arbor/tasks/*.md.
Arbor also ships arbor-cli for daemon-backed scripting:
cargo run -p arbor-cli -- health
cargo run -p arbor-cli -- worktrees list --json
cargo run -p arbor-cli -- processes list --json
cargo run -p arbor-cli -- tasks list --jsonArbor ships a dedicated arbor-mcp binary from the arbor-mcp crate. The stdio server is enabled by the crate's default stdio-server feature and talks to arbor-httpd, so the daemon must be reachable first.
Enable it in a normal build:
cargo build -p arbor-mcpEnvironment variables:
ARBOR_DAEMON_URLoverrides the daemon base URL. Default:http://127.0.0.1:8787ARBOR_DAEMON_AUTH_TOKENsends a bearer token for remote authenticated daemons
Remote access:
- On the daemon host, set
[daemon] auth_token = "your-secret"in~/.config/arbor/config.toml. - Start
arbor-httpd. When an auth token is configured, Arbor binds remotely by default on0.0.0.0:8787unlessARBOR_HTTPD_BINDoverrides it. - Point
arbor-mcpat that daemon withARBOR_DAEMON_URL=http://HOST:8787. - Pass the same secret with
ARBOR_DAEMON_AUTH_TOKEN=your-secret.
Loopback requests are allowed without a token. Non-loopback requests require Authorization: Bearer <token>.
Example client config:
{
"mcpServers": {
"arbor": {
"command": "/path/to/arbor-mcp",
"env": {
"ARBOR_DAEMON_URL": "http://127.0.0.1:8787"
}
}
}
}The arbor-mcp binary is feature-gated. To disable the stdio server binary in a build, use:
cargo build -p arbor-mcp --no-default-featuresSee docs/mcp.md for the full MCP setup guide.
- Rust nightly — the project uses
nightly-2025-11-30(install via rustup) - just — task runner
- A Caskaydia / Cascadia Nerd Font variant — icons in the UI use Nerd Font glyphs
just setup-macos
Or manually:
xcode-select --install
xcodebuild -downloadComponent MetalToolchain
brew install --cask font-caskaydia-cove-nerd-font
just setup-linux
Or manually:
sudo apt-get install -y libxcb1-dev libxkbcommon-dev libxkbcommon-x11-dev
Then install the CaskaydiaMono Nerd Font to ~/.local/share/fonts/.
Arbor can also be built with an experimental embedded Ghostty terminal engine. This is opt-in, disabled by default, and currently expects:
- the pinned
vendor/ghosttysubmodule checked out zigonPATH- a prebuilt
arbor_ghostty_vt_bridgeshared library intarget/ghostty-vt-bridge/lib - optionally,
ARBOR_GHOSTTY_SRC=/path/to/ghosttyto override the pinned submodule - optionally,
ARBOR_GHOSTTY_TARGET/ARBOR_GHOSTTY_CPUto force a safer Zig target in CI
With a build that includes --features ghostty-vt-experimental, Arbor defaults
to the embedded Ghostty engine. You can still choose the embedded engine in
~/.config/arbor/config.toml:
embedded_terminal_engine = "ghostty-vt-experimental"Example:
git submodule update --init --recursive vendor/ghostty
just ghostty-vt-bridge
RUSTFLAGS="-L native=$(pwd)/target/ghostty-vt-bridge/lib -C link-arg=-Wl,-rpath,$(pwd)/target/ghostty-vt-bridge/lib" \
cargo +nightly-2025-11-30 run -p arbor-gui --features ghostty-vt-experimentalTo run Arbor with both embedded engines available and let config.toml choose:
git submodule update --init --recursive vendor/ghostty
just run-configured-embedded-engineTo run the experimental checks:
git submodule update --init --recursive vendor/ghostty
just test-ghostty-vt
just check-ghostty-vt-gui
just check-ghostty-vt-httpdTo compare the embedded engine performance:
git submodule update --init --recursive vendor/ghostty
just bench-embedded-terminal-enginesTo build the daemon with the same terminal engine:
git submodule update --init --recursive vendor/ghostty
just ghostty-vt-bridge
RUSTFLAGS="-L native=$(pwd)/target/ghostty-vt-bridge/lib -C link-arg=-Wl,-rpath,$(pwd)/target/ghostty-vt-bridge/lib" \
cargo +nightly-2025-11-30 run -p arbor-httpd --features ghostty-vt-experimental- Superset — terminal-based worktree manager
- Jean — dev environment for AI agents with isolated worktrees and chat sessions
- Conductor — macOS app to orchestrate multiple AI coding agents in parallel worktrees
Thanks to Zed for building and open-sourcing GPUI, the GPU-accelerated UI framework that powers Arbor.