Guides

Knowledge base and search

How notes become knowledge base pages, what the filer and nightly tidy do, and how agents search by keyword and by meaning.

On this page

Every workspace has a knowledge base: Markdown pages in your git folder, kept up to date from what agents learn, and searched before they answer about past work. This page explains how it fills itself, how to turn on search by meaning, and how to look after it.

Conversation goes quiet Agent writes a note wheems note knowledge/inbox/ waits for the filer The filer files it by topic Checked in code the filer’s work knowledge/ pages/one topic per page brief.mdwhat every agent loads notes/the note, kept as a source Committed to git as “Wheems” Conversation goes quiet Agent writes a note wheems note knowledge/inbox/ waits for the filer The filer files it by topic Checked in code the filer’s work knowledge/ pages/one topic per page brief.mdwhat every agent loads notes/the note, kept as a source Committed to git as “Wheems”
  1. Agents write notes, never pages.
  2. The filer, a built-in agent you never talk to, turns each note into page changes.
  3. Wheems checks the filer’s work in code, then writes and commits it.
  4. Agents search the pages, notes and inbox with wheems kb search.
  5. Overnight, the tidy reports contradictions and stale pages, and refreshes the brief.

Two pages are loaded into every agent’s instructions when it starts:

Page Where Who changes it
About you ~/wheems/about-you.md, shared by every workspace You. The filer can suggest changes, which you approve in wheems review.
The brief workspaces/<id>/knowledge/brief.md The filer keeps it current: what’s in progress, recent decisions, what’s waiting on you.

Only the first 4,000 characters of about-you.md are loaded. The filer keeps the brief under 4,000 characters.

Agents write notes with wheems note, which reads Markdown:

