skip to content
agentmash get started
docsset up your repo

start

set up your repo

To see it first, agentmash.dev/how plays a made-up team of four in your browser: who is in which file, and what each agent is told before it writes.

Your team — connect once, sign in once:

  1. Connect the repository. Someone who can push to it signs in with GitHub at agentmash.dev/install and picks it. That is all the repository needs: nothing is committed to it and there is no pull request. It gets one live room, and connecting it again — or a teammate connecting it — opens the same one.

  2. Each developer, once per machine:

    npx agentmash login

    It opens GitHub in the browser; after signing in there they type the code the terminal shows (ABCD-EFGH), so a sign-in link sent to someone else gives its sender nothing. Then it puts AgentMash's hooks in their own Claude Code settings (~/.claude/settings.json, never a repository) and keeps a sign-in token in ~/.agentmash/. That is their whole setup, for every repository they can push to that anyone on their team has connected — including ones connected later.

    It connects every other coding agent it finds on the machine the same way, in that agent's own settings and never a repository, with the MCP server beside the hooks: Codex (~/.codex/hooks.json), Cursor (~/.cursor/hooks.json), and GitHub Copilot in VS Code and in its CLI (~/.copilot/hooks/agentmash.json). Devin needs nothing of its own: it runs the hooks in Claude Code's settings. The other agents it knows each get the generic hook in their own settings, and Continue and Zed their MCP server alone; which file each one gets is in docs/ADAPTERS.md, and Antigravity is connected only when asked for by name (npx agentmash tools add antigravity). It prints a line for each, connected, already connected or skipped and why; --skip codex leaves one out, and npx agentmash tools lists them later, with tools add <id> and tools remove <id> to connect or take out one at a time. Codex runs no hook until you approve it: open codex, type /hooks, and approve agentmash, once. The commands it approves never change from one version of agentmash to the next, so an upgrade does not ask again. Cursor drops what a hook adds to its agent's context, so there the warning before an edit comes as a refusal of the first edit of a file a teammate is in, with the advisory as its reason; the same edit again goes through.

  3. Restart Claude Code. From the next prompt on, every prompt (the first 500 characters) and every edit goes to the room, and the live view shows them. Before an agent edits a file a teammate's agent just changed, it is told who changed it, what changed and why. And when a teammate's agent is at work on the same branch, or in a file the session changed, the agent gets a short heads-up — when the session starts, and at a prompt, at most once every ten minutes and only when that is news.

Who gets into a room is decided by GitHub: anyone who could push to the repository when they last signed in, if that was within the last seven days (AGENTMASH_PUSH_ACCESS_DAYS). After that the room stays shut to them until they run npx agentmash login again, so someone removed from the repository loses its room within the week. A hook in a checkout finds the repository from its origin remote, asks the server which room it is connected to, and signs with the developer's own token — there is no room key on the machine and no link to keep secret. A repository that nobody connected is left alone, and so is one that carries its own install (below). npx agentmash status in a checkout says who you are signed in as and whether that repository is connected; npx agentmash logout takes it all back out.

A repository that carries its own install has a room already: the one init committed, which every clone reports to. Connecting it on the website connects it to that room, never a second one beside it, as long as the committed key opens a room on this server. If it was connected to another room before, status, login and doctor in a checkout say "two rooms", and npx agentmash connect there puts it right: it connects the repository to the committed room, for everyone at once, with nothing to commit. A room it leaves that nothing was ever reported to gives way without asking; one that has had anything reported to it, however long ago, only with --replace. Either way it is never deleted, since a committed key may be in any clone, and it keeps what is in it for its owners.

