Changelog
All notable changes are listed here. The project follows Semantic Versioning; until 1.0 minor versions may change configuration or the entry format, always with a migration note.
0.10.2 (2026-11-01)
A brief you can read. With more governing entries than fit, a focused brief printed a wall of ids. Where every id fits it still prints them; past that it prints as many compact lines as fit, closest first, then +N more governing: ctx_why <path>. Nothing governing is dropped silently: the count says how many are left and how to see them.
ctx_brief costs what its budget says. Its structured result is {text, entries}, and entries are those the text names. The governing list repeated each focus path's lines beside the text, which took one call past 60 KB on a large store.
0.10.1 (2026-10-29)
Fix: a person's unstaged edit of an entry is a conflict, not a stale revision. drafts.extend, drafts.stage with amends, drafts.retire and drafts.revise checked the revision first, so an entry file with uncommitted edits in the checkout answered stale_entry ("read it again") instead of operation_conflict ("stage or revert your edits"), which 0.9.0 said. Now an unstaged or untracked change to the entry's file is reported first, as operation_conflict with "unstaged" in the message; a revision that moved in a commit or in what kontext itself staged is still stale_entry. Nothing else changes.
0.10.0 (2026-10-29)
Promises hold again: trust-pinned verify commands, honest verification, a brief that keeps every governing entry, a fresh index, additive amendments, and a 2026 MCP surface.
Security
verify:runs only after a pin. A command in an entry'sverify:field is code from the repository. It runs only whentrust.tomlholds a SHA-256 pin of the entry path and the command text ([repos.<slug>.verify]). Without one nothing runs:kontext verifyanddrafts.verifyfail withuntrusted_verify, whose error carriesid,command,command_sha256andhint(kontext trust --verify <id>). Editing the command drops the pin. Capabilitydrafts.verify.pinned.kontext trust --verify [<id>|--all]pins verify commands from an interactive terminal only and prints what it pins. No MCP tool and noctx_apioperation pins.- Over MCP an unpinned command is returned, not run, and so is a pinned one while the entry's file or governed paths have uncommitted changes (
ran: false,reason: untrusted_verify | dirty_tree). The agent runs it in its own sandbox; the result is recorded as anagentstamp, not asverify. - The runner passes an environment allowlist (
PATH,HOME,USER,LANG,LC_*,TMPDIR,TERM, plus[verify] pass_envfrom your own config only), redactsoutput_tail, names uncommitted governed paths in the ledger line ([dirty: <paths>], anddirty,dirty_pathsin the result), stops reading stdout 2 s after the shell exits and kills the process group. The MCP server kills a running check when stdin closes or the request is cancelled. ctx_verifyis annotateddestructiveHint: true,openWorldHint: true. Thedirofctx_verify,ctx_inboxandctx_prepare_commitis confined to this repository, its worktrees and submodules.- Adapter trust pins are SHA-256 over the canonical TOML of the shared
adapters,varsandproject.name. A legacy 12-hex FNV pin is refused with a message, never upgraded silently. Shared[vars]never override the vars of a user or local adapter; a sharedproject.namemust be a slug;{{repo.remote}}carries no userinfo.kontext trustruns from a terminal only. ctx_threadstakes onlyclaude:,codex:,superset:,lastand paths under known transcript roots, and refuses-over MCP.ctx_read file:refuses.git/,.git-credentialsand.ssh.ctx_prepare_commit dropchecks every id first and refuses a candidate another worktree wrote.
What the agent is told
- A focused brief keeps every governing entry. A reserved Governs <focus> (N) section comes first: one compact line per entry (full id, title, marks, commits since), ordered by path specificity (file, directory, glob,
**), then oldest first. What does not fit is named on one always-printedalso governing:line; below the section's size only ids are printed. Other kinds trim line by line and end with… N more (K govern your focus). The footer counts against the budget. - Paths stay paths. A focus item with
/, a glob character or a known extension is a path even before the file exists. Overlap works in both directions, including leading wildcards and a leading slash.[slug]matches literally first, then as a glob. - Honest currency lines. The brief says
read by <who>,stamped by agent,bulk stamp,check passedorCHECK FAILING; "verified" appears only where the verification holds. A brief line usesrule_textwhen the summary lacks the rule. - The MCP server sees other processes. The index reloads when another process (a CLI capture,
kontext status, a second session) refreshed it; a new schema is built in a temporary directory and renamed. The branch is read per request; a config parse error comes back as a warning. - Visible from the first turn.
ctx_briefcarries_meta["anthropic/alwaysLoad"]; the first 512 characters of the server instructions stand alone and the whole stays under 4 096 characters.
Supersession and parsing
- Supersession follows active successors. An entry named in the
supersedesof an active entry is superseded, andsuperseded_byis filled in. The adr-tools## Statussection is read and written in its own style. References are written as full ids; an ambiguous target is refused.kontext checkreports a one-sided supersede andkontext repair [--dry-run]writes the missing side. - Entries parse the way people and formatters write them: multi-line flow lists, block lists, trailing comments, a BOM. An unparsable entry is a
checkerror.retired,archivedor emoji statuses read asdeprecatedwith a warning; non-Latin titles get a short hash id. - Amendments only add.
drafts.stage amendsaccepts a body only when the old body is its byte prefix and the rest are## Added <YYYY-MM-DD>sections; otherwiseamend_not_additive, pointing to supersede. The title and every field outside the body must stay the same.drafts.extendwithllmno longer folds: it adds the finding as written (as_written: true).extendspasses throughctx_capture, the inbox and promotion. - Challenges stay resolving until the entry's new blob lands in
HEAD. sincecounts by ancestry.sinceand freshness count non-merge commits on governed paths reachable fromHEADand not from the commit of the look, so a branch merged after a confirmation is counted. A failed check is shown but is not a look.- What counts as verified: a read by a person or a passed check. A
checked:date without a ledger line is kindcacheand reportsverified: false;kontext confirm --migrate-legacywrites bulk lines for such entries. The CLI writesreadonly on a terminal (otherwiseagent;--kind readforces it with a warning); MCP never writesread;kontext apirecordsby: application:<name>. - Drift needs a baseline and a look at or after the last governed change in the range; without a baseline it says why, and
--failexits 3.
Redaction and outbox
- Redaction masks what it promises and fails closed: whole PEM blocks, national phone numbers, IPv6 and every match on a line. An invalid
secrets.redactpattern is reported bystatus, and distill, threads and autopilot refuse to send anything to a model. Your ownredactandallowlists are joined with the repository's, not replaced. Adapter errors drop query strings and userinfo. Bash-mode output and compaction summaries of Claude threads are dropped. - The outbox loses nothing silently. An attempt counts only for the adapter that was tried; after repeated failures events move to
outbox.dead.jsonl, whichstatusshows, andkontext outbox retryrequeues them. Events for an adapter skipped bywhenstay queued.
Init
kontext init skip mod:<module>takes effect.dec:clusters whose commits an entry or aDecision:trailer already cites are not planned again;dec:task state is derived from git and from<store>/init-covered.log(committed, union-merged), so a colleague and a fresh clone agree.dec:ids aredec:<module>-<sha7>of the cluster's oldest commit.- Re-rendering a module doc keeps hand-edited
paths,tagsandsummary. Module choice and cluster ids are deterministic. - Bot authors are left out of scoring; Slovak and Czech decision words are bundled,
[init] decision_words = { strong, rationale, contrast }adds stems in your language and[init] bot_authorsnames more bots. Only an explicit--no-hooksrecords a hooks opt-out.init.jobsis honoured.
Search and eval
- Shadow fields. Folded and English-stemmed
title_fandbody_fare searched at a lower boost, sonamietkafindsnámietkaandadapterfinds "Adapters". The index schema version is bumped; the index rebuilds on first use. - Reviewed knowledge first. Local sources are weighed before they are fused (entries 1.0, doc chunks 0.7, commits 0.6; built in,
[search]keys are planned); superseded hits are weighed down and read→ superseded by [id] Title, never hidden; copies are found by a digest of title and text; deduplication never keeps a superseded twin over its active successor; adapter hits sort by mapped score. - Graded eval.
tests/eval/qrels.tsvwith nDCG@5, recall@10 and MRR per slice (identifiers, plurals, Slovak with and without diacritics, paraphrase, focused briefs from 200 to 1 400 tokens). Expectations are written by a different session than the one that implements the change.
API v1 policy
- The compatibility policy is written down. Within version 1, operations, optional inputs, fields, error codes, enum values and capability strings may be added, and clients ignore what they do not know. Narrowing an input is allowed only where the old behaviour contradicted a recorded decision or a security promise, and is announced with a capability string and a migration note. See Compatibility.
api.describereturns the JSON Schema of every operation's input.- One notion of revision: the blob id. A moved revision is
stale_entryeverywhere, with the oldoperation_conflictinerror.aliases;model_unavailablelistsllm_unavailable. The guard takes a blob id, a full commit hash or an older 12-hex revision;HEADor a branch name isinvalid_input. - Verification fields
last_verified,since_verified,failingandamended_sincesit beside the existing ones.entries.changedcarriesstatusand reads each revision's committed config; committed entries carrydate,verify,review_by,supersedes,commitsandauthor. A replay returns the stored receipt even after a later edit;operations.getfinds routed receipts. - New error codes:
untrusted_verify,amend_not_additive;stale_entryeverywhere. drift.ordered:entries.driftcarriesbase_source(explicit,origin-head,origin-main,upstream,default-remote,fallback-none) and, without a base,warning;kontext drift --failandkontext ci --strictexit 3 then.drafts.confirmtakesoperation_id, so a retry does not append a second ledger line;drafts.capturekeepsextends.- New capability strings:
api.describe,drafts.stage.amends.additive,drafts.capture.extends,drafts.confirm.operation_id,drafts.verify.pinned,verification.last_verified,drift.ordered.
MCP, hooks, structured results, skills and plugins
- Dual-era MCP. Capabilities no longer include
logging. The server answers the stateless 2026-07-28 revision (server/discover,_metaon requests withoutinitialize,resultType,ttlMs/cacheScope) and legacyinitialize, which falls back to 2025-11-25. An unknown version is-32022, an unknown tool-32602;resources/listpages with a cursor;tools.listChangedmay be true: it is when adapters expose tools. - Structured results.
ctx_brief,ctx_search,ctx_read,ctx_why,ctx_inboxandctx_driftreturnstructuredContentwith anoutputSchemabeside the text, andresource_linkblocks tokontext://entry/{id}.kontext brief --format jsonreturns the same structure. - Hooks.
kontext hook --host claude|codex|cursorreads the host's hook JSON on stdin and answers in its shape. SessionStart (startup, resume, clear, compact) and SubagentStart get the brief; PreToolUse onEdit|Write|MultiEdit(Codex:apply_patch|Edit|Write; Cursor:postToolUse) gets the governing entries for the edited files, only those not yet told in the session. One budget per session, shared withctx_briefwhen it knows the session (session_id,CLAUDE_SESSION_ID):[hooks] session_budget_tokens(6000),edit_budget_tokens(900). Fail-open; kill switchKONTEXT_HOOKS=offor[hooks] enabled = false. Installed only bykontext connect <host> --hooks; any--writealso installs a shell guard that denies an agent'skontext trust. See Hooks. - Honest approvals. Exposed adapter tools keep their upstream annotations; missing ones default to
readOnlyHint: false,openWorldHint: true.kontext connect codex --writewritesdefault_tools_approval_mode = "prompt"and a[mcp_servers.kontext.tools.<tool>]table per tool:approval_mode = "approve"for the read and inbox tools,"prompt"forctx_verify,ctx_apiandctx_init. - Skills and plugins. Skills go to
.claude/skillsand.agents/skills; akontext-skill-hashmarker keeps team edits, andconnect skills --write --forcereplaces them. A Claude Code plugin (.claude-plugin/plugin.json) and a Codex plugin are built from the same sources asconnect. Parameters gained aliases (id/uri,focus/paths,kind/kinds(also a string),limit/max,budget_tokens,reason/why/because); nothing was renamed.ctx_readpages a long text (part,offset). - A sturdier server. A panic in one request answers
-32603and the server keeps running; the HTTP MCP client re-initialises after a 404; outside a git repository the server says so anddirstill works. - New commands and flags:
kontext repair [--dry-run],kontext trust [--yes]and--verify [<id>|--all],kontext confirm --kind read|agentand--migrate-legacy,kontext distill --force,kontext outbox retry,kontext hook --host,kontext connect <target> [--write] [--hooks] [--force].
Migration.
- Rust 1.90 is the minimum (
rust-versioninCargo.toml). - Legacy FNV adapter pins are refused: run
kontext trustagain in every repository with shared adapters. - Verify commands do not run until pinned:
kontext trust --verify <id>or--all, in a terminal. - Peer:
drift.tsmust mapuntrusted_verifyto "not verified, show the command". - An entry whose only evidence is a
checked:date now reportsverified: false(kindcache);kontext confirm --migrate-legacyrecords bulk lines for them. sincecounts may grow: commits merged after a look are now counted.drafts.extendnever folds a finding into the body: with or withoutllmit is added as written andas_writtenis always true.entries.exportwithout a committed configuration reportsconfig_source.kind: "defaults"(store.ai), notlocal_configuration.- A challenge stays listed as resolving (
resolvingininbox.list) until the entry's new blob lands inHEAD, not whenprepare_commitstages the change. - API fields are additive and the API version stays 1. A client that passed
HEADas a revision getsinvalid_input, a non-additiveamendsbodyamend_not_additive. - The search index rebuilds once (schema version bump).
0.9.0 (2026-10-29)
Additions amend entries in place, new entries link what they build on, and changes between commits are listed.
drafts.extenddrafts an entry with a finding added to its body: same id, file and fields, the old body beside it, nothing written. Withllmthe model folds the finding in; otherwise it is added as written under## Added <date>(as_written: true). Conventions, learnings and incidents only: a decision is refused withdecision_not_amended, since it changes only by supersession. A moved revision isstale_entry. See Adding to an entry.drafts.stagetakesamends: {id, revision}to write that body into the entry's own file, with the front matter kept byte for byte (exclusive withsupersedes), andentry.extends: [ids]to link a new entry to the entries it builds on (unknown_entryfor an id the store lacks). See Amending and linking.entries.changed {base, head}lists the committed entries added, revised, superseded (withsuperseded_by) or deprecated between two commits, without a model. See Changed entries.entries.relatedcandidates carry theirrevision, the value the two operations above take.status.capabilitieslistsdrafts.extend,entries.changed,drafts.stage.amendsanddrafts.stage.extends. API version stays 1.
Known issues (fixed in 0.10.0): a verify: command runs through sh without a trust gate, so do not call ctx_verify, drafts.verify or kontext verify in a repository you do not trust; drafts.extend with llm and amends with an arbitrary body rewrite an entry in place, against the 2026-10-27 decision.
0.8.0 (2026-10-28)
Skills for knowledge maintenance, and flows in the brief.
- Skills.
kontext connect skills --writeinstalls fourSKILL.mdrecipes into.claude/skills/(project scope, to commit):kontext-audit(a budgeted look at the entries most likely stale: confirm, challenge or supersede, never delete),kontext-flows(reorganise the store into flows),kontext-verify(give entries averifycommand) andkontext-merge(find duplicates and conflicts withentries.related, draft one superseding entry per group). They are compiled into the binary; re-running the command after an upgrade brings the files back to the shipped text. See Claude Code. - Flows. An
architectureentry with idflow-<name>(or taggedflow) is a curated trail through the knowledge along one process: a## Trailof[[id]] — sentencesteps. A focusedctx_brieflists the flows whosepathsoverlap the focus, with their step count, under Flows through the focus; an unfocused brief says in one line how many flows exist. See Flows.
0.7.0 (2026-10-27)
A capture names the command that proved it, and a verification says where it landed.
- Capture with its proof.
kontext capture --verify "<command>",verifyinctx_captureand in theentryofdrafts.capturerecord the command that proved a learning or decision; it is validated like the entry field (one line, at most 500 characters) and kept through the inbox and promotion. The capture guidance (the tool description, the server instructions and theAGENTS.mdblock) says so. See Capturing. - A draft takes it later.
kontext inbox verify <id> "<command>"(--clear),ctx_inboxwithaction=verifyand the new operationinbox.verifyset or clear the command of an inbox draft. - Where it landed.
verification.landedis the commit inHEAD's history that first added the entry's newest ledger line, or null while it is only staged or in the working tree; for achecked:date alone, the last commit that changed the entry's file.sinceis unchanged. API version stays 1. See the application API.
0.6.0 (2026-10-27)
A verification is a commit in a ledger, and the brief says what changed since. A checked: date was a stamp anyone could set, often in bulk, and a merge could silently replace it with an older one. Now:
- Ledger.
kontext confirm,ctx_confirmanddrafts.confirmalso append a line to.ai/confirmations.log: the UTC time, the entry, how it was looked at (readfrom the CLI,agentfrom the MCP tool,bulkfor more than five entries in one call), the commitHEADnamed, who, and an optional reason (--because).kontext initand the first write addconfirmations.log merge=unionto.ai/.gitattributes, so branches merge without a conflict.checked:is still written as a cache. See Verifications. - Repair.
kontext checkwarns when an entry'scheckedis behind its ledger;kontext confirm --repair(drafts.confirmwithrepair: true) rewrites it from the ledger. - Executable checks. An entry may carry
verify:, one shell command.kontext verify <id>,ctx_verifyand the newdrafts.verifyrun it from the repository root with a timeout (KONTEXT_VERIFY_TIMEOUT_SECS, default 120) and record pass or fail in the ledger. - What changed since. For each entry governing the focus paths,
ctx_briefsays how it was last verified (kind, short commit, day) and how many commits touched its paths since, with their first subjects; once per brief it asks to read those before changing their paths. - API. Entries from
entries.list,entries.get,entries.search,entries.governingandentries.driftcarryverification,since,verifyandpremises;checkedis the newer of the file and the ledger.drafts.confirmtakesbecause,kind,idsandrepair. API version stays 1. See the application API. - Changed premises. An active entry that links to a superseded, retired or deprecated one (
[[id]],supersedes,extends) is flagged in the brief, the API and as an info line ofkontext check; nothing is rewritten. - Gate.
kontext hooks statusand the docs point teams tokontext drift --failin their check script or CI, which also covers jj commits; no hook blocks a commit for drift.
Migration. None needed. The first confirmation creates .ai/confirmations.log and adds a line to .ai/.gitattributes; commit both. kontext check counts info lines as neither errors nor warnings.
0.5.0 (2026-10-26)
Decisions can say what was rejected. A decision entry may carry an optional ## Alternatives section between ## Decision and ## Consequences: the options considered and why each was rejected, so a later challenge or drift does not reopen one that already failed. It is free Markdown, not front matter, and nothing requires it. See the entry format.
ctx_init_submittakes an optionalalternativesstring fordec:tasks and writes the section; an empty value writes nothing.- The
ctx_capturebody hint and the distill prompt mention the section, so agents fill it when there were real alternatives. - The one-line summary and the action line still come from
## Decision, so the brief and search read entries as before.
Migration. None: entries without the section stay valid, and older kontext versions read the section as ordinary body text.
0.4.1 (2026-10-20)
Fix: confirming an entry again the same day cleared nothing. kontext confirm wrote only a date, so a second confirmation on the same day left the file byte-identical, and drift, which counts an entry as looked at only when its file changes in the range, kept listing it after later commits. Confirm (kontext confirm, ctx_confirm, drafts.confirm) now writes the UTC time to the second, checked: 2026-10-20T14:05:09Z, and returns the same string. checked accepts that form or a bare YYYY-MM-DD (both validated, neither in the future); freshness counts after a time's second and from the next UTC day after a date. Nothing needs to change: dates already written stay valid. See Confirmations.
0.4.0 (2026-10-20)
Knowledge that follows the code it governs. A review of one repository found about ten entries that no longer matched the code. kontext already listed the entries covering a staged change, but only from git hooks, which a team committing with jj never runs; freshness never reset once someone checked an entry, and watched decisions only; and nothing answered which entries a range of commits left behind. Now, without a model and the same under git and jj:
- Confirmations. An entry can carry
checked: YYYY-MM-DD, the last day someone confirmed it still holds.kontext confirm <id>/ctx_confirm/drafts.confirmset it to today in the entry's own file (a one-line diff) and stage it, so the confirmation is reviewed with the change. See Confirmations. - Drift.
kontext drift/ctx_drift/entries.driftlist the active entries whosepathscover files changed inbase..headwhile their own file was not edited, retired or confirmed in the range. The base defaults to where the branch left the remote's default branch; without a head the working tree counts too, which is what a jj working copy is. See Drift. - CI.
kontext cichecks every entry and lists the drift of the pull request's commits, as text or as Markdown for a job summary; drift is a warning unless--strict. A ready-to-copy GitHub Actions workflow is in Validate knowledge in CI. - Freshness watches conventions and learnings as well as decisions, and counts commits since the latest of the entry's date, its confirmation and the last commit that changed its file. See Freshness.
- prepare-commit without a staged change says that it read the working tree's changes against
HEAD, and tells how to confirm an entry that still holds. With jj, run it (orkontext drift) beforejj commit/jj git push: see jj. - Application API. New operations
entries.driftanddrafts.confirm(listed instatus.capabilities); read entries and the embedding facade'sCommittedEntrycarrychecked.
Migration. checked is a new optional field; nothing in .ai/ needs to change. Things you may notice:
kontext statusand the brief may flag conventions and learnings now, and say "N entr(y|ies) may need a refresh … since they were made, edited or confirmed" instead of "N decision(s) …". Counts are often lower: the commit that last changed an entry's own file (usually the one that added it) and the commits before it no longer count.checkedis an entry field: an existingchecked:key moves fromextrato its own field in entry JSON and inCommittedEntry,kontext checkrejects acheckedthat is not a date or lies in the future, anddrafts.*refuse it as anextrakey.- The
prepare-commitreport's working-tree line reads "Nothing staged yet — read the working tree's changes against HEAD (untracked files included): …".
0.3.0 (2026-10-19)
Knowledge that stays correct after it is written. The brief and search no longer let a proposal pass for an accepted rule, merging sources no longer drops a different claim that happens to start the same way, and recorded knowledge can now carry a review date and its sources, be challenged and be retired, always through review. Measured on a new evaluation set of 33 scenarios: 8 passed on 0.2.1 (23 of 64 expectations found, 2 hits wrongly suppressed, 1 noisy); all 33 pass now (69 of 69, none suppressed, no noise).
- Authority marks. A line in the brief and a search hit say when an entry is not accepted (
(proposed),(deprecated)), when its file is new, edited or staged and nobody approved it (local, unapproved), when its review date passed (review due), when it is challenged locally, and how many sources it has. Accepted, committed entries carry no mark. See Marks. - Safe deduplication. Search merged hits whose first 90 normalized characters matched, so one of two different claims vanished. Now only proven copies are dropped (the same URI, an adapter's copy of a local entry, a full-text match); a look-alike is shown under the first one with what differs.
- Changed since the last brief. The brief lists, in at most five lines, the knowledge added, changed or removed since this worktree's last brief (the last 14 days without one), and says which entry a new one supersedes. A brief without changes adds nothing. See Changed since the last brief.
- Review dates.
review_by: YYYY-MM-DDon any entry; past it the entry is marked in the brief, search andkontext status, never hidden. Optional per-kind default[store.kinds.<kind>] review_after = "90d", off by default. See Review dates. - Evidence. Captures take
evidence: [{ref, quote?}]with referencespr:,issue:,task:,code:<repo>@<rev>:<path>#L<a>-<b>andurl:, kept inextra.external_refs. A quote of a code reference into this repository is checked against that revision; anything else is marked unverifiable, never refused. See Evidence. - Challenges and retirement.
ctx_challenge/kontext challengerecord that an entry no longer holds;ctx_prepare_commit retire=[id]retires it (statusdeprecatedand a## Retirednote, staged) or a replacement supersedes it. Retire and supersede work for every kind. See Challenges. - Related knowledge.
ctx_capturenames the entries a new one may duplicate, extend or contradict, with the reason (similar wording, the same paths); the old note that said "update it instead" is gone. A model is asked only on request, throughentries.related, and its answer is cached. - Search. A whole-query phrase bonus ranks an exact wording first (on the evaluation set the exact-phrase query moved from rank 2 to 1; queries in one's own words kept their rank).
[search] adapters = "fallback"asks the search adapters only when local hits are fewer thanmin_local_hits, or when asked (adapters: true,--adapters); the default staysalways. - Application API. New operations
entries.related,drafts.retireanddrafts.revise(listed instatus.capabilities);drafts.capture,drafts.stageanddrafts.formalizealso returnevidenceandrelated_entries, anddrafts.stageresolved_challenges; entries carryreview_by, and working readspublication.blob_hash, a per-entry content revision. See Knowledge maintenance.
Applications can use a shared knowledge engine through the application API: versioned JSON CLI and structured MCP, configured-store queries, path applicability, read-only extraction, idempotent draft staging and committed exports pinned to an explicit review ref. Existing human CLI commands and agent tools remain compatible.
Migration. Nothing in .ai/ needs to change. Things a script or client may notice:
kontext search(text) no longer printsacceptedamong a hit's metadata, and prints a look-alike hit as an unnumbered↳ similar, differs: …line;--jsonhits may carrysimilar_to.- The brief's decision lines may carry marks after the title, a new Changed since … section may appear, and the brief writes a small cache (
brief-head) into the worktree's local state under.git/kontext/. ctx_captureandkontext capturenotes sayrelated, check: … <kx:id> — <reason>instead ofsimilar existing entry: … — update it instead.review_by(andreview-by) are entry fields now: as anextrakey indrafts.*they are refused as reserved; passentry.review_byinstead.inbox.listcan return candidates of kindchallenge; they cannot be staged as entries (invalid_input).
0.2.1 (2026-10-03)
Agents act on the decisions that govern a change. In a test thread, an agent was given the brief injected at session start, which lists only the newest decisions, and made a change that contradicted an older one. It learned of the conflict only at commit time, from a one-line summary that left the rule out, and recorded nothing. Now:
- an unfocused brief says that
ctx_briefwithfocuslists the decisions that govern the paths being changed, ctx_prepare_commitquotes each covering decision's rule (the## Decisionparagraph) instead of its summary, and says how to record a superseding decision and promote it into the same commit.
The same task then ended with the superseding decision in the commit and a Decision: trailer.
0.2.0 (2026-10-03)
Migration: kontext hooks install --dir <dir> is now --hooks-dir <dir> (likewise uninstall). --dir names the repository, like -C.
Knowledge in submodules and other worktrees. A session that started in the app repository but worked in a submodule, another worktree or a sibling project got "not set up" from kontext, and its captures landed in an inbox they could not be promoted from. Now the paths decide which repository answers, and every tool takes dir. See Several repositories.
Private notes are found again. A private capture in a repository without a store was written once and never read, because search did not cover the inbox. ctx_search now finds inbox notes, and the brief lists the ones that match its focus.
Stale decisions are flagged. A decision is written once while its code keeps moving. The brief's State and kontext status list decisions whose paths have seen [freshness] threshold_commits (default 20) commits since they were made. See Freshness.
Shorter answers. A decision line no longer repeats its title as an id: references are the shortest unique prefix ([2026-09-28-adapters]), which makes the line about 20% shorter. ctx_threads turns each Claude Code background-task notification into one line. A thread that fanned out work went from 81,000 to 30,000 characters, and a part (20,000 characters by default) now fits one tool result.
Fresh clones. A clone made by an orchestrator or by CI has no git hooks. The brief says so, and ctx_prepare_commit no longer promises trailers that no hook will add.
Codex follows AGENTS.md, not the MCP server's instructions. kontext connect agents-md --write belongs to its setup.
0.1.5 (2026-09-29)
Autopilot
llm-clauderuns on the subscription of the logged-in account (ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKENare dropped for its calls), with no tools, no MCP servers and a short system prompt (about a tenth of the tokens per task), and without saving the calls as Claude Code sessions. Neweffortvariable (defaulthigh); timeout 10 minutes. Opus:kontext adapters add llm-claude --force --var model=claude-opus-5-5.
Init
kontext init --no-hooksis remembered for the clone: a laterinitorinit --deepen, from any worktree, no longer installs hooks where they were declined;kontext hooks installadds them.
0.1.4 (2026-09-29)
Sensitive threads
- Thread transcripts (
kontext distill,ctx_threads) and what is distilled from them mask email addresses, phone numbers, IBANs, card numbers and IP addresses, besides secrets;secrets.redactadds your own patterns (a client's name, an integration id). - The model is asked for roles instead of people's names and to leave out contact data, records, credentials and hosts; its entries are masked again.
- Measured on a client thread: 52 email addresses, 2 phone numbers and 13 IP addresses no longer reach the model, and the distilled entries named no one.
0.1.3 (2026-09-29)
Knowledge from agent threads
kontext distillreads Claude Code and Codex threads (every Claude account,$CODEX_HOME), Superset workspaces (by id, worktree name, path or branch;--supersetalone means the current one) or any text, and captures the durable decisions, conventions, pitfalls and incidents anllmadapter finds in them into the inbox, with paths, commits,origin: threadand the thread as source. Transcripts are compacted and redacted, split into parts for long threads, and checked against what is recorded already. See Knowledge from agent threads.ctx_threads(read-only) gives connected agents the same transcripts, in parts; thekontext-distillprompt walks an agent through distilling one withctx_capture, which now takessourceandcommits.- A Superset workspace's threads that ran in another repository are skipped, and a workspace of another repository is refused.
0.1.2 (2026-09-29)
From deploying kontext into that monorepo with Claude Code and Codex connected.
Bootstrap
- The autopilot's LLM calls no longer reach kontext's own MCP server, and the prompt asks for the JSON answer only: with kontext connected to Codex, a model recorded each task itself through
ctx_init_submitand again through its answer, so learnings and decisions appeared twice (…-2). Thellm-codexpreset passes-c mcp_servers.kontext.enabled=false,llm-claudepasses--strict-mcp-config. Presets live in your config: refresh them withkontext adapters add llm-codex --force(andllm-claude). - While
kontext init --deepenruns,ctx_init_submitfrom another process refuses the run's tasks. - A resubmitted task replaces its own earlier learnings and decisions instead of adding copies, and leaves entries people wrote alone.
- A branch without team knowledge is told when another branch has it (a bootstrap waiting for review): the brief says to merge it, and
ctx_initrefuses to bootstrap a second, conflicting.ai/. - Entries mined by init get no commit trailers: they come from the older commits listed in their
commits, and a bootstrap commit no longer carries dozens ofDecision:/Learning:lines.
Agents
- Registered for all repositories (user scope), kontext only reads where nobody set it up: in a repository without a knowledge store the MCP instructions say so,
ctx_capturerefuses team entries (private notes still work), promotions are refused, andctx_initbootstraps only withbootstrap=true(thekontext-initprompt passes it). - A decision or learning captured without
pathsand promoted with a change governs that change's files (conventions stay repository-wide), soctx_whyfinds it on the code it explains. kontext connect codexwrites to$CODEX_HOME/config.tomlwhenCODEX_HOMEis set (as account-switching wrappers do), creates the directory if needed and mentions a backup only when it made one.
0.1.1 (2026-09-28)
Fixes from a field test on a 74-module moon/Cargo monorepo worked by parallel Claude Code and Codex agents.
Agents
- Codex no longer refuses kontext's tools under
approval_policy = "never": every tool carries MCP annotations (readOnlyHint,destructiveHint,title), andkontext connect codex --writeaddsdefault_tools_approval_mode = "approve"(also to an existing entry). - Parallel worktrees:
ctx_prepare_commit, the pre-commit reminder and the brief offer only the inbox candidates captured in the current worktree; candidates of another live worktree are listed apart ("not for this commit"), those of a removed worktree may be adopted. - The brief lists every
AGENTS.md/CLAUDE.mdbetween the root and a focused path, and gives a focused module without a module doc its scan facts. - Empty values in list arguments (
--paths a,, an agent's[""]) are dropped instead of becoming entry paths, tags or supersessions.
Git
git commit --amend -m …keeps theDecision:/Convention:… trailers (an amend is measured from the parent ofHEAD);git merge --squashcommits get them too.- Hooks read staged knowledge in one
git cat-file --batchand match entry paths without recompiling globs: a commit of 44 knowledge files went from 4.2 s to 0.4 s. - The search index forgets commits that left the history (amended, rebased).
Bootstrap
- Decision mining recognizes choices phrased as rules ("X, not Y", "never", "no longer", "is gone"), more rationale words and long explanatory bodies, and the founding commit; when few commits pass, the next best fill up to a quarter of the history. Small clusters join their enclosing module, large ones are split into chronological parts of up to 8 commits;
init.max_decision_tasksdefaults to 20. Attribution trailers are dropped from mined messages. - Module descriptions fall back to the package's own doc comment (
__init__.pydocstring,//!crate docs,doc.go); README introductions that end in a lead-in (…:) keep their first sentences. - The overview names the modules without a module doc and counts the agent rule files it does not list.
Retrieval
- Federated search fuses sources by weighted reciprocal rank, so an adapter's compressed similarity scores no longer push local knowledge out; adapter copies of local entries (a
synced…/<id>.md) collapse into the local hit.
Security
- Secrets written into sentences ("the secret is …", "rotate the token …") are detected when the value looks random; paths and placeholders are left alone.
0.1.0 (2026-09-28)
First public release.
Knowledge store
- Markdown entries (decision, convention, learning, incident, architecture) with flat front matter, or classic ADRs with
**Status:**fields; date, sequential or no numbering; supersession; validation; generated, union-merged.ai/README.md.
Agents
- MCP server over stdio:
ctx_brief,ctx_search,ctx_read,ctx_why,ctx_log,ctx_capture,ctx_inbox,ctx_prepare_commit,ctx_init,ctx_init_submit; promptskontext-init,kontext-commit,kontext-reflect; resourceskontext://briefandkontext://entry/{id}. kontext connectfor Claude Code (project.mcp.json, SessionStart hook), Codex, Cursor, OpenCode andAGENTS.md.
Bootstrap
kontext init: scan (languages, manifests incl. Nx and moon, stack, modules and areas, dependency edges, ADRs, agent rules), history (decision signals, dependency swaps, churn, conventions), render, wire, and a resumable deepen protocol for agents or an LLM adapter.
Retrieval
- Tantivy BM25 over entries, section-chunked docs and commit history with identifier expansion; federated search across adapters;
ctx_whyfor paths, line ranges, commits and symbols; decision timeline.
Adapters
- Generic
mcp(stdio and streamable HTTP),httpandcommanddrivers; ops, events (capture,promote,sync), schema-based MCP argument binding, result mapping (items,split,where,mapwith paths,re:,tpl:, literals), federated and declared tools,whenconditions, trust for repository-declared adapters. - Presets: OpenViking, CodeGraph, Serena, Agent LCM, sessions, Claude/Codex/Ollama LLMs, Slack webhook.
Git
- Hooks (pre-commit validation and secret scanning, prepare-commit-msg trailers, post-commit/merge/rewrite sync) installed alongside existing hooks,
core.hooksPathand husky; an outbox with retries; worktree-aware local state.