Documentation
Install it, run a task, read the evidence. Everything on this page is what the CLI actually does — no layer between you and the commands.
Quickstart
Six steps from setup to a reviewed task. Any git repo, macOS or Linux.
Install
Homebrew, or direct downloads for macOS and Linux.
Set up the repo
init opens a guided setup in the dashboard — detect Claude, Kiro, and Codex, choose an implementer and an independent reviewer, and pick the checks that gate the work. Each agent has a Test connection button that validates it live: installed → authenticated → responds to a real prompt, reporting the first thing that’s wrong. Saving writes .selvage/config.yaml. Prefer the terminal? selvage init --cli.
$ selvage init
Trust the config
Config is untrusted input. You approve its digest once; if the config changes later, you’re asked to re-trust before it takes effect.
Start the pipeline
start validates each configured adapter with a live prompt and connects it to the daemon. Do this before your first run — a task submitted with no connected adapters waits at ready until one comes online. Check anytime with selvage nodes; if it’s empty, run start.
$ selvage nodes # confirm implementer + reviewer are connected
Run your first task
A description, or issue numbers — batches work in order. --local skips GitHub entirely. The command returns; follow with selvage watch. If a task sits at ready, your adapters aren’t connected — run selvage start.
$ selvage run 115
$ selvage run 115 130 136 --local
Read the evidence, then decide
Open selvage ui to inspect the diff, verification results, and review findings, then approve, request a revision, or reject the task. The same decisions are available in the terminal:
$ selvage approve 44
$ selvage revise 44 --reason "handle the 504 path"
What happens to a task
From the moment you queue it to the moment it’s yours to merge:
- Queued
Submitted to
selvaged, the daemon that schedules work across models. Your terminal is free the second the command returns. - Isolated
A
selvage/<task-id>worktree and branch exist before implementation — a failed run is still inspectable. Your working tree is never touched. - Implemented
An adapter drives the configured model — Claude, Kiro, or Codex — inside your repo, against your code and its conventions.
- Verified
The checks from
.selvage/config.yamlrun from the orchestrator, not the agent. Go tests run with-count=1, so a green run is fresh execution, not a cached replay. - Reviewed
A separate session — never the implementer — reads the diff and files findings. Findings go back to the implementer for revision.
- Reported
Diff, build, tests, review, approval state — all on the evidence chain.
selvage report <task>reads the ledger. - Gated by you
selvage approvepublishes per your config — or the branch simply stays local. There is no auto-push path.
Commands
Grouped the way the CLI groups itself. selvage with no arguments prints this same map; global flag --socket PATH (or SELVAGE_SOCKET) points at a non-default daemon.
| START | |
init | Guided dashboard setup: detect adapters, Test connection, write .selvage/config.yaml. --force re-opens it to replace an existing config; --cli uses the terminal flow |
register | Register a repository with the daemon |
start / stop | Bring the daemon and configured adapters up (with live validation) / shut them down. Run start before your first task |
nodes | List connected adapters. Empty means no implementer/reviewer is live — run start |
| DO | |
run | <issue|description> [more…] [--local] [--foreground] — queue one or more tasks; follow with watch |
ask | One prompt as a bounded task — "prompt" [--repo] [--base] [--effort] |
implement | Run a spec autonomously — --spec path.md |
status / watch | Terminal snapshot / live progress — watch [task-id] [--latest] [--dashboard] |
inbox / ui | Pending, landed, failed / web dashboard on localhost |
logs | Task logs |
report | The evidence — <task-id> [--output DIR]: diff, build, tests, review |
plan | Plan and scope an issue batch before running it |
usage | Usage and cost provenance |
adapters | <add|update|remove|list> — manage the models it drives (adapters doctor checks health) |
models | Model catalog |
index | build / query <provides|depends-on|exports|callers|callees|call-tree> — the structural code index the implementer is oriented with; opt in via SELVAGE_CODEINDEX=1 |
metrics | Throughput, phase timings, and lease outcomes |
ab-cost | Measured A/B of cost-to-done and revision counts across two sets of already-run task ids — --off IDS --on IDS [--feature TEXT] |
epic | Run a multi-issue epic as one dependency-ordered batch |
| DECIDE | |
approve | The human gate — TASK_ID; publishes per config |
accept | Accept a task — <task-id> [--dry-run] |
revise | Send it back with a reason — TASK_ID --reason TEXT |
reject | Close it out with a reason — TASK_ID --reason TEXT |
re-review | Re-run the independent review |
resolve | Record an operator decision on a blocking finding |
signoff | Acknowledge a major finding you have judged acceptable |
override | Override a routing or policy decision, with the reason recorded |
| TIDY | |
task | cancel | retry | recover | overage — task-level operations |
trust | Approve the config digest — [--repo PATH] |
clean | GC stale runtime state (alias gc) |
daemon | serve | status | stop — the daemon directly, when you are not using start/stop |
mcp-server | Expose selvage (or just its code index, with --index-only) over MCP to another agent |
Adapters — the CLIs it drives
Selvage does not call model APIs. It drives coding CLIs you have already installed and authenticated, one process per role, so your existing subscription and auth are the ones being used. selvage init detects what is on your PATH; selvage adapters list shows what the current config resolves to, and selvage adapters doctor checks each one is runnable and authenticated.
| SUPPORTED CLIs | |
claude | provider anthropic — reports real per-run cost and token totals through --output-format stream-json |
kiro-cli | provider kiro — reports credits; token and dollar fields are marked unsupported rather than guessed |
opencode | provider opencode — any provider you have authenticated inside OpenCode, including local and Cloudflare Workers AI models |
codex | provider openai |
OpenCode
OpenCode is a useful adapter when you want a model that is not behind one of the first-party CLIs — a local model, or a hosted one such as Cloudflare Workers AI — without Selvage needing its own provider integration.
1. Authenticate a provider inside OpenCode first. This is the step people miss: opencode --version succeeding only proves the binary runs. Selvage checks opencode providers list and refuses setup unless at least one provider is authenticated, because an unauthenticated OpenCode fails at the first lease instead of at setup.
opencode providers list # must show at least one authenticated provider
opencode models # the model ids you can use below
2. Add the adapter. Interactive, which reads the model list from opencode models for you:
3. Or write it directly in .selvage/config.yaml. Model ids are the fully qualified ones OpenCode prints, provider prefix included:
- kind: exec
node-id: opencode-impl
role: implementer
provider: opencode
model: cloudflare-workers-ai/@cf/zai-org/glm-5.3
profile-id: opencode/cloudflare-workers-ai/@cf/zai-org/glm-5.3
max_concurrent_leases: 1
command: ["opencode", "run", "--pure", "-m", "{model}"]
extra_flags: ["--completion", "commit", "--timeout", "30m"]
Three details matter. --pure keeps the run non-interactive and free of your local OpenCode session state. {model} is substituted from the model field, so the two never drift apart. And --completion commit tells Selvage this role finishes by committing, which is what an implementer must do — a reviewer omits it.
Then selvage trust to approve the changed config, and selvage start, which validates every adapter with a live prompt before accepting work. A model that cannot answer a one-line prompt is caught there rather than three minutes into a task.
What you get back is provider-dependent. Cost and token reporting is only as good as what the CLI prints. Claude emits machine-readable totals; Kiro reports credits; OpenCode's footer varies by provider, and Selvage records what is reported and marks the rest unavailable rather than inferring numbers. selvage usage shows the provenance for each figure, so an A/B measurement can tell a real zero from an unreported one.
Independence still applies: the reviewer must differ from every implementer that touched a task by node, profile, and provider, subject to minimum_independence. Running OpenCode as the implementer and Claude or Kiro as the reviewer satisfies it; the same OpenCode model on both sides does not.
Configuration
.selvage/config.yaml is created by selvage init: which adapters to drive, and which checks gate the work. Checks must defeat caches — the agent runs tests during implementation, so a verifier replaying cached results is just re-reading the agent’s own run:
go-test:
command: ["go", "test", "-count=1", "./..."]
timeout: 60s
go-vet:
command: ["go", "vet", "./..."]
timeout: 30s
The config is untrusted input: selvage trust approves its digest, and a changed config re-arms the prompt. Runtime state lives in XDG, never in the repo.
Local & hosted
Two ways to run it, one gate in both.
Local mode
From any project directory — no remote, no gh, no config file:
- Safe defaults in memory;
kiro-cliused when available - Detected build/test checks for Go, Node, Rust, Python
- Isolated
selvage/<task-id>worktree and branch - No issue lookup, no push, no PR — inspect with
git diff, merge manually
Hosted mode
The full workflow, in a repo with a GitHub identity:
$ selvage trust
$ selvage run 115
- Issue numbers resolve to real issues
- Adapters and publisher per
.selvage/config.yaml - Approve publishes per config — branch / PR
- Required before connecting an MCP client
MCP — connect your agent tools
One stdio server; the agent terminal you already use submits work, reads evidence, and files review verdicts inside the chat it’s in. The project must be trusted first:
selvage_submit_task | Submit a bounded task request |
selvage_implement_spec | Submit a spec for autonomous execution |
selvage_status | Read task states and progress |
selvage_get_evidence | Read diffs, verification results, review findings |
selvage_record_review | File a review verdict — revise or reject, never approve |
The hard rule: selvage_approve does not exist as a model-callable tool. An MCP client is an agent — if it could call approve, a model holds the human gate. Approval remains a human decision in the dashboard or terminal.
Claude Code — .mcp.json:
"command": "selvage",
"args": ["mcp-server", "--repo", "/absolute/path/to/repository"]
}}}
Codex and OpenCode take the same command in ~/.codex/config.toml / opencode.json — snippets on GitHub.
Guarantees
The invariants are architectural, not configurable — they survive every integration request and every “can we just…” conversation:
Review the evidence and approve in the dashboard or with selvage approve. MCP clients cannot call the approval action.
There is no flag that turns it on. Work lands only after you approve.
Independence guard: a different model, a different session, reads the diff.
Build and tests run from the orchestrator, cache-defeating. The agent can’t replay its own green run.
First use requires digest approval. Change the config and you re-trust.
Runtime state lives in XDG only — the repo stays clean.
Diff, tests, review, approval — all on the chain, readable with selvage report.
Everything else is convenience. The gates are the point.
FAQ
Does it ever push without me?
No. There is no auto-push — not behind a flag, not by default. Approval is a human decision in the dashboard or terminal.
Can a model approve a task?
No. selvage_approve has never existed as a model-callable tool. MCP review records are limited to revise or reject.
Who runs the tests?
The orchestrator, not the implementing agent — and checks defeat caches (Go: -count=1), so a green run is fresh evidence, not a replay.
Does it work without GitHub?
Yes — local mode needs only a project directory. A git repo gives you worktree isolation; a plain directory still records artifacts. No issue lookup, no push, no PR.
Which languages?
Build/test checks are detected for Go, Node, Rust, and Python. Anything else goes in .selvage/config.yaml under checks.
What exactly is the evidence?
The diff, build and test results, the review findings, and the approval state — on the chain, readable with selvage report <task>. If it’s not in the chain, it didn’t happen.