Skip to content

Knowledge vault ​

The knowledge vault gives the agent loop a long-term knowledge base it can use without reading it. Each turn, kdeps walks the vault's link graph from the words of the request, with no model involved. It then hands the model the few notes worth reading (paths and one-line summaries), not the whole vault.

your requestKDEPS.md routing table(where everything lives)project cardstatus, next step, placesgraph recall (no model)words -> matching notes -> 2 hops3-8 notes namedpath + summarymodel reads onlythe notes it needs

Recall is the default step of every prompt kdeps sends a model: each agent-loop turn (terminal and desktop app) and each workflow chat call. The agent loop's own internal calls (compaction, prompt refinement) skip it.

A vault of 2,000 notes holds about a million words. That's more than any model can read, and partial reads cost accuracy, time and money. With recall, a question typically reads a routing table, one card and a handful of notes.

One home per fact ​

FactIts only home
Status, next step, places on diskthe project's card: projects/<name>/<name>.md
What happened: focus, what was built, mistakes, decisions, winsthe session note: projects/<name>/sessions/
Why something was decidedone decision note: projects/<name>/decisions/
What the agent remembersmemory notes: projects/<name>/memory/ (see Persistent memory)
An idea, gotcha or conceptone note: projects/<name>/notes/, or shared/ when it spans projects
How notes connectthe link graph, in the vault's hidden .index/

A fact written in two places goes stale in one of them. kdeps knowledge check finds those.

Projects ​

Every place kdeps runs is a project, and each project has one folder that holds all of it. kdeps creates the folder and its card the first time it runs in a place, then fills it in as you work. Nothing is set up by hand.

kdeps runs in a foldera card's repo/folder/workflowrow covers it?use that projectname it: git repository root,else the folder; workflow: its namecreate projects/<name>/and its cardevery turn fillssessions/ memory/ decisions/ notes/yesno
text
~/.kdeps/notes/                       # the vault (knowledge.vault)
  KDEPS.md                            # routing table + rules; loaded into every session
  schema.md                           # how cards and notes are written
  projects/
    my-app/                           # created on the first prompt in ~/code/my-app
      my-app.md                       # the card: status, next step, places on disk
      sessions/                       # one note per session, updated every turn
      memory/                         # one note per [MEMORY: key]; .auto/ holds thinking and tool captures
      decisions/                      # one note per decision from a session summary
      notes/                          # notes the model saves, and your own
  shared/                             # knowledge across projects; shared/memory/ with KDEPS_MEMORY_GLOBAL=1
  inbox/                              # notes dropped by hand, not yet filed
  archive/                            # projects whose card says status: archived
  GRAPH_REPORT.md                     # god nodes, communities, surprising connections (rebuilt; not a note)
  graph.html                          # the graph explorer page: communities as clusters, a legend
  .index/                             # graph.json and caches (hidden; rebuilt)

The layout is the same for every use: a code repository, a folder of documents, a workflow, a bot, a research topic. What kind of project it is goes in the card's type, not in the folder names.

EventWhat kdeps writes
First prompt in a place no card coversprojects/<name>/<name>.md (status: active)
Every turnsessions/<date> <topic>.md, rewritten in place
[MEMORY: key] valuememory/<key>.md
Compaction, or the end of a terminal sessionthe session note from the model's summary; one decisions/ note per Key Decision; the first next step on the card
knowledge_note_savenotes/ (decisions/ for type decision), or shared/, inbox/
knowledge_card_update with status: archivedmoves projects/<name>/ to archive/<name>/; the next turn there moves it back
A workflow chat call, with workflow_notes: truesessions/<date> <workflow> runs.md, one line per call

Set up ​

Nothing to set up: the vault is on by default, in ~/.kdeps/notes. The first session creates it, and every session rebuilds its graph in the background.

Turn itHow
off for goodknowledge.enabled: false in ~/.kdeps/config.yaml
off or on, remembered across sessions/knowledge off, /knowledge on
to another folderknowledge.vault in config.yaml, or kdeps knowledge init <folder>
yaml
# ~/.kdeps/config.yaml
knowledge:
  enabled: true               # false: no recall, no notes, no knowledge tools
  vault: ~/.kdeps/notes       # the default
  session_notes: true         # agent sessions write a note per session (default true)
  workflow_notes: false       # workflow chat calls log to their project's sessions/ (default false)
  recall:
    hops: 2                   # how far from the matched notes to walk
    budget_tokens: 1500       # most tokens of recalled paths and summaries per turn

Cards ​

A card is short on purpose. It points; it never tells the story. kdeps writes this one the first time it runs in ~/code/my-app:

