kane-cli context builds a local, content-addressed knowledge store (.context/ in your project directory) from your requirement documents, and extracts use-cases from them with an AI agent. It is the first stage of the assurance lifecycle: Source → Use-case → Scenario → AC → Test.
context ingest — snapshot your sources
.context/ (the store is created on first use). A source is a file path or a remote URL — a Jira issue, a Confluence page, a Linear issue or document, or a public web page. See Requirement Sources for every accepted type.
Snapshots one or more files into .context/ (the store is created on first use) and then extracts them (0.7.1):
- On a terminal, the run continues straight into the interactive extract chat.
--mode agentextracts headless on the NDJSON stream (oneingestedevent per landing, before the extraction begins — see Automation);--mode overrideextracts headless too, auto-taking every default.--mode ci— or piped stdin without a--mode— lands only: the files snapshot, nothing extracts, exit0, with a guidance line on stderr telling you what to run next.--plan,--force, and--trustpass through to the extraction; they refuse under the land-only modes.
landed prd (prd.md) — new source); ci/piped runs keep the byte-exact script contract below. (0.7.2) Under --mode agent nothing prints outside the stream — the landing receipt is the ingested event itself.
prd-online-store.md → prd-online-store), or the issue key for a ticket (ENG-42 → eng-42). Pass --as <id> to name it yourself.
Ingest is deterministic about identity:
--asrecords versions: a colleague hands youPRD-v2.mdof an existing sourceprd—ingest PRD-v2.md --as prdrecords it as a new version ofprd(head moves, dependents go stale).--asnames one identity, so it refuses more than one file.- Version suggestion (terminal only): ingesting
prd-v2.mdwhen a sourceprdalready exists prompts “looks like a new version ofprd— ingest asprd?”. Accept and it versionsprd; decline andprd-v2mints as its own source. Piped runs never prompt and never auto-link — pass--asexplicitly in scripts.
Accepted sources
Files: text and structured text up to 2 MB, images up to 5 MB, PDF and Word documents up to 25 MB. Remote sources, passed as a URL and requiring the matching connection on your account:UNSUPPORTED_MEDIA, and oversized files with FILE_TOO_LARGE. Every source type, with its size cap, citation granularity, identity rules and refusal codes, is documented in Requirement Sources.
A Jira
ENG-42 and a Linear ENG-42 both mint the id eng-42. A URL whose id is already backed by a different kind of source refuses and offers a recovery rather than replacing it silently.kane-cli maintain reconcile over a bare re-ingest — it records the same head move and triages what the change means for your suite, in one step.
context extract — propose use-cases
--force to redo one).
On a terminal the default is an interactive chat. Headless use is an explicit opt-in: a bare non-TTY invocation exits 2 and asks you to pass --mode agent|ci|override — see Automation for the headless contract.
What the agent does:
- Reads each source and proposes use-cases with verbose descriptions (flows, inputs, states, boundaries) and
criteria[]— short, cited sketches of the acceptance-relevant promises the source states. Criteria are hints forkane-cli design, never test oracles. - Cites everything. Every proposal must quote an exact line from the source; fabricated evidence is rejected before anything is written. (Image sources cite the whole image — there is no text to quote.)
- Asks when the source is ambiguous. Conflicting requirements become clarifying questions with options, a recommended default, and a risk level — low/medium-risk questions can be defaulted, high-risk ones want a real answer.
- Grounds itself in what you already have. The agent explores the existing graph read-only before proposing, so a use-case you already committed becomes new evidence on the existing node (shown as
≈ matches) instead of a duplicate.
The interactive chat
The chat has two zones. The scrollback is the complete session journey — your words, the agent’s narrative, its reasoning segments and tool lines, each proposal list as it arrived, answer receipts, commit receipts, and per-turn credit costs. The live region below shows only what is happening now: the current thinking line (ctrl+t expands it), the question panel, and the composer. Answering questions happens right in the composer:- Bare input answers the active question (marked
›), and the cursor advances:1picks option 1, typing an option’s name matches it, anything else is free text where allowed. N:targets question N explicitly (2: yes). Without the colon,2 business daysstays free text.- Empty Enter accepts the recommended defaults for low/medium-risk questions only — each is echoed back as
↳ assumed … (flagged). High-risk questions are never bulk-defaulted: answer them, or typedeferto leave the rest with the agent. - The batch submits when every question is answered, assumed, or deferred — never silently partial.
--message form) and the run exits 3. If the save can’t complete within a few seconds you get an honest interrupted — session not saved (exit 130, not resumable), and a second Ctrl+C at any point is an immediate hard exit. /pause does the same from the composer; /done ends the session cleanly.
Slash commands (everything else you type is conversation for the agent):
The review checklist
After the agent proposes, the same session walks you through a review checklist: space cycles approve / edit / reject / skip per item,e opens an edit form, and Enter commits the whole batch as one record:
- approve / edit → committed as
trusted - reject → committed + archived (kept on record, not deleted)
- skip → committed as
derived— queued for later review
Pausing and resuming
When the agent needs an answer you’re not there to give (or you Ctrl+C), the session is saved and the run exits3. Resume it any time within 24 hours:
--message answers in plain words — no question ids, no option indexes. The agent maps your statement to its own pending questions. A statement that answers nothing pending is treated as steering (“also cover the coupon path”). If your answer leaves a high-risk ambiguity standing, the run pauses again with refreshed questions.
Two structured alternatives to --message (0.7.1):
-
Answer by id —
--answer <question-id>=<option number | free text>(repeatable,--resume --mode agentonly). Each landed answer echoes as apanel_resolvedevent before the run continues: -
Land a source instead of answering —
--resume <sid> --with-source <path|url>lands the file or URL first and sets the pending batch aside (ask_deferredon the stream); the agent reads the new source and re-asks only what it didn’t settle. Only refs you provide can land — anything else refuses withINGEST_UNAUTHORIZED_REF.
context review — review outside the extract session
derived(default) — everything unreviewedskipped— strictly the items you skipped during an extract reviewarchived— resurrection candidates: an explicit approve restores trustdrift— a listing only (works without a TTY): nodes whose evidence is stale or orphaned, with their pinned sources — the re-extract worklist
--verdicts <file.json> is the one non-TTY write path: a JSON array of
resolution one of approved | edited | rejected | skipped | supersede (plus optional reason, edit, supersede_target). It is atomic: every ref must resolve and sit in a verdict queue, or nothing commits (exit 2). With --json, each landed verdict echoes as one NDJSON row. There is deliberately no auto-approve mode for review — trust requires a human decision.
Archives need explicit consent (0.7.1). A headless rejection no longer destroys anything: --verdicts holds rejected entries as non-destructive pending_archive facts (exit 0, with a loud summary). Actually archiving them requires --allow-archive and --because "<reason>" — the reason goes on the record. Under --mode ci, archives are refused under any flag (exit 2, atomic).
Structured verdicts (0.7.1) — the flag form for scripted single decisions: --approve <refs...> lands approvals; --skip and --defer record nothing and leave the items queued. The three are mutually exclusive with --verdicts.
Inspecting the graph
context list
--inferred shows only unreviewed (derived) nodes, --stale only stale or orphaned nodes (evidence pinned to an outdated snapshot, or no live source at all), --all includes superseded versions (hidden by default). --json emits one JSON object per line.
context view
--json prints the computed payload for scripting.
context explain
<ref> is a logical id (uc-manage-the-cart) or a cid.
context sessions
.context/sessions/ for 24 hours. list shows each with its pending-question count, expiry, and ready-to-paste resume command. show <sid> prints everything the paused agent is waiting on — the questions in full, any defaults it assumed in your absence, and both resume forms. clean garbage-collects expired sessions (clean <sid> removes one; --all removes everything).
Housekeeping
context retire
orphaned once no live source evidences them. Fully reversible via revert.
context name
uc-3, ac-12, …) is reserved for ids assigned at mint — name refuses it (exit 2).
context revert
context fsck / context rebuild
fsck verifies the full record chain and checks the read caches for drift (exit 1 on any issue) — run it whenever hands touched .context/ directly. rebuild wipes the derived caches and regenerates them from the verified records; it is always safe.
Destructive-verb rule: retire, revert, name --backfill, and rebuild prompt for confirmation on a terminal (default No) and require an explicit --yes headless. Read commands never create a .context/ store in a directory that has none — only ingest and extract do.
Trust and freshness
Freshness is orthogonal:
fresh / stale (the source snapshot moved) / orphaned (no live source evidences it) / superseded (this version was replaced). A stale use-case is still trusted — it just needs re-verification against the new snapshot, which is exactly what kane-cli maintain reconcile is for.
The store on disk
.context/ to your .gitignore when it creates the store inside a git repository: kane-cli context ingest, kane-cli context clone and kane-cli context sync doctor --export all do it, and say added .context/ to .gitignore once. When the line cannot be written, the store is still created and warning: could not add .context/ to .gitignore: <reason> says why, so add the line yourself. Set KANE_CONTEXT_GITIGNORE=0 to keep it out.
To share the store with your team, bind it to a location, a GitHub repository, an S3-compatible bucket, or a folder on a shared drive, and use kane-cli context push, kane-cli context pull, kane-cli context sync and kane-cli context clone. See Sharing the context graph with your team. A teammate who has pulled your records has the same use-cases, cited lines and review verdicts you committed, and nothing needs to be re-ingested.
.context/sync/ holds what sharing adds: the location list (no secret in it), a backup and a receipt for every rebase, and the location’s on-disk state for this machine.
Tracing a run
Every extract and design run prints atrace: <path> line naming its log file — the first place to look when a run surprises you.
Every extract run also writes a per-run trace to .context/logs/extract-<ts>.log (the path is printed at the start of the run) — the first place to look when a run surprises you.
For agents and CI
Headless extraction (--mode agent|ci|override), the NDJSON event stream, exit codes, and the pause/resume contract are documented in Agents and CI. A pipeline that works on a shared store clones it once, pulls before each run and pushes after: the sync verbs speak the same stream, see the sync verbs on the stream, and the CI shape is in CI/CD.
Next steps
- Requirement sources — every accepted file type and remote URL.
- Designing tests — turn a trusted use-case into ACs, scenarios, and runnable tests.
- Maintaining the suite — what to do when a source changes.
- Sharing the context graph with your team — one location; publishing, taking your teammates’ records, cloning, and what happens when two people change the same thing.
- Automation — the headless contract.