A key committed to a public repository is anyone's who reads it, so init, join and rotate ask GitHub first, unauthenticated, whether each GitHub repository the checkout has a remote for is public (one through an SSH host alias named for GitHub, like git@github-work:acme/app.git, too), and stop when one is: connect it on the website instead, where only people who can push get in and nothing is committed. --allow-public-key commits the key all the same, and says what anyone who reads the repository can then read; with no GitHub remote, or no answer from GitHub, they go ahead and say so in a line. For a key committed before that, the server asks GitHub the same of every repository a room is connected to (at most AGENTMASH_GITHUB_CHECKS_PER_HOUR times an hour, each repository at most once a day, and while a request waits only before a key disconnects its room) and learns it from every sign-in's list too. A room disconnected before GitHub answered stays judged by the repository it left until GitHub has. When the answer is public, the room's key opens it only beside the sign-in of someone who can push there: npx agentmash login on the machine, which the hooks, the MCP server and the CLI send beside the key, or a browser signed in on the website for the dashboard. Anyone else is turned away with 403 room_key_public, and the key stays that way if the repository goes private later; npx agentmash rotate mints one that never was public. GitHub not answering changes nothing. A room that was never connected to any repository can't be judged: its key opens it on its own, wherever the key is, so connect the repository, or rotate.

Which repository that is goes by every remote of the checkout, not origin alone: in a fork, origin is your own and upstream the team's, and a remote through an SSH host alias (git@github.com-work:acme/app.git) names its repository by its path. With remotes for more than one GitHub repository, connect binds only the one you name, npx agentmash connect acme/app, and init leaves it to you; it never picks your fork by itself. A fork connected on the website gets a room of its own, never the one its copied config.json names, and connect in a checkout of a fork is refused, with origin alone too: GitHub says which repositories are forks when you sign in, and a fork's checkouts report to that room by its key anyway. And init on a signed-in machine makes no room for a repository that is connected already: it says where its room is, and --force then npx agentmash connect --replace is how to commit one all the same.

Or let Claude do it: agentmash.dev/setup is one prompt to paste into Claude Code. It runs the login, checks the repository you are in, and tells you what is left; the same prompt is plain text at /setup.md for an agent that fetches it.

Or commit it to the repository — the older way, for a server without GitHub sign-in:

npx agentmash init

and the dashboard opens itself in your browser (--no-open to skip). Until someone's agent has edited something it shows three things to do next, each with a copy button: make an edit, commit the hooks so your team gets them by pulling, and turn diff streaming on. A bare npx agentmash in a repo that is not wired up says the same in two lines.

npx fetches the published agentmash package — no clone, no global install, Node 18 or newer. It creates a room, installs the hook scripts and the MCP server with its launcher into .claude/agentmash/ (the package carries its own copy of them), registers the hooks in .claude/settings.json without disturbing what's already there, registers the MCP server in .mcp.json, writes the room config beside them, installs the git post-commit client into this checkout, and prints your dashboard link. (If your repo sets core.hooksPath to a directory in the working tree — .githooks/, husky, lefthook — the git client is not installed: writing there would commit AgentMash to your whole team. Nor when core.hooksPath comes from your global or system git config, a ~/.githooks every repository runs its hooks from: a hook written there would run for every repository on the machine. init says which, and carries on; --force-hooks-path overrides either, and a hook put in a shared folder that way is taken out again only by uninstall in the repository that put it there.) Commit it:

git add .claude .mcp.json && git commit -m "add agentmash" && git push

Your teammates: git pull, and approve the MCP server once.

The hooks, the MCP registration and the room travel with the repo, so their next Claude Code session joins automatically — nothing to install, no token to paste, no config to write. Claude Code picks up new hooks on its own; restarting the session is the sure thing. The one thing each teammate does by hand is answer Claude Code's prompt to approve the MCP server this repo registers; AgentMash does not answer it for them, and the hooks work either way — see How it reaches your teammates.

.git/hooks is not committed, so the git client is the one thing that does not arrive with a pull. Each teammate runs npx agentmash git-hook install once; doctor says so when it is missing. Teammates on Cursor run npx agentmash login, which connects it at user level, or wire up the adapter in the repository.

The dashboard is served by the coordination server itself, at the link init printed: https://<your-server>/r/<room-id>. Nobody runs a build. A sidebar holds the pages — live, people, changes, collisions (right now, and by place), history (blocks of work, and the event feed) and settings — with the room itself at its foot. Pages switch from the sidebar, with the keys 1–6, with ctrl/cmd+K (jump to any page, person or file), or by hash (/r/<room-id>#history/24h, #collisions/places/7d). The window is in the link as well as the page, so a link opens on the week you were reading and not on somebody else's default; links from before the pages had these names (#board, #zones/7d, #timeline/24h) still open the page they meant. On a phone the sidebar folds into a drawer.