markdown
---
type: project          # any word: project, client, area, research, bot
status: active         # the only place status lives; archived moves the folder to archive/
next: (none)           # the one next step; session summaries fill it in
updated: 2026-10-15
---
| Source | Path |
|---|---|
| repo | /home/me/code/my-app |   <- runs in this folder (or below it) use this project

Add rows to make several places one project: repo (a git repository; its Go packages join the graph), folder or workflow. The deepest matching row wins. A search row is a search folder: searched with the project, but not one of its places. kdeps keeps one branch row naming the git branch the project is on, updated at the start of a turn when it changes. kdeps adds an index row for each place that has a search index (built by /search index, kept under ~/.kdeps), so the card says where everything about the project lives. Every turn carries a status overview of the active projects, read from the cards at that moment (<knowledge-status>); it is never stored. The model reads and changes cards with knowledge_card_get and knowledge_card_update.

Notes ​

Every note is plain markdown with frontmatter. summary is what recall shows before anyone opens the note.

markdown
---
type: decision          # session | decision | concept | gotcha | tool | note
status: evergreen
tags: [billing]
created: 2026-10-15
summary: Bill monthly, not per call - per-call billing doubled churn.
links: ["[[Stripe webhook retries]]"]
---
We moved to monthly billing because ...
  • Link notes with [[Note title]] or [[folder/Note title]]. A link resolves by path, by title anywhere in the vault (the closest one wins when two share a title) or by aliases:.
  • Every link kdeps writes uses the full vault path - [[projects/app/app]], [[projects/app/sessions/2026-10-15 0900 billing]], [[shared/Stripe gotcha]] - so it can never point at the wrong note. A link to a project that was archived later still resolves, by its title.
  • Links inside code blocks are examples, not links.
  • One idea per note. The model saves new ones with knowledge_note_save into the project's notes/ (or decisions/, shared/, inbox/); it refuses a title that already has a note anywhere in the vault.

Session notes ​

After every turn, kdeps writes the session's note into the project's sessions/ folder and rewrites it in place as the conversation goes on. A note covers one thread: when a request is unrelated to the thread so far, the next note starts, so a session that moves from billing to Kubernetes leaves two notes. Each note links the project's card, so the card's backlinks list every session.

