Crow is a self-hosted daemon and web UI for running AI coding agents — Claude Code, Codex, Cursor, OpenCode and others — in parallel, each in its own git worktree, driven by your GitHub, GitLab or Jira board.
Why. One coding agent in one terminal is easy. Five at once is not: each needs its own branch and checkout so they don't trample each other, someone has to remember which terminal belongs to which ticket, and every PR needs watching for review comments, failed checks and merge conflicts. Crow does that bookkeeping. Pick a ticket and it creates the worktree, launches the agent with the ticket as context, moves the ticket across your board, and tracks the PR until it merges. It can also review PRs, answer review feedback, and rebase stale branches on its own.
Who it's for. Developers who already work with a coding agent and want to run several tickets at once without losing track of them. Crow runs on your own machine (or a box you control) and drives the git, gh/glab and agent CLIs you've already installed and logged into — it isn't a hosted service.
There is no stable release yet. Prereleases carry macOS builds, but until a stable release is published, building from source is the supported way to install Crow. When one ships, a download path will go here, above the source build.
You need the prerequisites below — at minimum a Swift 6 toolchain, git, tmux and a coding agent.
# 1. Clone
git clone https://github.com/corveil/crow.git
cd crow
# 2. Build the `crow` CLI and the `crowd` daemon (Swift toolchain only).
# `make build` also builds the optional native desktop app — see "Desktop app" below.
make daemon
# 3. Authenticate the GitHub CLI (GitHub workspaces only) — the write `project` scope is required
gh auth login
gh auth refresh -s project,read:org,repo
# 4. Configure your development root + workspaces
.build/debug/crow setup
# 5. Run the daemon — it serves the web UI
.build/debug/crowdcrowd prints HTTP/WS listening on http://127.0.0.1:8787 on startup — open that URL in your browser. The first screen guides you through any remaining setup.
Note: The required GitHub scope is the write
projectscope —read:projectis insufficient because Crow updates ticket status via theupdateProjectV2ItemFieldValueGraphQL mutation. See docs/getting-started.md for details.
The Manager terminal and the /crow-workspace skill call bare crow ..., so a build you can only launch by full path will break those workflows. Install the binaries so they're invokable from anywhere:
make install # symlinks crow + crowd into ~/.local/binIf ~/.local/bin isn't already on your PATH, add this to ~/.zshrc (then restart your shell):
export PATH="$HOME/.local/bin:$PATH"Use a different directory with BINDIR, e.g. make install BINDIR=/usr/local/bin.
make install creates symlinks into .build/debug/, so a later make build updates them in place — no need to re-run it. Re-run make install only when you switch to a release build (make daemon CONFIG=release && make install CONFIG=release) or after make clean (which removes .build/ and leaves the symlinks dangling until the next build). Remove the symlinks with make uninstall.
To start crowd automatically at login, see crow autostart install in the CLI reference.
crowd binds 127.0.0.1:8787 by default, so it's reachable only from the machine it runs on. To reach it from another device, front it with an HTTPS reverse proxy (e.g. tailscale serve) and set a web password under Settings → Web Access or with crow web-password set. Non-loopback requests are blocked until a password is set and the connection is HTTPS.
The password and the AI gateways are local-only surfaces: they're settable from a local browser or the crow CLI (which talks over the Unix socket), and refused for remote web clients — a remote session must not be able to change the password gating remote access, or read gateway credentials. See CLI Reference → Gateway Commands.
crowd is the only process you run, and it drives git, tmux, and the coding agents on the host — so it needs a Unix-like host:
- macOS 14.0+ (Sonoma or later), or Linux (x86_64 or arm64). Windows isn't supported.
- A Swift 6 toolchain — bundled with Xcode Command Line Tools on macOS, or installed from swift.org/install on Linux
- A modern web browser for the UI
| Tool | Version | Purpose | Install |
|---|---|---|---|
| Swift | 6.0+ | Compiler — Xcode CLT (macOS) or the swift.org toolchain (Linux) | xcode-select --install · swift.org/install |
| Rust | 1.77+ | Only for the optional desktop app | rustup.rs |
| Tool | Purpose | Install |
|---|---|---|
git |
Worktree management | Ships with Xcode CLT |
tmux |
Terminal backend for managed sessions (≥ 3.3) | brew install tmux |
claude |
Claude Code — the default coding agent | claude.ai/download |
gh |
GitHub CLI — issues, PRs, project boards. Only for GitHub workspaces | brew install gh |
glab |
GitLab CLI. Only for GitLab workspaces | brew install glab |
acli |
Atlassian CLI. Only for workspaces that track tickets in Jira | developer.atlassian.com/cloud/acli |
Install commands above are macOS/Homebrew; on Linux use your distribution's package manager (e.g.
apt install git tmux;gh/glabhave their own apt repos).claudeis the default coding agent — Codex, Cursor, OpenCode, Grok Build, Antigravity, and Muse Code are also supported and selectable per session (Settings → General, orcrow agents set); install whichever agents you use. An uninstalled agent still appears in the picker, greyed out. What each one can and can't do is in the agent harness matrix.
flowchart TB
subgraph clients["Clients (pure, no privileged state)"]
WEB["Web UI — browser or Tauri window<br/>web UI + xterm.js"]
CLI["crow CLI"]
end
subgraph daemon["crowd — the sole authority"]
HTTP["HTTP + WebSocket server<br/>/rpc · /terminal · web + login"]
ENGINE["CrowEngine<br/>SessionService · spawn / lifecycle"]
BOARDS["IssueTracker<br/>JobScheduler · auto-respond / -review"]
HUB["EventHub — server push"]
STORE[("store.json")]
end
subgraph host["Host + backends"]
TMUX["tmux cockpit"]
AGENTS["Coding agents<br/>Claude Code · Codex · Cursor · OpenCode · …"]
GIT["git worktrees"]
PROV["GitHub · GitLab · Jira"]
end
WEB -- "WebSocket: /rpc + /terminal" --> HTTP
CLI -- "Unix socket JSON-RPC" --> ENGINE
HTTP --> ENGINE
ENGINE --> STORE
ENGINE --> TMUX
ENGINE --> GIT
TMUX --> AGENTS
ENGINE --> BOARDS
BOARDS --> PROV
BOARDS --> HUB
HUB -. "push: changed" .-> WEB
crowd is the single source of truth — the only store writer, the only spawner, and the owner of terminal + agent lifecycle. Every UI is a pure client: it subscribes to crowd's state over the /rpc + /terminal WebSocket surface, sends JSON-RPC, and renders. The web UI is the same either way — a browser tab or the Tauri desktop window, which just wraps that web UI in a native window and can spawn crowd as a sidecar on launch. Multiple clients (browser tabs, the desktop window, the crow CLI, any future UI) attach to one running system at once. Full detail in docs/architecture.md.
History: Crow began as a native macOS (AppKit) app. Per ADR 0009 and ADR 0010 that app was retired:
crowdis the sole authority and every UI is a pure client.
Prefer a native window to a browser tab? crow-desktop/ is a thin Tauri shell that opens a "Crow" window pointed at the same web UI. It doesn't reimplement anything — crowd stays the sole authority; the window is just another pure client. It needs a Rust toolchain.
make run # build crowd + the desktop app, then open the Crow windowOn launch the window looks for a crowd already listening on 127.0.0.1:8787. If it finds one, it reuses it and leaves it running when you quit. If not, it spawns its own crowd — .build/debug/crowd in a debug build, the bundled sidecar inside Crow.app in a release build — and stops it on quit.
Platforms: prebuilt for macOS only. The shell's macOS-specific code is cfg-gated, so it is meant to compile on Linux with cargo, but make doesn't build it there and it isn't tested or released for Linux — on Linux, use the browser. Windows isn't supported, because crowd needs a Unix host with tmux.
Working on the desktop shell or the web UI? See docs/development.md.
Using Crow
- Getting Started — Clone, build, authenticate, and run
- Configuration — File locations, workspace config, directory layout, session lifecycle
- Automation — Auto-create, auto-respond, auto-complete, and the Settings → Automation tab
- Web UI skins — The built-in color skins and how to make your own
- Web Chat view — Read and drive an agent session as chat messages instead of a terminal
- MCP — Crow's read-only MCP server: pointing Cowork or an off-box bot at the board
- Troubleshooting — Build and runtime errors
CLI
- CLI Reference — The canonical reference: every
crowsubcommand and flag, generated from the commands themselves (make docs), so it can't drift - CLI Guide — The companion guide: what each verb is for, JSON response shapes, worked examples and gotchas. A test keeps it covering every verb in the reference
Agents and session logs
- Agent harness matrix — What each supported coding agent can and can't do under Crow, and why
- Session-log collector — Uploading agent transcripts to Corveil, per workspace
- Session backfill — Uploading transcripts that predate the collector
- Harness transcript locations — Where each agent writes its transcripts on disk
Development
- Development — Dev loops for
crowd, the web UI and the desktop shell; adding packages; tests - Architecture — Packages, key components, data flow
- Architecture Decision Records — Why Crow is built the way it is
- macOS release signing — How release builds are signed and notarized
- Harness gap audit — Version-pinned audit behind the harness matrix
- Terminal runtime research — Archived: the original Ghostty-era terminal investigation
The left rail groups your work:
- Tickets — Assigned issues grouped by project board status (Backlog, Ready, In Progress, In Review, Done in last 24h). Click a status to filter.
- Manager — A persistent Claude Code terminal for orchestrating work. Use
/crow-workspacehere to create new sessions. Launches in--permission-mode autoby default so orchestration commands (crow,gh,git) skip per-call approval (recent Claude Code versions can still prompt once for a file read outside your dev root); opt out via Settings → Automation → Manager Terminal. - Active Sessions — One per work context. Shows repo, branch, issue/PR badges with pipeline and review status.
- Completed Sessions — Sessions whose PRs have been merged or issues closed.
Right-click a session (or long-press / tap the ⋮ button on touch devices) for its actions — rename, delete, copy links, and more.
In the Manager tab, tell Claude Code what you want to work on:
/crow-workspace https://github.com/org/repo/issues/123
Or use natural language:
/crow-workspace "add authentication to the acme-api API"
This will:
- Create a git worktree with a feature branch
- Create a session with ticket metadata
- Launch Claude Code in plan mode with the issue context
- Auto-assign the issue and set its project status to "In Progress"
- Pipeline view showing issues by project board status
- Click a status to filter the list
- "Start Working" / "Start Exploring" split-button creates a workspace from an issue (explore is read/explain only)
- Issues linked to active sessions show a navigation button; explore sessions carry an Exploring badge
- Scriptable from the CLI:
crow list-tickets,crow work-on-issue,crow explore-issue,crow batch-work-on-issues,crow start-review, andcrow quick-actiondrive the same actions as the board buttons (see the CLI Reference)
Per ADR 0005, a workspace's
Task Backend (where tickets live) is chosen independently of its Code
Backend (where code + PRs live). You can track work in Jira while keeping
code and pull requests on GitHub — the task side runs through acli, the PR
side still runs through gh.
Prerequisite — authenticate acli:
# Install: https://developer.atlassian.com/cloud/acli/guides/install-acli/
acli jira auth login
acli jira auth status # should print "✓ Authenticated"Configure a Jira-task / GitHub-code workspace (Settings → Workspaces → edit a workspace):
- Code Backend →
GitHub(code + PRs stay on GitHub). - Task Backend →
Jira(offered only whenacliis installed + authenticated; an inline hint tells you the fix when it isn't). - Atlassian Site (e.g.
acme.atlassian.net) — used to build…/browse/KEYlinks. - Project Key (e.g.
PROJ) — default project for created tickets. - My-tickets JQL (optional) — defaults to
assignee = currentUser() AND statusCategory != Done.
Settings persist to the workspace entry (~/.claude/workspace-repos.json keys:
taskProvider, jiraProjectKey, jiraJQL, jiraSite). Existing GitHub/GitLab
workspaces are unaffected — when no Task Backend is set, it follows the Code
Backend (GitHub code ⇒ GitHub issues, as before).
- Pipeline checks (passing/failing/pending)
- Review status (approved/changes requested/needs review)
- Merge readiness (mergeable/conflicting/merged)
- Purple badge with checkmark for merged PRs
- Sessions automatically move to "Completed" when their linked PR is merged or issue is closed
- Checked every 60 seconds during the issue polling cycle
- Requires positive evidence the session was worked, so an unrelated PR merge can't flip an idle session
Crow can drive a ticket from assignment to merged with minimal manual steps. Toggles live under Settings → Automation; full walkthrough in docs/automation.md.
- Auto-create workspace when an issue assigned to you is labeled
crow:auto(or an exploration session when labeledcrow:explore) - Auto-suggest opening a PR if a session completes with no PR linked
- Auto-start review sessions for opted-in workspaces when a PR becomes reviewable
- Auto-respond to changes-requested reviews and failed CI checks (off by default)
- Auto-merge Crow-authored PRs labeled
crow:mergeviagh pr merge --auto --squash(off by default; only acts on PRs whose commits carry aCrow-Session:trailer matching a known session). Crow lazily creates thecrow:mergelabel on first observation; to pre-seed it manually:gh label create crow:merge --color 0E8A16 --description "Crow: enable auto-merge once mergeable" - Scriptable —
crow automation get|setdrives every toggle on the tab: the five auto-permission modes, remote control, commit attribution, both label watchers, and the auto-respond toggles. Same config as the UI, live within a board poll, nocrowdrestart. The tab's ticket/review board filters are global defaults and belong tocrow defaults set(CLI reference)
- Multi-select with batch Start Review
- Bulk delete sessions
- Filter projects out via
excludeReviewRepos - Quick action buttons on the session detail header (open PR, mark in review, copy branch)
- Move completed sessions back to active
- xterm.js terminal surface in the browser, streamed from tmux over a WebSocket (
/terminal) - tmux-backed managed terminals — each session is a tmux window on a shared server (the "cockpit"), so per-session shells stay alive across UI navigation and across browser reconnects. Requires
tmux ≥ 3.3(brew install tmux); without it, managed terminals don't render. See docs/architecture.md#terminal-backends. - Rename tabs from the UI or via
crow rename-terminal - tmux maintenance from the CLI as well as Settings → About:
crow restart-manager,crow restart-tmux-server,crow reload-tmux-config,crow launch-agent,crow retry-readiness, pluscrow open-in-vscode/crow open-terminalfor the session's worktree on the host. See docs/cli-reference.md.
- A workspace maps a folder under your dev root to a forge (GitHub or GitLab), a ticket source (GitHub, GitLab, or Jira), the repos it always lists or auto-reviews, and free-text instructions appended to its session prompts
- Manage from Settings → Workspaces or from the CLI with
crow workspace list|get|add|edit|remove— both write the same config, and an open browser tab picks up a CLI change within a couple of seconds - Renaming or removing a workspace is guarded: sessions are tied to it only by their worktree path and jobs only by its name, so both refuse while references exist and report what
--forcewould orphan. See docs/cli-reference.md.
- Events for task complete, agent waiting, review requested, changes requested and CI failing, plus the automation events Crow emits when it acts on your behalf (auto-created workspace, auto-merge enabled or blocked, branch rebased, rebase conflicts or stuck) and a config reload.
crow notifications getlists them all - Cascading control: a master mute, global sound / system-notification toggles, then per-event toggles and a sound picked from 14 built-in sounds
- Manage from Settings → Notifications or from the CLI with
crow notifications get|set— both write the same config, and an open browser tab picks up a CLI change within a couple of seconds
- On startup, scans git worktrees across all repos
- Worktrees not tracked in the store are automatically recovered as sessions
- Fetches ticket metadata and PR links from GitHub for recovered sessions
- Deleting a session on a protected branch (main, master, develop) only removes the session metadata — the repo folder and branch are preserved
- The delete confirmation dialog reflects this, showing "Remove Session" instead of "Delete Everything"
We welcome contributions! See CONTRIBUTING.md for guidelines on reporting bugs, suggesting features, and submitting pull requests, and docs/development.md for dev loops, adding packages, and running tests.
Apache 2.0 — see LICENSE for details.
