Skip to content

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.

ArgumentNotesWhat it is
--symptom SYMPTOMrequiredwhat does not work — a phrase, never a fix
--why WHYrequiredone sentence, ending in a stop: why it matters
--block BLOCKdefault "F"the block of roadkeep's own backlog this belongs under (default: F)
--without PARTrepeatable; default []; one of command, engine, where, config, source, document, output, traceback, environmentdrop one part of the capture, repeatable: what a private repository must not publish is deleted by name, never scrubbed by a filter
--issuedefault falseprint the tracker body on stdout and the command that files it on stderr; nothing is sent, and the destination is [report] upstream
--to OWNER/REPOfile against this repository instead of the configured upstream
--embeddefault falsecarry the governed files this project declares, so the capture can be replayed without this repository — a test somewhere else, and files leaving here
--jsondefault falsemachine-readable form
-- COMMANDrequiredthe 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.

ArgumentNotesWhat it is
pathrequireda capture written by `report --json`
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
pathrequireda capture under .roadkeep/reports/
--as IDrequiredthe 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
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
--checkdefault falsesay what would go and leave the directory alone
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
--prefix PREFIXrepeatablethe id prefix, uppercase alphanumeric (default: RK). Repeatable for a backlog numbered by track; the first is what `add` mints under
--block LABELrepeatablea block heading, repeatable: 'A' or 'A — The model'. A task is filed under a heading and a write never invents one (default: A)
--strategydefault falsescaffold 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
--deferreddefault falsescaffold 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
--existingdefault falsedeclare 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
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
rolerequiredwhich 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 PATHwhere it goes, project-relative (default: this role's own docs/ path)
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
pathrequiredthe file to measure, e.g. docs/ROADMAP.md
--prefix PREFIXrepeatableread 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_SCHEMEone of id, outlinemeasure the pointers under this scheme: 'outline' asks what adopting the tool costs, 'id' what adopting it and renumbering the outline costs
--ledgerdefault falsemeasure it as a changelog: shipped marker, no deps field, no pointer
--sectionsdefault falsemeasure 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 PATHrepeatable; 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
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
--checkdefault falsewrite 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 PATHthe 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-mergedefault falsewire 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
--committeddefault falsewire 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
--vendordefault falsecopy 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
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
--invokedefault falseprint only the command that reaches the copy wired to this project, so a shell invocation needs no directory listing to find it
--jsondefault falsemachine-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.

ArgumentNotesWhat it is
--checkdefault falsetake nothing out and exit 1 while anything is still wired: the same tense `install --check` reports in, on the other direction
--jsondefault falsemachine-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.