Baton is a local coordination hub + knowledge base for running multiple AI coding agents on one repo β Claude Code, Cursor, Codex, Gemini, Aider, OpenCode. Isolated git worktrees, a realtime dashboard, shared evidence-anchored memory, installable skills, and one-file session handoff.
Docs Β· Features Β· How it works Β· Use cases Β· FAQ Β· About
In this repo: Quickstart Β· Documentation Β· CLI reference Β· Architecture
Developers increasingly run two or three AI coding tools at once and split work to save money and quota β plan and reason on a powerful (often plan-included) agent, then do the bulk editing on a cheaper one. But the agents don't know about each other:
- They clobber the same files with no warning.
- Switching tools loses all the context β the plan, the diff, the remaining tasks die with the session.
- Each one re-reads the whole repo to orient, burning tokens.
Baton coordinates them on one repo: every task runs in its own git worktree, a local daemon streams who's editing what in realtime, a queryable knowledge graph lets agents navigate instead of grepping, shared memory carries verified facts between sessions, and a single HANDOFF.md carries a curated, execution-ready brief β with a cost estimate β from one agent to the next.
One file (
HANDOFF.md). No server lock-in. No database. Open source.
Claude Code (plan / think) Cursor Β· Codex Β· Gemini (edit cheap)
ββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββ
baton pass my-task --to cursor ββββββββββΆ HANDOFF.md ββββββββββΆ baton take my-task
(curated brief + est_cost_usd) (objective Β· plan Β· (prints the execution
files Β· git state Β· prompt, marks in-progress)
graph excerpt) β¦agent editsβ¦
baton done
Do the expensive thinking where it's powerful (or included in your plan); do the bulk editing where it's cheap. Baton emits a minimal, cheap-to-execute brief with a token/cost estimate β not a raw history dump.
Prefer to have an agent do this for you? Paste this repo into Cursor or Claude Code and say "set this up for me" β it'll follow AGENTS.md, ask what it needs to know (which project to wire up, which agents you use, which port), run every command itself, and leave you a personalized
GETTING_STARTED.mdin your project when it's done.
Requires Node β₯ 24 and git. Run this in any repo:
npx batonhq setupIt scans the folder, then asks a handful of arrow-key questions β one repo or a hub over several, which agents you use, whether to turn on the knowledge graph. Each option carries a note explaining it, and Enter takes the recommendation. Then:
baton serve --write # daemon + dashboard β http://localhost:7077Installing it permanently, and the optional knowledge graph
npm install -g batonhq # `baton` on your PATH (setup offers this at the end)Those two β npx or a global install β are the ways that work. Never
npm i batonhq inside a project: Baton is a CLI, nothing imports it, and as a
dependency it makes every npm install in that project rebuild the whole tree,
native modules and all.
The knowledge graph needs one extra tool, the Python graphify CLI:
uv tool install graphifyy # or pipx install graphifyySetup offers to install it for you and never blocks on it β without it you lose the graph, and worktrees, tasks, edit signals, memory, handoff and the dashboard all still work. See docs/installation.md.
The npm package is batonhq; the command is baton. (Unrelated packages named baton, baton-cli and create-baton belong to other projects.)
Then create an isolated session and point an agent at it:
baton new "refactor the auth middleware" # β branch baton/β¦ + worktree under .baton/wt/
cd .baton/wt/refactor-the-auth-middleware # start claude / cursor / codex hereWorking across several repos? Run baton setup on the folder that holds them to create one hub β a single dashboard + merged knowledge graph over all of them. baton serve runs from the hub root (which needn't be a git repo); each task just names its sub-project, and the worktree branches off that repo:
baton new "fix the checkout crash" --project api-server # or pick it in the dashboard| Feature | What it does | |
|---|---|---|
| π³ | Worktree isolation | Every task gets its own git worktree + baton/<slug> branch. No clobbered branches, ever. |
| π§ | Knowledge graph |
baton kb indexes your repo into a queryable graph (via graphify) + a CODEBASE.md map. Agents navigate instead of grepping β the map is ~300Γ cheaper than reading the files. |
| π€ | Session handoff |
baton pass packages a session into one HANDOFF.md β objective, plan, checklist, files, git state, cost estimate β and baton take turns it into an execution prompt. |
| π‘ | Live edit signals | A realtime dashboard (SSE) shows who's editing what β and what they're doing (each session's live intent note + freshness). Two sessions on one file β an overlap warning before the conflict. |
| π | Evidence-anchored memory |
Shared facts pinned to commits + file content hashes. When an anchored file changes, the fact is withheld β agents can't hallucinate from stale knowledge. Nothing is hard-deleted: removed facts go to a journaled archive (baton memory log). |
| π§© | Installable skills | A catalog of reusable agent playbooks β one click (or baton skills install <id>) installs a skill into every agent at once, each in its own format (.claude/skills/β¦, .cursor/rules/β¦). Ships a flagship bug-fix pipeline, a lean-code restraint skill (adapted from Ponytail, whose ladder measured ~54% less code and ~20% cheaper on real agent sessions), and an efficiency & traceability pack. |
| π | Bug recurrence |
baton bugs "<symptom>" β was this fixed before, and did a later change re-break it? Composes recorded fixes (memory) with commit history to name the suspect commits. Zero new storage. |
| π | Agent routing |
baton route picks the right agent per task from committed rules (deterministic, no LLM) β and handoff prefers the least-loaded available agent. |
| π§ | MCP tools |
baton mcp exposes coordination tools (check_files, who_touched, recall_memory, β¦) to every agent over MCP. |
Five situations Baton is built for. Each is one command.
Your good agent is rate-limited, and you still have work to do. Plan on the agent that reasons well, execute on the one that's cheap or still has quota. The brief carries the objective, plan, checklist, touched files, git state and a cost estimate β not a transcript dump.
baton pass fix-checkout --to cursor # β HANDOFF.md
baton take fix-checkout # on the other agentTwo agents just edited the same file. Every task gets its own worktree and branch, so they physically cannot collide. Before an agent touches a shared file, it asks β and gets told who's in there and what they're doing.
baton new "refactor auth" # isolated worktree + branch
baton signals # who is editing what, right nowA session died mid-task β context ran out, the window closed, you went home. The next session picks up from a written brief instead of re-deriving everything.
baton resume fix-checkoutAn agent is new to the repo and starts grepping.
It reads a queryable graph and a CODEBASE.md map instead β roughly 300Γ cheaper than reading the files it would otherwise open to orient.
baton kb init && baton orientOne product, several repos (api, web, mobile, infra). Point setup at the folder holding them: one merged graph, one dashboard, tasks that name their sub-project.
npx batonhq setup # detects the repos, offers the hub
baton new "fix the checkout crash" --project apiBonus β "didn't we already fix this?" Composes recorded fixes with commit history to name the commits that likely re-broke it.
baton bugs "checkout 500s on empty cart"Baton is a local tool. It is worth being precise about this rather than asking you to take it on faith:
- No telemetry, no analytics, no account. There is no tracking code in the source β nothing to opt out of, because there is nothing to opt into.
-
Solo mode makes zero outbound requests. The daemon binds
127.0.0.1and is unreachable from outside your machine. Your code, graph, memory and tasks live in.baton/in your own repo. -
No install scripts.
npm i -g batonhqruns nopostinstall, so nothing executes on install. It works fine undernpm i --ignore-scripts. -
Team mode is opt-in and metadata-only. Networking happens only after you run
baton host set <url>to link machines. Even then, what crosses the wire is coordination metadata β task slug, agent name, which paths are being edited β never file contents.baton serve --hostlikewise binds a public interface only when you explicitly ask it to. -
Two commands fetch a URL, and both are ones you typed.
baton join <url>reads a workspace manifest from a host you name, andbaton skills import <url>downloads a skill you point it at. Neither runs on its own, and neither uploads anything. - Your agents still talk to their own vendors. Claude Code, Cursor and the rest send your code to Anthropic, OpenAI and so on exactly as they always did. Baton neither adds to that nor can prevent it β it coordinates the agents, it does not sit between them and their APIs.
Everything above is checkable: the outbound calls are in src/host-link.ts, src/pipeline-claims.ts and src/remote-claims.ts, all gated on a host link you configured. See docs/security.md.
baton serve serves a realtime React dashboard at http://localhost:7077 β a Command Center board, live Activity, Conflicts, the Knowledge Graph, Memory, History, an Agents roster (with one-click MCP wiring), and the Skills catalog. It binds to 127.0.0.1 only and is read-only until you pass --write. See docs/dashboard.md.
No β Baton is terminal-first. You open your own terminals, run claude / cursor / codex yourself, and coordination happens through hooks + MCP tools + a local SQLite file. Start the dashboard only when you want to look:
| Works with no daemon | Needs baton serve
|
|---|---|
| Edit signals β sessions warn each other before touching a busy file (the edit hook writes them) | The dashboard UI + realtime (SSE) live view |
Shared memory, recall/save, orient briefs, baton bugs, reports, blame, handoff |
Knowledge-graph queries over MCP (the daemon hosts one shared graphify backend per project) |
| Graph rebuilds (git post-commit hook, incremental) | Interactive agent terminals in the browser |
The whole CLI: status, signals, pass/take, merge, doctor
|
Headless agent launch from the UI |
History, memory, and reports are plain files + git β so when you do open the dashboard later, the past is all there; only live uncommitted-edit activity from hook-less agents needs the daemon watching at the time.
Tip
π Read the docs on the web β baton-landing.vercel.app/docs
Cross-linked and nicer to read than raw markdown β start with How it works for the handoff flow, Use cases for real setups, or the FAQ.
Home Β· Docs Β· Features Β· How it works Β· Use cases Β· FAQ Β· About
The same docs also live in this repo under docs/:
- Installation Β· Quickstart Β· CLI reference
- Dashboard Β· Knowledge base Β· Session handoff
- Skills Β· Project memory Β· MCP tools Β· Agent routing
- Configuration Β· Security model Β· Architecture Β· Troubleshooting & FAQ
-
Zero-dependency daemon β
src/server.tsis rawnode:http. No express, no fastify. - Realtime is SSE, not socket.io β every live event flows through one bus.
- Git-native β no external database; a small local SQLite index over your real git history. All git runs shell-free through a hardened wrapper.
-
Loopback-only + write-gated β the daemon binds
127.0.0.1, and every mutating request requires a loopback origin and (mostly)--write. See the security model. -
Strict TypeScript in two workspaces (root +
web/).
Baton is open source (AGPL-3.0) and contributions are welcome β the project is deliberately easy to hack on:
- Orient first: STATUS.md is the living map β what's built, what's pending, and where every module lives. docs/architecture.md explains the shape; CLAUDE.md lists the conventions that must not break (zero-dependency daemon, SSE-only realtime, shell-free git).
- How changes land: every feature is TDD'd (the test exists and fails before the code), and non-negotiable behaviors are guarded by invariant tests β if a future edit drops a safety rule from a bundled skill, the suite fails loudly.
-
Good first contributions: an agent adapter (add your CLI to
src/agents/registry.ts), a bundled skill (src/skills/bundled/<id>/SKILL.mdβ the loader auto-discovers it), a language check against your stack, or a docs fix.
npm install && npm install --prefix web
npm run build && npx vitest run # backend build + full test suite
npm run build --prefix web # dashboard build
node dist/cli.js serve --write # run it locally on :7077
npm run dev --prefix web # UI dev server :5173 (demo data ON)Open a PR against main with tests. If you're changing coordination behavior, run the suite a few times β flaky is treated as broken here.
AGPL-3.0-or-later Β© Rakshan Shetty. See LICENSE.
Use it, change it, run it commercially β all fine. The one condition: if you distribute Baton or run a modified version as a network service, the people using it get the source under the same terms. That second clause is the reason this is AGPL and not GPL β Baton is a daemon with a web dashboard, so hosting it without ever shipping a binary would otherwise be a way around the license.
Baton was MIT until 2026-08-07. Copies taken before then keep their MIT grant β relicensing does not reach backwards. Contributions are accepted under the terms in CONTRIBUTING.md.