text
switch billing to monthly invoices      -> 2026-10-16 0900 switch billing to monthly invoices.md
why are monthly invoices late           -> same note (shares the thread's words)
yes do it                               -> same note (a short follow-up)
configure kubernetes liveness probes    -> 2026-10-16 0912 configure kubernetes liveness probes.md

Telling them apart needs no model: a request continues the thread when it shares at least a fifth of its content words with the thread (stemmed, without stopwords or task verbs like fix, add, make), or has fewer than three content words. The model's summary at compaction and session end goes to the current thread's note, written from that thread's messages only.

markdown
---
type: session
project: my-app
session: 7f3c...
summary: Ship knowledge recall for my-app
links: ["[[my-app]]"]
branch: feat/recall              # in a git repository: the branch the thread ran on
commits: 3f2a91c0b7de..9c41e2d07a55  # HEAD when the thread began .. HEAD now
---
## Focus
## What was built
## Mistakes
## Decisions
## Wins
## Git
On branch `feat/recall`, commits `3f2a91c0b7de..9c41e2d07a55`: `git log 3f2a91c0b7de..9c41e2d07a55` shows them.

In a git repository a note points into git instead of copying it: branch and commits (from the commit HEAD was at when the thread began to the one it is at now, read with git rev-parse at the start of each turn), and a ## Git line the model can turn into git log or git diff. The history itself stays in git (one home per fact), so a rebase or a squash never leaves the vault behind. A rewritten note keeps the start it first recorded, even in a resumed session. Outside a git repository a note has no git lines.

After each turn the note is updated without a model call: your prompts, the files written or edited, decisions saved to memory and tools that failed. At compaction the model's summary replaces it with a written one (no extra model call: compaction makes that summary anyway), and later turns are added on top. When an interactive terminal session ends, one summary call covers the turns since the last note; a piped or scripted session exits at once (its compactions still write notes). The summary's first next step goes to the card's next, not into the note, and each of its Key Decisions becomes a note in decisions/, titled by its bold lead (- **Monthly billing**: per-call doubled churn becomes decisions/Monthly billing.md). A decision that already has a note is left alone.

Workflow mode ​

A workflow chat call recalls from the vault by default. Writing is off: a workflow can run thousands of times. Turn it on to keep a log per workflow:

yaml
# ~/.kdeps/config.yaml
knowledge:
  workflow_notes: true     # each chat call adds one line to its workflow's run note for the day

A workflow's project is keyed by its metadata.name: the first logged run creates projects/<name>/, with a card whose workflow row is the folder it ran from; the same workflow run from anywhere else logs to the same project. Each chat call adds - 14:02:11 <prompt> -> <reply> to sessions/<date> <name> runs.md. A resource with knowledge: false neither recalls nor writes. Run notes join the graph on its next build (any agent session, or kdeps knowledge build).

The graph ​

kdeps knowledge build turns the vault into a graph:

  • Nodes: each note, each tag, and each Go package of every card's repo row.
  • Edges: wikilinks (references), frontmatter links (relates_to), tags (tagged) and Go imports (depends_on).
  • Provenance: every edge records how it was found. Edges from links and imports are extracted; code goes through the Go parser, never a model. A local model can add inferred edges (see Model extraction).
text
$ kdeps knowledge build
2003 notes (2003 changed), 1986 code files -> 4210 nodes, 9873 edges in 1.2s
$ kdeps knowledge build
2003 notes (0 changed), 1986 code files -> 4210 nodes, 9873 edges in 270ms

Code files are the ones git tracks or would track, so .gitignored folders stay out; without git, every .go file outside vendor/, testdata/ and hidden folders.

The graph lives in the vault's hidden .index/ folder (graph.json and the caches), so it travels with the vault and is never read as a note. GRAPH_REPORT.md and graph.html are written at the vault root, where you see them; the report is skipped when the vault is read, so it never becomes a note. A GRAPH_REPORT.md or graph.html of your own there is never replaced: kdeps only rewrites the ones it wrote, and yours stays a note. A rebuild re-reads only changed files.

Model extraction ​

Links written in notes become extracted edges. A local model can add what the notes do not link: it reads each changed note and lists the projects, tools, decisions, rationales, gotchas and concepts it is about, and how they relate. Its findings join the graph as inferred edges with the model's confidence (a note mentions an entity; entities depends_on, rationale_for, ... each other), or ambiguous ones below 0.5 confidence, listed under "Edges to review" in the report. An entity named like a note is that note, so two notes about the same tool meet at two hops.

changed notesfirst note alone(loads the model)the rest in parallel(workers)extract.jsonby note hashgraph buildinferred / ambiguous edges
  • In agent sessions it runs at session end, after the session note: up to per_session changed notes, with the session's model when it is a local one (llamafile, GGUF, Ollama). With a cloud model it is skipped unless knowledge.extract.model names a local model. It never runs during your turns. /knowledge extract runs it now, over every changed note.
  • From the shell: kdeps knowledge build --extract [--model <local model>] [--limit N].
  • A note is read again only when it changes; a failed note is retried on the next run.
yaml
# ~/.kdeps/config.yaml
knowledge:
  extract:
    enabled: true
    model: llama3.2:3b        # a 3B+ local model finds far more than a 1B one
    workers: 2                # parallel calls after the first
    per_session: 20           # changed notes read at each session end

Communities and the report ​

There is one graph per vault, covering every project, shared/ and the Go packages of each card's repo row. Each build groups it into communities with the Louvain method: notes and packages that link mostly among themselves, which usually follow projects and the areas inside them. Each node gets a community number in graph.json; 0 is the largest. At the vault root, the build writes GRAPH_REPORT.md and graph.html, a page to explore the graph: each community gathers in its own colored cluster, a legend lists every community with its size and best-connected members (click one to focus it), and you can search, zoom and hover for a note's summary. The page's template (templates/knowledge) is installed the first time it is needed, so it is written under any asset profile; kdeps knowledge build prints where it is.

bash
kdeps knowledge report
text
# Knowledge graph report
| Notes | Nodes | Edges | Extracted edges | Communities | Modularity |
| 2003  | 4210  | 9873  | 100%            | 37          | 0.61       |

## God nodes            the most connected notes and packages: changing them touches the most
## Communities          each group with its best-connected members and the summary of its top note
## Surprising connections
- [[projects/app/decisions/Billing decision]] (community 3, 40 nodes) -[references, extracted]-> [[shared/Kubernetes probes]] (community 9, 25 nodes)
## Links to notes that do not exist

A surprising connection is a single link between two communities that otherwise never touch, ranked by the size of the smaller one: a lone bridge between two large groups is the least expected.

Inside an agent session, kdeps rebuilds the graph in the background when the session starts and after it writes a note.

Recall ​

Before each model call, kdeps:

  1. Scores graph nodes on the request's words. Rarer words count more, a word that is part of a note's title counts double, and word forms meet (billing matches bill). Notes kdeps writes itself rank lower than notes you curate: session notes at 0.4x, memory notes at 0.6x. The session's own note is never recalled into that session.
  2. Walks up to hops edges from the best matches. Extracted edges count fully, and each hop halves the score.
  3. Hands the model the best notes within budget_tokens, as paths it can open with read_file.
  4. When the project's places or search folders have a search index (/search index), adds the files that match most of the request's words, up to 3 per folder, in a <knowledge-files> list headed by the folder and its index path. A file is listed once, even when two folders overlap. The model is told to open them with read_file or search further with search_local: path set to one folder, or no path for all of the project's folders. The index is only read, never built or changed, and a busy index is skipped.
text
<knowledge-files>
Files in this project's search index that match the request (best first). Open the ones you need with read_file; search further with search_local, path set to the folder (or no path to search all of the project's folders).
Folder /home/me/code/my-app (search index /home/me/.kdeps/projects/.../index.db):
- /home/me/code/my-app/billing/invoices.go - monthly invoices go out on the first day
Folder /home/me/docs/billing-specs (search index /home/me/.kdeps/projects/.../index.db):
- /home/me/docs/billing-specs/proration.md - prorate upgrades to the day
</knowledge-files>
text
<knowledge-recall>
Notes in the knowledge vault related to this request, from its link graph (best first). ...
- /home/me/notes/projects/my-app/decisions/Billing decision.md - Bill monthly, not per call. ...
- /home/me/notes/shared/Stripe webhook retries.md - Webhooks retry for 3 days. (linked from Billing decision)
</knowledge-recall>