Settings are read in the browser and changed in the repo. Each setting shows its value and, behind change, the exact npx agentmash … command to run where the room key is. A link with the key reads the room's own settings with the key in a header; a room opened by signing in reads what its owner can see and says which values take the key.

Or sign in and skip the link. On a server with GitHub sign-in configured, /rooms lists the rooms that belong to your account and opens each dashboard at /r/<room-ref> — the non-secret ref, not the key — so there is no link to keep safe and nothing in the address bar worth stealing. A room you connect on the website is listed for you and for everyone who can push to its repository; one made with npx agentmash init joins the list when you paste its room id into that page once. Signing in opens exactly what the dashboard reads (/activity, /events, the live socket) and nothing else: reporting, rotating, purging and deleting still take the room key. You stay signed in for 30 days and across deploys; the GitHub token that came with the sign-in is held in memory for two hours and never written down, so connecting another repository after that asks you to sign in again.

The CLI and the web installer write the same bytes — the same hook scripts, the same settings.json merge, the same config.json — so it doesn't matter which one a team uses. That is enforced by a test, not by care: the packaging tests install the built tarball into a scratch directory and diff every file it writes against the server's own install plan.

Commands

CommandWhat it does
npx agentmash initCreate a room and wire up this repo
npx agentmash join <id|url>Point this repo at an existing room
npx agentmash doctorCheck exactly what is and isn't working
npx agentmash statusWho is working on what, from the terminal
npx agentmash git-hook installInstall the post-commit client in this checkout
npx agentmash git-hook uninstallRemove it, restoring any hook it replaced
npx agentmash rotateIssue a new room key; the old one gets a grace period
npx agentmash revokeEnd that grace period now
npx agentmash loginSign this machine in with GitHub: AgentMash for every connected repository you can push to
npx agentmash logoutSign this machine out and take agentmash back out of every agent it connected
npx agentmash tools [add|remove <id>]The coding agents on this machine (claude, codex, cursor, copilot, devin, amp, antigravity, cline, crush, droid, gemini, goose, junie, kilo, kiro, opencode, openhands, qwen, continue, zed): found, connected, Codex's hooks approved; connect or take out one
npx agentmash token <create|list|revoke>Personal API tokens for the public API, made with this machine's sign-in; create prints the token alone on stdout
npx agentmash hook --print-command --client <id> --event <event>The line to register in a tool's own hook settings, for a tool agentmash has no connector for: the generic hook, in the dialect it reads
npx agentmash connect [owner/name] [--replace]Connect this repository, on the website, to the room it carries, so login and the website open it too; name it when the checkout has remotes for more than one
npx agentmash disconnectStop this room opening to everyone who can push to the repository it is connected to
npx agentmash login --roomIn a committed install, prove this machine is you (optional)
npx agentmash secure <off|any|github>Require proven identities to write
npx agentmash reconcile <approve|auto|off>Whether a finishing session that overlaps a teammate's says so (it only ever advises)
npx agentmash diffs <on|off>Stream the changed text to the live view (off by default)
npx agentmash auditWhat was read and changed, by whom
npx agentmash purge <prompts|events>Delete what the room collected
npx agentmash delete --yesDelete the room outright
npx agentmash uninstallRemove the hooks and the MCP registration from this repo
npx agentmash team add <name> --agents <a,b|all>Put agents from the crew in this repo as a named team
npx agentmash team remove <name> [--agents <a,b>]Remove a team, or only the agents given
npx agentmash team list [--json]The teams installed in this repo
npx agentmash team updateRewrite the team files from the crew version this CLI carries
npx agentmash mcpServe the MCP tools on stdio — the same server .mcp.json starts from .claude/agentmash/

The digest is not a command of this CLI, and not available to customers yet: it lives in its own workspace (digest/) of the private AgentMash repository and is not published to npm — see Weekly digest.

doctor is the one to reach for when someone's events aren't showing up. Because hooks fail silently by design, it's the only thing that will tell you why — it resolves the config and shows where each value came from, checks the hooks are registered, measures the round trip and compares it against what a cold hook would need, validates the room, reports whether the git client is installed, and lists the teammates it can see.

from README.md, “Setup”