cruo-agent
v0.1.20
Published
Run a Cruo agent: it watches your board, picks up the cards you assign it, and works them.
Maintainers
Readme
cruo-agent
Run a Cruo agent. It watches your board, picks up the cards you assign it, and works them — on your machine, under your own account with the model's vendor: Claude Code by default, or Codex (GPT), Antigravity (Gemini) or Hermes Agent (GPT, Gemini, Grok, Hermes and open models).
npx cruo-agent login cruo_pat_… # the token Cruo showed you once
npx cruo-agent --dry-run # what would it pick up? starts no model
npx cruo-agent run # let it workBefore you start
| you need | check it with |
|---|---|
| Claude Code installed and signed in — it is the default harness, and the agent reaches no model without it. Using another model instead? See Choosing the model | claude -p 'say ok' |
| Node 20 or newer | node -v |
Worth ten seconds, because both failures are silent. A missing harness exits 127
with no output; a signed-out one prints Not logged in and exits zero. The
supervisor reports either as a run that reached no model and backs off — which
on the board is indistinguishable from having nothing to do.
npx cruo-agent … resolves the package on every run. If you are going to use it
daily, npm i -g cruo-agent puts cruo on your PATH and every command below
gets shorter. Typing cruo on its own prints the command list and starts
nothing: running an agent is cruo run, or any command with flags.
What this actually is
Three things people tend to run together, kept apart because they fail differently:
- The agent is a member of your workspace — a row and a token. It signs in to nothing, and nothing runs because it exists.
- The supervisor is this program. It watches the board with a plain database query, so sitting idle costs nothing, and starts a harness when there is work.
- The harness is the agent CLI that does the work — Claude Code unless you choose another — started fresh for one card and gone when that card is done. Nothing carries over between cards but the board itself.
Cruo runs no model of its own and never bills you for inference.
Choosing the model
--harness-kind picks which agent CLI works the card. Each runs on your own
account with that vendor; Cruo bills you for no inference either way.
| --harness-kind | models | needs | check |
|---|---|---|---|
| claude (default) | Claude | claude installed and signed in | claude -p 'say ok' |
| codex · preview | GPT, on your ChatGPT plan | brew install --cask codex, then codex login | codex exec 'say ok' |
| antigravity · preview | Gemini, on your Google sign-in | brew install --cask antigravity-cli, then sign in once with agy | agy -p 'say ok' |
| hermes · preview | GPT, Gemini, Grok, Hermes and open models | Hermes Agent with a provider key in ~/.hermes/.env; needs --provider and --model | hermes -z 'say ok' --provider openrouter -m openai/gpt-4o-mini |
cruo run --worktree --harness-kind codex --allow "mcp__cruo,Read,Edit,Write,Bash"
cruo run --worktree --harness-kind hermes --provider openrouter --model openai/gpt-4o-mini \
--allow "mcp__cruo,Read,Edit,Write,Bash"What each can touch outside the card's checkout — the thing to know before leaving one running unattended:
- claude — its file tools are held to the worktree; its shell (if
--allowincludesBash) is not, and known dangerous commands are denied by name. - codex — the strongest without a container. The operating system's sandbox
refuses writes outside the worktree and the git directories a commit needs;
.git/hooksand.git/configstay read-only, so a run cannot plant a hook that your own git would later execute. Reads are not limited. - antigravity — runs with
--sandbox: its terminal cannot write outside the workspace. Whether its file-editing tool is held to the worktree is not verified — Gemini declines to attempt a boundary test. Each run adds acruo-run-*server to~/.gemini/config/mcp_config.jsonand removes it after; a supervisor sweeps any a killed run left behind. - hermes — unconfined: its shell and file tools reach anything your user can. The supervisor says so at every start.
--allow stays the one knob for all four: it is mapped onto each harness's own
controls (Hermes toolsets; Codex and Antigravity drop to read-only / plan mode
when it names no write tool).
Preview means each has worked a real card end to end — claimed it, changed
the file, committed, moved it and commented, checked on the branch and the
board — but has not yet had the months of use Claude Code has. Codex's sandbox
was also checked on disk: writes outside the worktree, into .git/hooks and
into .git/config were refused while the commit still landed. --usage
records tokens only for Claude Code.
Getting a token
Cruo → Settings → Members → Add an agent. The token is shown once; Cruo stores a hash. If you lose it, issue another from the key button on its row.
Then assign the agent a card. That is the whole of the setup — an agent is a member, so it appears in the assignee list like anyone else.
Where the token comes from
In order: CRUO_TOKEN in the environment, then --token, then whatever
cruo login stored in ~/.cruo/config.json (mode 0600).
There is no cruo <token> form on purpose. A credential in a positional
argument shows up in ps output, where every other user on the machine can read
it, and in your shell history, where it stays. --token is there for a CI
runner that injects secrets its own way, and it warns.
Letting it write code
By default the harness gets the board and nothing else, which is right for an agent whose work is judgement over your issues. An agent that writes code needs a checkout and the tools to use it:
npx cruo-agent --worktree --allow 'mcp__cruo,Read,Glob,Grep,Edit,Write,Bash(git:*)'--worktree gives every card its own checkout, cut fresh from origin/main —
never the tree you are working in, and never whatever you have half-finished. It
carries tracked files only, so an agent cannot read a .env you have not
committed. When the run ends the checkout is deleted and the branch survives.
Run it from the repository the agent should work on. If that repository needs
installing before its tests will run, add --prepare 'npm ci' or whatever your
equivalent is — a fresh checkout has your source and none of your dependencies.
Checkouts go under ~/.cruo-work/<agent>, one directory per agent, so running
several agents at once needs no extra flags. --worktree-root overrides it if
you want them somewhere else; pointing two agents at one root is safe too, since
the sweep that clears abandoned checkouts at startup only removes ones too old
for any run to still be inside.
When it stops doing anything
A supervisor sitting idle costs nothing — it is a database query on a timer. If the harness refuses to work, though, the supervisor says so and slows down:
! the harness is refusing to work: the account's spend limit is reached
No card is charged for this, and polling backs off until it changes.That distinction matters more than it looks. A refusal is a fact about your
account, not about the card, so those runs are not counted against the
card's --max-attempts — otherwise one billing problem would quietly set aside
every issue the agent was holding, and you would come back to a board that had
given up on work nobody abandoned.
Common options
| flag | |
|---|---|
| --once | one pass, then exit |
| --dry-run | show what it would pick up; starts no model |
| --limit <n> | work at most n issues this pass |
| --interval <seconds> | how often to poll (default 20) |
| --worktree | a checkout per card |
| --allow <tools> | what the harness may use |
| --harness-kind <kind> | claude (default), codex, antigravity or hermes — see Choosing the model |
| --model <name> | the model the harness uses. Required for hermes; the others fall back to the account's default |
| --provider <name> | hermes only: where the model comes from, e.g. openrouter |
| --push | publish the branch after a run that commits |
| --harness-timeout <seconds> | kill a run that wedges (default 3000 — 50 minutes). It used to have to stay under an hour, because that is how long a run's board session lasted; since 0.1.17 the session is renewed under a running card, so what this bounds now is spend, not credentials |
| --max-attempts <n> | give up on a card after n unproductive runs (default 3) |
| --max-cost <dollars> | stop spending on one card once it has cost this much, and hand it to a human with what it has. Unset by default. Read from what the harness itself reported, so it only bites where those figures exist |
The full list, and what each is for: https://cruo.space/docs#agents
Running it somewhere that is not your laptop
The same command works on a server, and that machine needs no privileged access to Cruo: the supervisor trades its token for a short-lived session, so the only secret on the box is the agent's own token — scoped to one workspace, in one product, revocable from Settings.
The harness still runs under your Claude account, on that box.
cruo start survives the terminal closing, not the machine restarting. For that,
use what the box already has — a launchd agent on macOS, a systemd unit on Linux
— pointing at the same command. Both files are written out, filled in, at
https://cruo.space/docs#agents, along with the two traps that make them fail
silently: neither reads your shell profile, so every path must be absolute and
PATH must name wherever claude lives; and both restart what dies, so a token
the service cannot find becomes a crashloop rather than one loud error.
The name
The package is cruo-agent; the command it installs is cruo. npm refuses the
bare name as too close to cron and crc, and a bin's name is independent of
its package's — so npm i -g cruo-agent gives you cruo, and npx cruo-agent
works without one.
