Multi-agent orchestrator for Claude Code. Start a normal Claude Code session that can fan out work to parallel autonomous agents, each in its own git worktree and tmux pane.
klausThat's it. Run it from a repo or from your home directory — either works. You're in an interactive Claude Code session. Talk to Claude normally — plan features, debug issues, review code. When there's work that can run in parallel, Claude (or you) spawns agents:
You: We need to fix the flaky auth test, add dark mode to settings,
and update the API docs. Can you launch agents for each?
Claude: [runs klaus launch for each task]
Three new tmux panes appear. Each agent works independently in its own worktree, pushes a branch, and opens a PR. Your coordinator session stays focused on the big picture.
- In a repo: a fresh git worktree is created from
origin/main. Anywhere else: a scratch workspace under~/.klaus/sessions/ - Claude Code starts interactively in that workspace
- You talk to Claude as usual — it has
klauson PATH - When Claude runs
klaus launch, a new tmux pane splits off with an autonomous agent - Agents push branches and open PRs —
klaus dashboardpicks them up automatically - The pipeline monitors CI, dispatches fix agents on failure, and auto-merges when approved
- Your job shifts from babysitting agents to reviewing and approving PRs
- When you're done,
klaus cleanup --alltears everything down
Klaus is repo-agnostic. You can run it from your home directory and target any repo with klaus launch --repo owner/repo or set a session default with klaus target owner/repo.
The session is the experience. The pipeline handles the rest.
Once an agent opens a PR, the dashboard's event-driven pipeline takes over:
PR created → CI pending → CI passed → Approved → Merged
↓ ↓ ↓
CI failed Changes Req. Conflicts?
↓ ↓ ↓
Fix agent Fix agent Rebase agent
- CI fails — a fix agent is dispatched automatically (via
--pr) to push a correction - Review comments — an agent is dispatched to address requested changes
- Approved + CI green + no conflicts — auto-merge (when
auto_merge_on_approvalis enabled) - Merge conflicts — a rebase agent resolves them before merging
When a pr-fix run is already active on a PR — including coordinator-launched runs from klaus launch --pr — the pipeline will not auto-dispatch additional fix or rebase agents on it. This prevents races during multi-step refactors where intermediate commits may fail CI before the run completes.
Pipeline stages per PR: ci_pending → ci_passed → approved → merged, with failure paths back through ci_failed or changes_requested. Budget-exhausted agents land in budget_paused — see Budget pause and resume below.
You can also drive the pipeline manually with klaus approve and klaus merge.
Pipeline events (PR created/approved/merged, CI passed/failed, agent errors) are appended to ~/.klaus/sessions/$KLAUS_SESSION_ID/events.jsonl and exposed as a streaming channel via klaus watch. It's designed for Claude Code's Monitor tool — each matching event becomes a notification injected into the coordinator's context between turns, so the coordinator can react to merges or CI failures without you having to mention them.
klaus watch # default filter, follow new events
klaus watch --since-start # replay everything in the file, then follow
klaus watch --filter pr:merged # narrow to a single event type (repeatable)
klaus watch --filter-out pr:approved # subtract from the default filter
klaus watch --json # raw JSONL passthrough
klaus watch --list-types # show live and reserved event typesThe coordinator session's system prompt automatically suggests arming a persistent Monitor on klaus watch at startup. The dashboard reads the same events.jsonl file independently — both consumers can run side by side.
When an agent exhausts its --budget cap, klaus does not silently kill the worktree. Instead it parks the in-progress work on GitHub:
- Commits any uncommitted changes in the worktree (
WIP from klaus run <id> (budget paused)). - Pushes the branch to
origin(with--force-with-lease). - Opens a draft PR — or updates the existing one — and applies the
klaus:budget-pausedlabel. - Posts a one-line PR comment explaining the pause and how to continue.
- Cleans up the worktree and tmux pane.
The draft PR + label is the persisted state — klaus does not keep an in-process "paused" status. The dashboard surfaces these as budget paused, awaiting decision via the pipeline FSM (which reads the label off GitHub).
To resume, dispatch a fresh agent against the PR's branch:
klaus launch --pr <num> "continue the work"The new agent sees the WIP commit and picks up from there. When the follow-up agent's _finalize runs, the klaus:budget-paused label is automatically removed and an agent:resumed event is emitted. If the follow-up agent also exhausts its budget, the cycle repeats (a new WIP commit, label re-applied).
To abandon the work, close the draft PR. To redirect, push manual commits to its branch.
There is no separate klaus resume or klaus finalize command — klaus launch --pr is the only resume path, and _finalize handles the WIP commit automatically.
Add as a flake input to your repo:
inputs.klaus = {
url = "github:patflynn/klaus";
inputs.nixpkgs.follows = "nixpkgs";
};Then add klaus.packages.${system}.default to your devShell's buildInputs.
git clone https://github.com/patflynn/klaus.git
cd klaus
go build -o ~/.local/bin/klaus ./cmd/klaus/The coordinator session uses these — you generally don't run them directly:
| Command | Purpose |
|---|---|
klaus session |
Start an interactive coordinator session |
klaus launch "<prompt>" |
Spawn an autonomous agent |
klaus launch --repo owner/repo "<prompt>" |
Launch an agent against a different GitHub repo |
klaus launch --repo <project-name> "<prompt>" |
Launch an agent using a registered project |
klaus launch --pr <number> "<prompt>" |
Push fixes to an existing PR's branch |
klaus target owner/repo |
Set session-level default target repo |
klaus status |
Dashboard of all runs (with CI, conflict, and merge-readiness columns) |
klaus logs <id> |
View agent output (live, replay, or raw) |
klaus cleanup <id>|--all |
Tear down worktrees, panes, and state |
klaus push-log <id> |
Force-push a log held back for sensitivity |
klaus project add <owner/repo> |
Register a project (clones if needed) |
klaus project list |
Show registered projects |
klaus project remove <name> |
Unregister a project |
klaus project describe <name> <desc> |
Set a one-line description (empty string clears it) |
klaus project set-dir <path> |
Set the default projects directory |
klaus sync |
Fetch and fast-forward every registered project |
klaus new <project-name> |
Scaffold a new project using principles-based generation |
klaus webhook check |
Check registered projects for GitHub webhook configuration |
klaus webhook setup [project] |
Create missing webhooks for registered projects |
klaus dashboard |
Live TUI dashboard for monitoring agents and PRs |
klaus watch |
Stream pipeline events line-by-line (designed for Claude Code's Monitor tool) |
klaus approve <pr>... |
Approve PRs for merging |
klaus merge <pr>... |
Sequentially merge PRs with conflict resolution |
klaus init |
Scaffold .klaus/ config (optional, for customization) |
Push fixes to an existing PR's branch instead of creating a new PR. The agent checks out the PR's branch, makes changes, and pushes directly — the PR updates automatically. Useful for addressing review comments or fixing CI failures on an existing PR.
klaus launch --pr 42 "Address the review comments"
klaus launch --pr 42 --issue 10 "Fix the auth bug mentioned in review"The --pr and --issue flags can coexist (the agent may reference the issue in commits).
Launch an agent against a different GitHub repository. The repo is cloned (or fetched if already cached) and the agent gets its own worktree in that clone. State is still tracked in the host repo.
klaus launch --repo owner/repo "Fix the bug in their API"When sandbox_host is set in ~/.klaus/config.json, agents run remotely via SSH on the sandbox host instead of locally. The worktree is synced to the sandbox before launch, and results are synced back after completion. Log streaming, formatting, and finalization still happen locally.
{"sandbox_host": "klaus-worker-0"}If the sandbox is unreachable, execution falls back to local automatically. Use --local to force local execution, or --host <name> to override the configured sandbox host.
klaus launch --local "Run this locally"
klaus launch --host my-sandbox "Run on a specific host"The dashboard shows [sandbox] tags on remotely-executed agents and displays sandbox reachability status in the header. The status command includes a HOST column.
Set a session-level default target repo. When the coordinator session is not inside a git repo, this avoids needing --repo on every klaus launch. Accepts a registered project name or owner/repo.
klaus target owner/repo # set default by owner/repo
klaus target my-project # set default using registered project name
klaus target # show current target
klaus target --clear # remove defaultThe targeting priority for klaus launch is:
--repoflag — if it matches a registered project name (noowner/prefix), resolves to that project's local path--repoflag —owner/repoor full URL (clones/fetches from GitHub)- Current git repo (if in one)
- Session target (
klaus targetsetting) - Error with usage hint
The status dashboard shows these columns for each run:
| Column | Values | Meaning |
|---|---|---|
| CI | passing / failing / pending / unknown |
CI check status for the PR |
| CONFLICTS | none / yes / unknown |
Whether the PR has merge conflicts |
| MERGE | ready / blocked / pending |
Overall merge readiness (combines CI, conflicts, and review status) |
Live TUI view of the PR pipeline. Groups runs by repository, auto-refreshes via filesystem watching and GitHub polling every 30s. Keyboard shortcuts: q quit, r force refresh.
Mark PRs as approved for merging. By default, klaus merge requires approval before merging.
klaus approve 42 43 # approve specific PRs
klaus approve --all # approve all merge-ready PRs
klaus approve --run 20260328-1603-a3f2 # approve by run IDSequentially merges a list of PRs. Handles conflicts by rebasing onto main, verifying the build, and force-pushing. Waits for CI to pass before merging (up to 10 min).
By default, PRs must be approved with klaus approve before merging. Unapproved PRs trigger an interactive prompt (or are skipped with --yes).
klaus merge 42 43 44
klaus merge --dry-run 42
klaus merge --merge-method rebase --no-delete-branch 42
klaus merge --force 42 # bypass approval check
klaus merge --yes 42 43 # skip unapproved PRs without promptingFlags: --dry-run, --merge-method (squash/merge/rebase), --no-delete-branch, --force (bypass approval), --yes (skip unapproved).
Manage a persistent registry of projects. The registry maps short names to local paths and is stored in ~/.klaus/projects.json.
klaus project add owner/repo # clone into projects dir and register
klaus project add owner/repo --path . # register an existing local checkout
klaus project add owner/repo -d "CLI for X" # register with an explicit description
klaus project add my-tool # search your GitHub repos by name
klaus project list # show all registered projects
klaus project remove my-tool # unregister (does not delete the clone)
klaus project describe my-tool "CLI for X" # add or update the one-line description
klaus project describe my-tool "" # clear the description
klaus project set-dir ~/hack # set the default clone directoryWhen klaus project add is called without -d/--description, klaus tries gh repo view --json description to pick up the GitHub description automatically. If gh is unavailable or the repo has no description, the project is registered without one — you can backfill later with klaus project describe. Descriptions show up in klaus project list and in the session coordinator's ## Registered projects block.
Check and create GitHub webhooks for registered projects. Webhooks let the dashboard receive real-time events (CI status, PR reviews, pushes) instead of relying solely on polling.
klaus webhook check # show webhook status for all registered projects
klaus webhook setup # create missing webhooks for all projects
klaus webhook setup my-project # create a webhook for a specific projectBoth commands require webhook.relay_url in your config. setup also requires webhook.secret_file — a path to a file containing the HMAC secret used to verify incoming payloads.
{
"webhook": {
"relay_url": "https://your-relay.example.com",
"secret_file": "/path/to/webhook-secret"
}
}The created webhooks subscribe to push, check_run, check_suite, pull_request, and pull_request_review events.
Creates a new GitHub repo and launches a Claude agent to scaffold it. Reads principles from .klaus/principles.md (or built-in defaults). The agent makes all scaffolding decisions based on those principles — no templates. The new project is automatically registered in the project registry.
klaus new my-projectKlaus works out of the box with sensible defaults. To customize, run klaus init to scaffold a .klaus/ directory (or ~/.klaus/config.json when outside a repo), or create the files yourself. Configuration layers: defaults → ~/.klaus/config.json → .klaus/config.json.
.klaus/config.json — Override defaults:
{
"worktree_base": "/tmp/klaus-sessions",
"default_budget": "5.00",
"data_ref": "refs/klaus/data",
"default_branch": "main",
"trusted_reviewers": ["gemini-code-assist[bot]"],
"require_approval": true,
"auto_merge_on_approval": false
}.klaus/prompt.md — Custom system prompt for launched agents. Go template variables: {{.RunID}}, {{.Issue}}, {{.Branch}}, {{.RepoName}}. Customize this to match your repo's conventions, test commands, and PR workflow.
.klaus/session-prompt.md — Custom prompt for the coordinator session. Same template variables.
.klaus/pr-fix-prompt.md — Custom prompt for PR-fix agents. Additional variable: {{.PR}}.
- Worktrees isolate each agent — they can't step on each other or your working tree
- tmux panes give live visibility into each agent's progress
- JSONL logs are saved for replay and post-run analysis
- Sensitivity scanning checks logs for private IPs, SSH keys, and credentials before persisting
- State storage — session state lives in
~/.klaus/sessions/(ephemeral, machine-local), while finalized run artifacts sync to the repo's data ref - Data ref (
refs/klaus/data) stores run metadata without polluting your branch list
tmux(sessions run inside tmux)claude(Claude Code CLI)git(needed for agent worktrees; sessions can run without it)gh(GitHub CLI, for PR operations)