Adopting and installing
These run before the project is governed, which is why most of them are not offered to an agent mid-session: their subject is a file this tool does not own the writes to yet.
init scaffolds the files and a roadkeep.toml beside them, and init --existing is the
same write over a repository that already has a backlog — the ordinary case, because a
repository with a ROADMAP.md in it is exactly the one worth adopting. A file that is already
there is declared rather than written, only what is missing is scaffolded, and the prefix and
the blocks are read off the roadmap instead of typed. declare retrofits one role onto a
project past that point.
adopt is the read to run before either. It measures a foreign file — how many lines it
holds, how many would be refused by the limits a scaffold would write, and what the spread
looks like — so the decision is made against a number rather than a hope. It is asked once and
never again.
install wires the tool into a checkout: the hook, the gate and the merge driver. engines
answers which copies of roadkeep are present and which of them writes, judges, gates and
merges — the read for the confusion where a plugin cache and a checkout disagree about what
the tool does.
report and replay are a pair, and their subject is a defect in this tool rather than
in a backlog: report files what happened as facts, argv already substituted, and replay
re-runs them to say whether it still reproduces. capture is what became of the ones on disk.
mcp and guard are transports, not questions. One speaks a protocol to a client and the
other answers a hook payload on stdout; what either dispatches is the same parser every
command on this site is generated from.
report
Reads.
Re-run the command that failed, in this process, and emit what identifies the defect: the argv, the exit code, the engine that answered, this project's roadkeep.toml, the line the engine objected to and any traceback. The two facts a machine cannot supply are arguments and are refused here against this tool's own schema, so a report arrives inside the limits the backlog it is destined for enforces. Nothing is sent: the capture is printed, and delivery is a separate decision.
| Argument | Notes | What it is |
|---|---|---|
--symptom SYMPTOM | required | what does not work — a phrase, never a fix |
--why WHY | required | one sentence, ending in a stop: why it matters |
--block BLOCK | default "F" | the block of roadkeep's own backlog this belongs under (default: F) |
--without PART | repeatable; default []; one of command, engine, where, config, source, document, output, traceback, environment | drop one part of the capture, repeatable: what a private repository must not publish is deleted by name, never scrubbed by a filter |
--issue | default false | print the tracker body on stdout and the command that files it on stderr; nothing is sent, and the destination is [report] upstream |
--to OWNER/REPO | — | file against this repository instead of the configured upstream |
--embed | default false | carry the governed files this project declares, so the capture can be replayed without this repository — a test somewhere else, and files leaving here |
--json | default false | machine-readable form |
-- COMMAND | required | the roadkeep command that failed, after a bare --, without the program name |
replay
Reads.
Stage the capture's own configuration and file in a scratch directory, run the argv it recorded, and answer whether the defect still reproduces. Nothing from the reporting project is needed: a capture that was never made replayable says which part it lacks instead of being staged from a guess. Exits 1 when the answer differs from the `reproduces` the file records — which is what makes a corpus of field reports a gate rather than a folder.
| Argument | Notes | What it is |
|---|---|---|
path | required | a capture written by `report --json` |
--json | default false | machine-readable form |
capture
A group of the verbs under it.
The third of the capture pair's family (RK1142). `report` writes one and `replay` re-runs it; this says what happened to one that is already there — which task it was filed as, and whether that answer makes it spent. The retention `keep` parked arrives here as `sweep` (RK1394), in its exact half only: rotation, an age limit and a dedup by argv are still open, and they are what a capture that never gets a stamp waits for.
capture filed
Writes.
Write into the capture the id it was filed as, so the row `stats` counts is cleared by a fact in the artefact rather than by a symptom that matches (RK1141). `add --capture` does this for a capture being filed now; this is the door for one already on disk, and it is the whole of what RK1142 was: clearing this repository's own row took a `python -c`, which is what L5 exists against. Refused where no governed file holds the id — a stamp naming nothing is a link to nothing — and where the path is not a capture this tool wrote. An id **qualified by a repository** is the exception (RK1160): a defect in roadkeep is filed in roadkeep's backlog, so no local file will ever hold that id, and both readers left a row nothing could clear.
| Argument | Notes | What it is |
|---|---|---|
path | required | a capture under .roadkeep/reports/ |
--as ID | required | the task it was filed as, e.g. RK1138 — refused unless a governed file holds it, or `owner/repo#ID` for one filed in another backlog this project cannot read |
--json | default false | machine-readable form |
capture sweep
Reads.
The retention `keep` parks, keyed on the fact the artefact already carries (RK1394). A capture whose `filed` id the ledger records as shipped is answered by this repository's own record, so it is deleted; every other state is named and left. An age limit would be the weaker key — it says time passed where a stamp says the work landed — and it deletes exactly the captures an exact reading protects: one never filed, one open, and one delivered to a backlog this project cannot read. `--check` prints the same table and removes nothing.
| Argument | Notes | What it is |
|---|---|---|
--check | default false | say what would go and leave the directory alone |
--json | default false | machine-readable form |
init
Writes.
Write the configuration and the three governed files, or write nothing. The config is rendered from the schema's own defaults, so a scaffold cannot declare a format the tool does not implement. No starter task and no prose: a title, the blocks you name, and where the non-goals go.
| Argument | Notes | What it is |
|---|---|---|
--prefix PREFIX | repeatable | the id prefix, uppercase alphanumeric (default: RK). Repeatable for a backlog numbered by track; the first is what `add` mints under |
--block LABEL | repeatable | a block heading, repeatable: 'A' or 'A — The model'. A task is filed under a heading and a write never invents one (default: A) |
--strategy | default false | scaffold the strategy file too: a prose role for a document that outlives every task filed under it, where an improvements section is one task's rationale and goes when the line ships |
--deferred | default false | scaffold the deferred store too: the file `defer` moves a line to, which keeps the id, the deps and the section a retirement deletes. Without it that verb refuses, and the remedy is a toml key and a skeleton written by hand |
--existing | default false | declare the governed files that are already there instead of refusing over them, and scaffold only the rest: the door onto a repository whose backlog somebody kept by hand. The prefix is read off the ids the roadmap carries and the blocks off its headings, unless --prefix or --block says otherwise |
--json | default false | machine-readable form |
declare
Writes. Served to an agent as declare.
Write one role's file and the `[files]` key governing it, or open an opt-in table, on a project past `init`. Reach for it when a verb refuses over an undeclared role or table: `init` writes both once and refuses to run twice, so either declined at scaffold time was otherwise a hand edit. A role's file arrives with the block headings the roadmap carries, spelled as that file spells one; a table arrives empty, which is what opting in means, and `govern` tunes what is in it. The config keeps every other byte. Refused where it is already declared.
| Argument | Notes | What it is |
|---|---|---|
role | required | which governed file to declare, one of roadmap, changelog, improvements, strategy, deferred, decisions — or an opt-in table to open, one of non_goals, criteria |
--path PATH | — | where it goes, project-relative (default: this role's own docs/ path) |
--json | default false | machine-readable form |
adopt
Reads.
Run the schema over a backlog this tool does not own yet and report the delta: what parses, what conforms, the longest field against its limit, the markers to declare. Writes nothing and never fails — an estimate that exits 1 is a gate, and the point is to take it before the commitment.
| Argument | Notes | What it is |
|---|---|---|
path | required | the file to measure, e.g. docs/ROADMAP.md |
--prefix PREFIX | repeatable | read the ids under this prefix, repeatable for a backlog numbered by track; without it the project's own is used, or the one the file's ids already spell — never all of them, which is a judgement and not a count |
--ref-scheme REF_SCHEME | one of id, outline | measure the pointers under this scheme: 'outline' asks what adopting the tool costs, 'id' what adopting it and renumbering the outline costs |
--ledger | default false | measure it as a changelog: shipped marker, no deps field, no pointer |
--sections | default false | measure it as a rationale file: sections against `section`, and the width its prose is already wrapped to — the two limits an adopter has to declare |
--with PATH | repeatable; default [] | another prose file an address could be doubled across, repeatable — the one measure here that is about a set of files rather than this one; requires --sections, and never inferred from the directory |
--json | default false | machine-readable form |
install
Writes.
Write the surfaces the plugin ships, for a project that runs roadkeep from a checkout instead: the server, the guard on its three hook events, and the skill that says which command to call — plus the CI workflow when the repository already has one. Every byte is translated from what the plugin carries, the launcher's path being the only substituted fact, so the skill cannot drift from the file it was copied from. The skill is refreshed on every run; the declarations keep everything they hold that is not this project's entry; the workflow is written once and then yours.
| Argument | Notes | What it is |
|---|---|---|
--check | default false | write nothing and exit 1 on anything that would change: the gate that keeps the copied skill in step, for a CI job or a pre-commit hook |
--source PATH | — | the roadkeep checkout to wire in (default: the one this command is running from, which is the one whose hook and tools the project would get) |
--register-merge | default false | wire the merge driver too — the `.gitattributes` half of `merge --register`, with the `git config` line printed for you to run: a flag and not a default, because it is configuration and the other half is outside these files |
--committed | default false | wire a launcher committed to this repository instead of a path to the checkout, so the guard reaches an environment that installs no plugin and clones no checkout — Claude Code on the web. It defers where the harness has the plugin wired for this project, and never blocks a turn |
--vendor | default false | copy the highest-versioned roadkeep this machine can reach into .roadkeep/, so the project runs a pinned engine instead of whichever copy a search order reaches first; ROADKEEP_SRC names a working checkout, which is otherwise skipped |
--json | default false | machine-readable form |
engines
Reads. Served to an agent as engines.
An adopting project wires three: the plugin its hook and skill run, the action its workflow gates on, and whatever `roadkeep` the caller invokes. A fourth is vendored under .roadkeep/, which the launcher finds first, and a fifth is read and never judged: the merge driver, a command and not a version. They may differ — a cache lags a checkout — and what is not survivable is not knowing which answered. Exits 1 where two state different versions.
| Argument | Notes | What it is |
|---|---|---|
--invoke | default false | print only the command that reaches the copy wired to this project, so a shell invocation needs no directory listing to find it |
--json | default false | machine-readable form |
uninstall
Writes.
Un-wire a project that ran roadkeep from a checkout — moving to the plugin, or off the tool entirely (RK138). The inverse of `install` under the same two rules: the declarations keep every entry that is not this project's, and a file that is not a JSON object is refused rather than rewritten. A file left holding nothing but what `install` wrote is deleted, because that is the state it was created from. It reads no checkout — the wiring is recognised by the server's name and the launcher a hook runs — so a project can be un-wired after the tree it pointed at is gone. The CI workflow stays: that gate calls the published action and not the checkout.
| Argument | Notes | What it is |
|---|---|---|
--check | default false | take nothing out and exit 1 while anything is still wired: the same tense `install --check` reports in, on the other direction |
--json | default false | machine-readable form |
mcp
Reads.
Speak JSON-RPC on stdin and stdout so the fields arrive as a schema the client validates instead of flag names an agent types from memory (RK24). Every tool is dispatched through this same parser, so the refusal is the one a terminal prints. Not for a human to call: a session's client starts it.