Terminal (in an agent's session)
wheems note - <<'EOF'
# Picked the boat name
Halcyon, over Kestrel, because it's calmer.
EOF
  • Wheems adds what agents can’t be trusted with: the workspace, agent, engine, conversation and time. It saves the note to knowledge/inbox/, named by time, agent and title.
  • wheems note works only inside a conversation Wheems started. Anywhere else it fails with wheems note works inside a conversation started by Wheems (WHEEMS_CONVERSATION is not set).
  • A note is at most 32 KB.
  • A note that looks like it holds a password, token or key is refused: The note looks like it holds a password, token or key. Notes are kept in git: write it again without it.

A saved note looks like this:

knowledge/inbox/2026-11-11-213709-chief-of-staff-picked-the-boat-name.md
---
workspace: personal
agent: chief-of-staff
engine: claude-code
conversation: "personal:slack:D0123ABCD:1762896000.000100"
origin: person
written: 2026-11-11T21:37:09.000Z
---
# Picked the boat name
Halcyon, over Kestrel, because it's calmer.

Notes when a conversation goes quiet

Link to “Notes when a conversation goes quiet”

When a conversation has been quiet for 30 minutes after new work, and before an idle session is stopped to make room, Wheems asks the agent for a note, as a turn of its own. That turn’s answer is never posted to Slack.

Change the wait, or turn it off, in workspace.yaml:

~/wheems/workspaces/personal/workspace.yaml
knowledge:
note_after_idle: 30 # minutes; 0 turns it off

When a note lands, the service runs the filer. It runs in Herdr core like any agent, so you can watch it with hc attach, and handles one note at a time per workspace. It works on a copy of the knowledge base in .wheems/filing/<workspace>/: it reads the note, updates or creates pages, and keeps the brief current.

Then Wheems checks its work in code. A change is applied only if:

  • each page has a name of lowercase words and dashes, and keeps at least three quarters of its text;
  • every changed page lists the note among its sources, and keeps the sources it had;
  • no page is deleted;
  • the brief stays under 4,000 characters;
  • nothing looks like a credential.

Anything else the filer wrote is ignored. Changes that pass are written, the note moves to notes/<year>/<month>/, and only those paths are committed, as “Wheems”.

A page looks like this:

knowledge/pages/boat-name.md
---
title: Boat name
sources:
- 2026-11-11-213709-chief-of-staff-picked-the-boat-name.md
updated: 2026-11-11
---
The boat is called Halcyon, chosen over Kestrel because it's calmer.

Your edits are safe. If a page or the brief changed while the filer worked, such as an edit by hand, nothing is applied and the note is filed again from the new version.

When filing fails. A note the filer can’t file is tried three times, then waits until the service restarts. A note that looks like it holds a credential is moved to .wheems/quarantine/ and never filed or committed.

The filer runs on Claude Sonnet when the chief of staff is on Claude Code, and otherwise on the chief of staff’s engine and model. Change it per workspace:

~/wheems/workspaces/acme/workspace.yaml
knowledge:
filer:
engine: claude-code
model: claude-sonnet-5-5
account: claude-subscription

Once a night the filer reads the whole knowledge base and writes two reports for you:

  • knowledge/reports/contradictions.md: places where pages disagree with each other or with the brief, and which looks current;
  • knowledge/reports/stale.md: pages that look out of date, such as a plan for a date that has passed.

It also refreshes the brief. It changes no page. Nights with nothing new are skipped, so it costs nothing then. A service that was stopped overnight tidies when it starts.

~/wheems/workspaces/acme/workspace.yaml
knowledge:
tidy_at: '03:00' # local time; false turns it off

Agents search before answering about past work. You can too:

Terminal
wheems kb search what did we decide about the boat name --workspace personal
Output
Boat name
/Users/you/wheems/workspaces/personal/knowledge/pages/boat-name.md (page, updated 2026-11-11)
The boat is called Halcyon, chosen over Kestrel because it's calmer.

When nothing matches:

Output
Nothing in the knowledge base matches.

It searches one workspace: its pages, filed notes and inbox. Inside an agent’s session, that’s the agent’s own workspace. From your terminal, give --workspace unless you have only one. Add --limit <n> for more than five results, or --json for scripts.

  • By keyword, always, with SQLite’s full-text search, built into Node.js. Common words such as “what” and “the” are left out, and any remaining word can match.
  • By meaning too, once you turn it on (below).
  • The two rankings are combined by reciprocal rank fusion, and each file is shown by its best passage.
  • A match by meaning alone must score at least the model’s floor (0.5 for nomic-embed-text) and be within 0.1 of the best match. So a question the knowledge base can’t answer gets “Nothing in the knowledge base matches.” rather than unrelated pages.
  • Notes from automated jobs, and pages built only from them, count half as much as your own work.

Files are split into passages of up to 1,200 characters, starting afresh at each heading. Links, files over 1 MB, and anything that looks like a credential are left out of the index.

Search by meaning finds “the vessel is Halcyon” when you ask “what is the boat called”. It uses Ollama with nomic-embed-text, running on your Mac for free. Nothing you index is sent anywhere.

  1. Install Ollama and start it.
  2. Run wheems setup and choose Knowledge, then By meaning, with Ollama. Setup uses the embedding model Ollama already has, or offers to run ollama pull nomic-embed-text.
  3. Restart the service so it builds the index with the model: wheems service restart.

Setup writes this to install.yaml:

~/wheems/install.yaml
knowledge:
embeddings:
driver: ollama
model: nomic-embed-text

Add url if Ollama isn’t at http://127.0.0.1:11434. To go back to keywords only, choose Keyword search only in setup, or remove embeddings.

The index is running state in .wheems/index/, never committed and rebuildable at any time. The service brings it up to date when it starts, after each note is filed, and every ten minutes for edits by hand. Only files that changed are read again.

Terminal
wheems kb reindex # every workspace
wheems kb reindex --workspace acme # one
Output
acme: indexed 12 files with nomic-embed-text

reindex builds a fresh index and swaps it in when it’s done, so search keeps working meanwhile. When the service is running, it does the rebuild.

  • Changing the embedding model rebuilds the index, because vectors from different models can’t be compared. Until it finishes, search uses keywords only.
  • If Ollama isn’t running, search falls back to keywords and says so. wheems doctor warns: Ollama isn't answering at http://127.0.0.1:11434, so search is keyword-only for now.

Editing the knowledge base by hand

Link to “Editing the knowledge base by hand”

Pages are Markdown files in git: edit them in any editor. The filer never overwrites an edit, and the service re-indexes within ten minutes. To undo a change the filer made, use git in ~/wheems.