Repository navigation
Releases: rsdoiel/knowledge
Release list
v0.0.24
Foul Papers can build on kb: story front matter and Fountain scenes become story events, concepts have a kind, and kb story timeline and kb story check list and check them. The decisions are DR-0075, DR-0078 and DR-0079 (all accepted).
Story events. A scene file with a narrative key in its front matter (event, story_time, pov, characters, foreshadows, pays_off, precedes; status and place ride along), or a Fountain scene with a scene number (INT. KITCHEN - DAY #12A#) whose metadata is a one-line boneyard after the heading (/* story: story_time=1969-10-29; pov=Anna */), is a story event. story_time is a date, a month, a year, circa 1890, ordinal: 12, or after:/before: another event's label with an optional offset (after: the-fire +3d). Events are derived from the files by every kb document ingest, an unchanged file included, and do not travel through export, import, merge or check-db: after an import, run kb document ingest on the same paths.
Timeline and check. kb story timeline --project P lists the events in story order, or --narrative in reading order; where the order after the row above is not established it says so (~) and never guesses. kb story check --project P reports unnumbered scenes, duplicate and dangling labels, times it could not read or resolve, orders the dates contradict, cycles, a character in two places on one day, and foreshadowing out of order. It changes nothing and exits 0 unless --strict.
Concepts have a kind. character, place, theme or other (the default): kb concept add --kind, kb concept set-kind, kb concept list --kind. The kind travels through export, import, merge and check-db.
Wikilinks accept a display alias. [[the-long-fire/Anna|Anna]] links the concept before the bar and shows the text after it.
Requires fountain 1.0.3, which parses boneyards and scene numbers. For packagers and Foul Papers: the library exports StoryEvents, StoryTimeline, StoryCheck, ParseStoryTime, ResolveStoryTime, SetConceptKind, ConceptsOfKind, ConceptKinds, WikilinkTarget and the story fields of ParsedDocument.
Full Changelog: v0.0.23...v0.0.24
v0.0.23
Notes get frontmatter at ingest, search hits say where they are, kb stats shows a database's shape, and the knowledge skills and an agent document now ship in this repository. The decisions are DR-0076 and DR-0077 (both proposed).
Notes. kb document ingest PATH --project P, on a terminal, offers frontmatter for a file that has none: title, author, dateCreated and the known concepts the text mentions as keywords, one at a time (Enter accepts, text replaces, - skips, q stops), written only after you confirm. --no-prompt, --dry-run, --json and a missing terminal never prompt. A date at the start of a file name, 2026-09-29-worklog.md, is now the first dateCreated signal, here and in kb document frontmatter.
Searching. A hit now carries a record's qualified reference and status (harvey/DR-0004 (accepted)) and the passage that matched, the matched words between « and », with the section it is in for a record (Decision:, or title:). This is in kb search TERM as well as the scoped form, and in --json.
Counting. kb stats reports rows per table, links per join table, five checks (observations_without_project, concepts_without_links and others) and a line per project, with no SQL; --json is one object. kb concept show says which projects a concept spans, tagged directly or through observations, records and document sections.
Completion. kb completion bash -install now also adds a line to the bash startup file (~/.bashrc, or on macOS the first of ~/.bash_profile, ~/.bash_login and ~/.profile that exists), because macOS's bash 3.2 never reads the bash-completion directory, so completion did nothing in a new Terminal window. -uninstall removes what -install wrote, and -check says what is missing. Use eval "$(kb completion bash)" to try it in a session: source <(...) silently does nothing in bash 3.2.
Fixed. kb ingest on a project directory failed on dated notes (notes/2026-09-29-....md, "no frontmatter"): the year read as a record id. A record is NNNN-slug.md and not YYYY-MM-DD..., and the walk skips design, plans, feature_requests, notes and hand-off below the directory you give it. The closing kb: ingest: N error(s) line no longer repeats the first error.
Shipping. agents/skills/ holds setup-knowledge-base, update-knowledge-base and review-knowledge-base, and AGENTS.md (with a CLAUDE.md that points at it) tells a harness what kb is, the rules for using it, the verbs and the exit codes. The release zips include them. make install-skills copies the skills to ~/.claude/skills (SKILLS_DIR changes it) and make check-skills compares; make install does not install them. A test fails if a skill's kb_version is not the release's.
For packagers and harvey: the library gains Stats, StatCount, ProjectStats, ConceptSpan and ConceptDetailResult.Spans, and KBSearchResult carries Ref, Status, Passage and Section; Search and SearchScoped take what they took.
Checked in this release: the race detector passed on darwin/arm64 (macOS), and the test suite passes on Linux (Raspberry Pi OS, arm64). The built binary was driven on a pseudo-terminal on Linux for the frontmatter prompts, and on macOS for completion -install, -check and -uninstall under /bin/bash 3.2 and for the review skill. Not checked: the frontmatter prompts by hand on macOS or Windows, and completion on Windows.
Full Changelog: v0.0.22...v0.0.23
v0.0.22
Search is scoped by a path, in the command and in the interface, / now filters every list, and every row of the interface's menus is built. The decisions are DR-0072 to DR-0074.
Searching. kb search harvey/ "exit codes" searches one project, harvey/records one kind in it, workspace/ the workspace tier only and /records one kind everywhere; kb search TERM is unchanged, and a first word with no slash is still part of the term. Results are grouped by kind with counts, name a record by its qualified reference, show the projects a concept is in, and say showing 50 of N when they were cut. An unknown scope or kind is exit 2; workspace/observations and harvey/projects are exit 1 with the reason. In the interface, Search is a menu of scopes and a prompt that takes the same line, S opens it from any screen with the scope of where you are, and kb search on a terminal opens it.
Filtering. / narrows the list in front of you as you type, on every list; Enter keeps the filter and Esc clears it. / no longer starts the search, S does.
The interface. Check, the Browse lists, Recall, Suggest, Check retractions, Frontmatter (a checklist, written only on y), Enter on a search result, d to delete a concept, source or document, and u to unlink a concept from a project or cut one link of an observation are all on screens now, each with the typed or keyed confirmation its class needs and the command that does the same. kb --json verbs carries the menu fields.
Changed. source check-retractions is classed as a changing write, so : asks first; on the command line nothing changes.
For packagers and harvey: the library gains SearchScoped, SearchKinds, ErrNoMembers and ObservationConcepts, and KBSearchResult carries SourceID and ProjectID; Search is unchanged.
Not checked in this release: the race detector was not run (the machine it runs on was not available), and the new screens were not tried by hand on macOS or Windows. The test suite passes on Linux (Raspberry Pi OS, arm64), and the built binary was driven on a pseudo-terminal there for the filter and the search prompt.
Full Changelog: v0.0.21...v0.0.22
v0.0.21
Records are now read in kb's own viewer, with Markdown highlighting, and the pager no longer depends on which programs happen to be installed. The decision is DR-0071 (a partial supersede of DR-0066 point 5).
Reading. Enter on a record in the terminal interface used to return straight to the list when bat was installed: bat quits at once when the text fits one screen and the interface repainted over it. kb now shows a record itself. YAML frontmatter, headings, fenced code, list markers, quotes, inline code, bold and links are coloured with the terminal's own 16 colours; NO_COLOR or TERM=dumb turns it off. In the viewer / finds text (case-insensitive), n and N move between matches, g and G jump to the ends. kb record set-status REF with no status prints the same highlighted record on a terminal. bat, batcat and less are no longer looked for; $KB_PAGER is the override and is run exactly as written (give bat --paging=always).
Fixed. kb help ingest showed kb ingest clasm/decisions, which exits 66 from the workspace root: PATH is a directory relative to the current directory, one only, walked recursively, and the project and tier come from each record's project: frontmatter. The text now says so and the examples work; the kb index and kb record fmt examples are corrected too. kb ingest's "missing" line said kb had no verb to remove a row; it now names kb record delete REF. The kb-index(1) page no longer points at the developers' TODO.md.
For packagers: github.com/muesli/termenv is now a direct dependency (it was already built in). The race detector passed on darwin/arm64 at the last code commit. The viewer was driven on a pseudo-terminal against the built binary on Linux (Raspberry Pi OS), and tried by hand on macOS and Windows, where it worked.
Not in the interface yet: Documents Browse and Frontmatter (frontmatter is reachable through :), Concepts Recall and Suggest, Check, and the removing writes source remove, unlink and document delete; kb verbs --json does not yet carry the menu fields.
Full Changelog: v0.0.20...v0.0.21
v0.0.20
The terminal interface can now do everything the command line does to what you are looking at, behind the same gates. The decisions are DR-0066 to DR-0070 (the menu tree and :, the shared chooser, the write classes and the removing gate, plan then apply for ingest, the document summary workflow, and the terminal rule for promote), from the design brief tui-keys-and-write-flows-design.md and its plan. Everything was written and tested red first, including the built binary on a pseudo-terminal with real bytes. The race detector passed on darwin/arm64 at the last code commit, and the interface was tried by hand on Linux (Raspberry Pi OS) and macOS. It has not been run on Windows.
Writes. n on the project list, an observation or concept tab and the Records screens, and the New rows of the menus, open a form that asks the fields one at a time and ends with the command that does the same and y. s, e and r on the project list change a project's status, description and name; e on an observation writes a correction (a new observation that supersedes it, as kb observation update does) and on a concept renames it; u on a record makes it supersede another. d deletes a project, observation, concept or record behind a gate that shows what points at it and asks for its name to be typed. Each write is the command's own function, so its rules and refusals are the same, and the screen ends by showing the command that does the same.
Plans and the command line. Ingest, Records, Fuzzy-tag and Documents (Ingest a document, Tag, Fuzzy-tag) show the command's own --dry-run output first and apply on y; Index and Format files run at once. : opens a command line on the menus and browsing screens: any verb, run by the command line's own code, with the gate its write class calls for (reads and direct verbs run, additive and changing writes ask y, a delete meets the typed-name gate, plan verbs show their dry run, merge, import, init, export and completion are refused).
Documents. Documents, Review queue lists the sections waiting for a person; Enter writes the summary in $VISUAL or $EDITOR (the interface is suspended) or in a built-in text area, then shows it above its source, and y saves it as written by a person and promotes it. A section that already has a draft starts at that review, so a model's draft is read beside its source, and promoted as it is it keeps its author.
kb ingest now says which concepts it created, or with --dry-run would create, so a typo in a [[wikilink]] no longer adds a concept silently (concepts_created in -json; (*KnowledgeBase).HasConcept in the library).
Building: cmt is no longer part of make. make generate regenerates version.go, about.md, CITATION.cff and the installers from codemeta.json, and make release runs it, so the version and release hash change only when asked for.
Not in the interface yet: Documents Browse, Documents Frontmatter (document frontmatter is reachable through :), Concepts Recall and Suggest, Check, and the removing writes source remove, unlink and document delete; kb verbs --json does not yet carry the menu fields.
Full Changelog: v0.0.19...v0.0.20
v0.0.19
The terminal interface can now change something, and kb describes its own command language in one table. The decisions are DR-0059 (one verb table, in part), DR-0064 to DR-0067 (keys, a shared chooser, the menu tree, and which writes get which gate), DR-0068 (ingest) and DR-0069 and DR-0070 (documents and promotion), from the design brief tui-keys-and-write-flows-design.md. Everything was written and tested red first, including the built binary on a pseudo-terminal with real bytes. The race detector passed on darwin/arm64 at the last code commit, and the interface was tried by hand in a real terminal on Linux.
Bare kb, on a terminal, opens a menu with one row per verb group (Projects, Records, Observations, Concepts, Sources, Documents, Search, Ingest, Index, Check), under a header naming the workspace, its database and what it holds. A group opens its own menu; rows that are not built yet are dimmed with the release that brings them, and choosing one shows the command-line equivalent. A project's observations, concepts and records are tabs with counts (o, c, r). Records Browse and Pending list records in the scope kb record list would use, one line each with its qualified reference, and a widens the scope. On a record, Enter reads it and s sets its status: the record file is shown in your pager ($KB_PAGER, else bat, else less -R) with the interface suspended, or in a built-in viewer when there is none, then each status is one key, y confirms, and Esc or q backs out at either step with nothing written. The write is the same function kb record set-status uses, and the screen shows the equivalent command.
The keys follow clasm's. q goes back one screen and quits only at the top menu, Esc cancels something in progress and never closes a screen, Ctrl-C quits from anywhere, and a legend line on every screen lists the keys that apply. While you type in the search prompt every key is text, so a term that starts with q works. A complete command line always runs and prints, on a terminal or not; only an incomplete one opens the interface, and only on a terminal (bare kb, a bare group such as kb record, kb record show or kb project show with no argument). The new global option -i opens the interface at a command: kb -i record pending, kb -i record show REF, kb -i search TERM.
kb verbs (and kb -json verbs) prints the verb table: every verb, subverb and flag, with what it does to the database. kb record set-status REF with no status is now a review that takes single keys, with no Enter, and Enter on the confirmation does nothing. kb document review promote needs a person at a terminal, as accepted does: a model can draft a summary but cannot make it trusted. kb ingest reports a status that arrives through a file, such as clasm/DR-0012 proposed -> accepted (edited in file) or a record first ingested already accepted; it is a report, not a block.
Upgrading: the interface's keys changed (q goes back instead of quitting, Esc no longer leaves a screen), and a script that promoted summaries without a person at the keyboard must hand that step over. Bare kb with no terminal is now a usage error (exit 2) and no longer tries to start a terminal program, and opening the interface no longer creates a database where there is no workspace. lipgloss is a direct dependency; it was already built into kb through bubbles. Skills that tell a model to run set-status ... accepted or document review promote need kb >= 0.0.19.
Full Changelog: v0.0.18...v0.0.19
v0.0.18
Accepting a record is now the author's act, and the tool enforces it. The decisions are DR-0060 (set-status reviews the record, then asks), DR-0061 (accepting needs a terminal) and DR-0063 (cancelled covers explored work), all from the review-then-decide design. Everything was written and tested red first, including the built binary on a pseudo-terminal and with redirected streams.
kb record set-status follows a table of allowed moves. A record that is proposed may become accepted, rejected, cancelled or superseded; accepted may become cancelled or superseded; rejected and cancelled may go back to proposed; superseded is final, and needs superseded_by already set (use kb record supersede). A move outside the table, or setting the status a record already has, exits 1 and names the moves it may make; nothing is written. A record whose status is outside the vocabulary can only become proposed. cancelled now means pursued or explored and then abandoned, and need not have been accepted; rejected means considered and not pursued.
kb record set-status REF accepted exits 2 unless standard input and standard output are both a terminal, with a message that a person must accept it. No flag or environment variable turns that off, and every other move works without a terminal, so a script can propose, reject, cancel and supersede but not accept. The test asks the terminal driver, so < /dev/null does not count. It guards the accidental path, not a determined one: a process can allocate a pseudo-terminal, and a record file can be edited by hand.
kb record set-status REF with no status is a review for a person at a terminal. It shows the record through $KB_PAGER (else bat -l markdown, else less -R, else prints it), prompts with the current status and the moves allowed (harvey/DR-0004 is proposed -> [a]ccepted [r]ejected [c]ancelled [q]uit), and asks [y/N] before it writes. q, an empty or negative answer, or end of input leaves the record unchanged and exits 1. KB_PAGER is new. The library exports AllowedTransitions and CanTransition, so harvey and the TUI read the same table.
Upgrading: a script that ran set-status ... accepted must hand that step to the author, and one that relied on arbitrary moves (for example accepted to rejected; use cancelled) now gets exit 1. Skills that tell a model to promote a record need updating; the ones in the Laboratory do not any longer. github.com/charmbracelet/x/term and golang.org/x/sys are direct requirements, both already built into kb through bubbletea. The generated kb-*.1.md pages are now checked against their help text, so an edit made only to a page fails the tests.
Full Changelog: v0.0.17...v0.0.18
v0.0.17
Records are named by scope, and the workspace is found from anywhere inside it. The decisions are DR-0057 (qualified record references) and DR-0058 (scope). It was written and tested red first, the race detector passed on darwin/arm64, and the new commands were checked read-only against two real workspaces, one with 277 records in 23 projects where DR-0001 appears ten times.
A record is SCOPE/DR-NNNN, where SCOPE is a project name or workspace (the workspace directory's own name is accepted for it). kb record list prints that reference first on every line, --json gains ref, and show, set-status, supersede, delete, new and fuzzy-tag confirm with it, so "DR-0047 needs accepting" says which project. A bare id still works where only one record has it, and otherwise lists the qualified forms. A change (set-status, supersede, delete) will not act on a bare id with no scope.
kb record list harvey clasm workspace takes scopes as arguments. With none it uses the project the working directory belongs to, then KB_PROJECT, then the whole workspace; --all widens it; record new does the same. kb record pending lists the proposed records in scope. --project and --workspace still work on those verbs and say on standard error that they are deprecated. A project can no longer be named workspace.
kb walks up from the current directory to the nearest agents/knowledge.db or agents/knowledge.jsonl, so it works from any subdirectory; a fresh clone with only the JSONL file is told to kb import -in agents/knowledge.jsonl. KB_DB, KB_PROJECT, KB_CEILING_DIRECTORIES and KB_QUIET are read; a note on standard error says when the workspace is not the current directory. The library exports FindWorkspace, Ref, ParseRef, ResolveRef and ProjectForDir, for harvey.
Upgrading: a script that reads record list by column breaks; use --json. Skills that quote the old forms need kb >= 0.0.17. A scratch directory inside a real workspace now reaches it unless KB_CEILING_DIRECTORIES names the scratch directory.
Full Changelog: v0.0.16...v0.0.17
v0.0.16
One new verb, kb completion, so that tab completion works in bash and PowerShell. The decision is DR-0056. It was written and tested red first, and checked by sourcing the script in real bash and PowerShell against the real workspace.
kb completion bash and kb completion powershell write a completion script to standard output (pwsh is accepted for powershell). It completes the verbs, the subverbs of project, observation, concept, source, link, record and document (and document review), each verb's flags once a dash is typed, help topics after help, paths after -db, -in, -out, -a, -b, -jsonl, -root and -dir, and project names after --project and after project show, concepts, set-status, set-description, rename and delete. Project names come from kb project list in the current directory and honour a -db typed earlier on the line.
kb completion SHELL -install installs it instead. With bash the script goes to $XDG_DATA_HOME/bash-completion/completions/kb, or the same path under ~/.local/share, and a file that kb did not write is never overwritten (exit 73). With PowerShell it writes kb-completion.ps1 beside the profile and adds one line that dot-sources it, once. Windows PowerShell 5.1 is not covered.
The verb list is read from the verbs kb registers, so a new verb is completed without anyone naming it. The subverbs and flags are tables, and the tests fail when a table disagrees with the code, so a new flag or subverb must be added to them. The verb opens no database and refuses -db. A bad or missing shell name, a surplus argument and an unknown flag exit 2.
Upgrading: nothing that worked changes. kb completion did not exist before, so a script that called it got exit 2 (unknown verb).
Full Changelog: v0.0.15...v0.0.16
v0.0.15
Three new ways to see what the knowledge base holds, and one to check that it agrees with its JSONL dump. The decisions are DR-0051 to DR-0055. Everything was written and tested red first. The new verbs were checked by running the v0.0.14 build beside the new one, on a copy of the real workspace, over 415 commands in plain and --json mode: the only changed exit codes were the two new verbs' own, and nothing exited 70. That comparison was made before the two fixes described last, which change behaviour on purpose.
kb concept show NAME prints one concept's description and identifier, what links to it (projects, observations, records, document sections) with the full counts, and up to --limit items of each kind, newest first (default 10; --limit 0 gives counts only). The name matches exactly, as concept delete does, and a miss offers a case variant. It replaces the raw sqlite3 joins that judging a concept suggest candidate used to need.
kb concept recall finds the concepts named in some text (arguments, or stdin with -) and lists the observations, records and document sections linked to them, ranked by how many of those concepts each matches and then by recency, with the concepts each hit matched. --concept NAME,... names concepts directly, --project restricts the hits, --limit caps them. Text that matches no concept exits 1. Harvey's memory recall uses the same library call.
kb record fuzzy-tag --project NAME reports near-miss spellings of known concepts in decision records (a detoast for the concept toast), which exact matching never links, and the tags: line that would link them. It writes nothing by default. --write adds the concept to the tags: of proposed records only, changes nothing else in the file, and never touches an accepted record; kb ingest then links the tags. --concept NAME,... widens the named concepts to forms that contain the name.
kb check-db [--jsonl FILE] compares the database with the JSONL dump beside it by full content, never by file time, and recommends kb import, kb export, or both. It is read-only and exits 0 in sync and 1 otherwise. There are no tombstones, so rows only in the dump may be rows deleted here on purpose, and the report says so.
The detection half of kb merge is now a read-only library pipeline shared with check-db; merge's output is unchanged.
Two fixes. kb import no longer rewrites an observation kind outside note, finding, decision, question and hypothesis to note (DR-0054): it keeps the kind and prints a warning: line, or a Warnings list under --json, and still exits 0. The rewrite made kb check-db report a false divergence, and following its advice to import and export would have written the changed kind into the authoritative dump. kb project add (DR-0055) no longer prints "added" for a name that already exists: it exits 1 with already exists, as project rename does, and writes nothing (it used to move updated_at, which merge uses to pick a winner, and drop the status and description you gave it). A --status typed after NAME is a usage error that says the flag goes before NAME, where it used to become part of the description; -- before NAME keeps a flag-looking word as text.
Upgrading: two things that worked change. kb project add on an existing name now exits 1, where it exited 0, so a script that repeated the call must expect that; the library's AddProject still returns the existing id. And a record file that does not parse now exits 65 (wrong content) from record set-status, record supersede and project rename (the verbs that read a record file to edit it) where it exited 2, since the file's content is what is wrong, not the command line. Library additions: ConceptDetail, RecallByText, RecallByNames, RecordFuzzyReport, AddRecordTags, CompareToJSONL, DiffDatabases, PrepareMergeScratch and DetectIdentityIssues; ImportTableSummary gains a Warnings field.
Full Changelog: v0.0.14...v0.0.15