Recall is added to the turn, not to the cached system prompt, so each request gets its own. The terminal shows what it cost:

text
recall: 4 notes (~180 tok), 2 files

/recall shows the last turn's recall and why each note was chosen; /recall <words> recalls for other words; /knowledge shows whether the vault is on and where it is. From the shell:

bash
kdeps knowledge recall "why monthly billing"

Search folders ​

A search folder is a folder outside the project (docs, specs, a shared library) that recall and search_local cover as if it were part of the project. It is indexed under ~/.kdeps, like the project's own folder, and nothing is written into it.

kdeps --index ~/docs/search add ~/docsknowledge_card_updateproject card| search | /home/me/docs |~/.kdeps/projects/docs-<hash>/index.dbrecall: <knowledge-files>per foldersearch_local(no path: every folder)records the full pathindexes nowwhich folders

The card keeps it as a search row. Unlike a repo or folder row, a session started inside a search folder is not this project's; the folder gets its own project:

markdown
| Source | Path |
|---|---|
| repo | /home/me/code/my-app |
| search | /home/me/docs/billing-specs |
| index | /home/me/.kdeps/projects/billing-specs-3f2a91c0/index.db |

Add one as a session starts, from the shell, inside a session, or let the model add one:

bash
kdeps --index ~/docs/billing-specs                # add and index before the session starts; repeatable, fine to pass every time
kdeps knowledge folders                           # list the project's folders and their indexes
kdeps knowledge folders add ~/docs/billing-specs  # add and index now
kdeps knowledge folders index                     # update every folder's index
kdeps knowledge folders remove ~/docs/billing-specs
text
/search folders                   list them
/search add ~/docs/billing-specs  add and index now
/search remove ~/docs/billing-specs
/search index                     update the index of every folder the project searches

The model uses knowledge_card_update with add_search_folder or remove_search_folder. kdeps refuses your home folder, a filesystem root, the vault, the project's own folder, a folder inside one the project already searches, and a path that is not a folder. Key and credential files (SSH keys, .env, *.pem, credentials, anything in .ssh, .aws or .gnupg) are never indexed or returned by a search, in any folder. A search folder that is deleted shows up in kdeps knowledge check.

Check ​

bash
kdeps knowledge check
text
  projects/my-app/notes/old status.md: has a next step; it belongs in the project card (one home per fact)
  shared/Graph recall.md: links to [[Louvain]], which has no note
  shared/Pricing.md: has the same summary as shared/Tiers.md; keep the fact in one note and link it
  projects/web/web.md: card holds 9 lines of prose; move the story to a vault note and link it
  projects/my-app/my-app.md: search folder /home/me/old-specs is gone; remove it with kdeps knowledge folders remove /home/me/old-specs

It exits non-zero when it finds something, so it can run in CI.

Tools ​

ToolDoes
knowledge_recallRecall notes for other words than the request
knowledge_card_getRead a card (default: the working directory's project, created on first use)
knowledge_card_updateSet status and/or next; stamps updated; archived moves the project to archive/; add_search_folder / remove_search_folder change the search folders
knowledge_note_saveSave a new one-idea note; scope: project (default), shared or inbox

They are offered in agent sessions while the vault is on (the default), refuse while /knowledge off, and ship with the agent asset profile.

Released under the Apache 2.0 License.