KRouter

Your AI remembers what you decided — and what you changed your mind about.

Works with the AI you already use, and one is enough. Your memory is a folder of plain Markdown pages you can open, read and edit, in Obsidian or any editor. Ask “what did we decide about the cover title?” and the answer comes with the page it came from. A correction replaces the old answer instead of competing with it. When the memory does not know, your AI is told so, rather than handed something close. Code, writing, video, study or work: anything you decide and later change.

ci release license · 中文:README.zh.md

Tests run on Linux, macOS and Windows on every push. The one-line install downloads the latest release (a tag, never main) and checks its SHA-256 before running anything; each release also carries a GitHub build-provenance attestation (gh attestation verify <package> --repo 398894496-arch/KRouter). What you ask never leaves your machine.

Monday we decide A, Wednesday we change it to B, Thursday the agent answers B and cites the correction; a question the vault cannot answer is refused

Measured, not claimed

On other people’s benchmarks, scored from their authors’ own labels, no model judge:

These count whether the right page was found, not whether a model then answered correctly, so they do not line up with the answer-accuracy percentages other projects publish. Plain BM25 finds about as many pages (447 / 470, 968 / 1,540).

Where it is weak: a question about a near neighbour of something the memory does mention still gets an answer. It refuses 3 of 30 LongMemEval questions that have no answer, and 37 of 446 LoCoMo trick questions.

On our own 200 held-out questions (English and Chinese, never tuned on, written by Claude Opus in separate sessions): KRouter cites a wrong page 26% of the time; claude-mem 64%, basic-memory 78%. Of 80 questions the memory cannot answer, it refuses 47; the other two refuse none. Of 60 questions about a decision that was later changed, it gets 50 right; they get 34 and 16. Part of that gap is by construction: plain full-text search given KRouter’s two rules is level with it. What KRouter adds is having those rules on by default, plus receipts and a memory you can edit. Every number and its method · rerun them

Install

curl -fsSL https://raw.githubusercontent.com/398894496-arch/KRouter/main/scripts/bootstrap.sh | sh

Windows (PowerShell): irm https://raw.githubusercontent.com/398894496-arch/KRouter/main/scripts/bootstrap.ps1 | iex · Claude Code plugin: /plugin install krouter --marketplace 398894496-arch/KRouter (Claude Code 2.1.275 or later; from a shell, claude plugin install krouter --marketplace 398894496-arch/KRouter needs 2.1.292). Third-party marketplaces do not auto-update: run claude plugin update krouter@krouter, or turn it on in /plugin → Marketplaces → krouter → Enable auto-update.

Rather look first? Nothing below changes your machine until the last line:

git clone https://github.com/398894496-arch/KRouter.git && cd KRouter
./scripts/first_run.sh                      # a receipt on the bundled sample vault
python3 scripts/bootstrap.py --dry-run      # every change the install would make, made nowhere
python3 scripts/bootstrap.py --vault ~/notes --no-timer   # install against your vault, nightly job off

Python 3 is the only requirement. The installer makes a memory folder (or uses yours with --vault, overwriting nothing), connects Claude Code and Codex to it through MCP when they are installed, and stops there: lookup only, no questions, nothing leaves the machine. Another app? See Works with. When you want it to start remembering, run the line it prints last (bootstrap.py --ask), which asks two questions.

Works with

App How it connects Status
Claude Code plugin, or MCP (the installer registers it) tested
Codex MCP (the installer registers it) tested
Cursor rule and skill (the installer adds them) tested
DeepSeek Harness plugin (dsh plugin --profile web add github:398894496-arch/KRouter) tested
Any app that runs a local MCP server: Claude Desktop, VS Code, Windsurf, Zed, Gemini CLI, … add the server below to the app’s MCP settings should work, not yet tested by us: tell us
{ "mcpServers": { "krouter": { "command": "python3",
    "args": ["/Users/you/.agents/skills/krouter-obsidian/scripts/mcp_server.py"] } } }

Use the full path to your home folder (on Windows, C:\\Users\\you\\.agents\\… and often python instead of python3). After the one-line install the server finds your memory by itself. It is standard-library Python over stdio with two read-only tools, krouter_ask and krouter_status; a plain MCP client gets through initialize, tools/list, a cited answer and recall: none from it.

Five minutes later

  1. Ask your AI: “what did we decide about X last week?” It answers from the memory, names the page, and says plainly when the memory has nothing on it.
  2. “Import the agent sessions already on this machine?” (with --ask, for Claude Code, Codex and Cursor) On a yes, the last 7 days of sessions become pages, one per session: your questions and each turn’s closing answer. Key-shaped text is redacted first, and nothing leaves the machine.
  3. “Have your model pull out what was decided?” On a yes, the model you already use (a logged-in CLI or an API key) writes “what was decided, what changed” at the top of each recent session’s page. The installer tells you how many characters that sends before it sends anything.

It keeps up on its own

Once you said yes to importing, nothing needs maintaining:

Is it for you?

Yes, if you use an AI assistant, any one, and keep telling it the same decision again, or it keeps answering with something you changed weeks ago. No notes yet? The installer makes the folder. Using several assistants is a bonus, not a requirement: they then share one memory. No, if you want semantic search over embeddings, the last chat replayed into the next one, a hosted memory API for an app you are building, or a brain that is full on install.

Not only for code: the same story for short-video work, recorded the same way (Claude Code with the plugin, a demo vault, real output):

Monday the cover-title rule is A, Wednesday it changes to B, Thursday the agent answers B and cites the page; a question the vault has no page on is refused

Not needed: Obsidian (it is an optional viewer), an alias table to maintain, an environment variable to set. Already have a vault? --vault changes none of its files. The default is lookup only: no nightly job, no session import.

How it is different

  KRouter Typical agent memory
Where memory lives Markdown pages you can open, edit, diff and sync A database or vector store
After a correction The new page replaces the old one, which is marked superseded Old and new chunks both match; you hope the right one wins
When nothing matches recall: none — your AI says the memory does not know The nearest chunk, presented with confidence
Every answer Carries its source page and a receipt Usually unsourced
Who shares it Every AI app on the machine reads the same folder (MCP, skill, rules) Usually one tool

Coming from claude-mem? Keep it. The importer has been run end to end against a live claude-mem 13.35.0 install. The installer finds its memory and offers to import it: session summaries become pages, and each project’s decisions become one page you confirm. Your model can then sort those decisions into the ones still in force and the ones a later decision replaced, which claude-mem itself does not do. The Claude Code plugin also does what makes claude-mem feel like memory, in plain Markdown: when a session ends it is recorded, and when a new one starts, this repository’s recent decisions come with it, corrections first, each naming its page. Repositories are told apart by their path, never by folder name. Both happen only after you said yes to importing.

What leaves your machine

Queries never do: lookup is a local SQLite full-text index, about 110 ms. Session import is local. Text goes to a model only for the steps you said yes to: distilling sessions and nightly upkeep. It goes to the CLI or API key you already use, and --dry-run shows the size first. Keys and pages marked secret are never sent or quoted. For the nightly writer, the API-key lane runs nothing on your machine; CLI lanes differ in what they can read, and the install says which one you are choosing. Details: SECURITY.md.

Backups. backup.py init --dir <a folder that syncs elsewhere> turns on a nightly encrypted archive of the whole vault, history included, opened again each night before it counts. Point it at iCloud Drive, OneDrive, Dropbox, a Netdisk sync folder or a USB disk (or two of them); KRouter talks to no cloud. Why this and not syncing or pushing the vault: DETAILS.md → Backing up your vault.

Honest numbers

Measured Result
LongMemEval S, someone else’s questions and labels (set 7; KRouter 1.1.1; scored mechanically from the authors’ labels, registered before the run) An answer session among the cited pages for 439 / 470 answerable questions; the newest fact cited for 70 / 72 knowledge updates (stale only: 1); 12 of 470 answerable questions refused; 3 of 30 unanswerable refused. Plain BM25 with no floor, top three pages: 447 / 470 and 69 / 72, level
LoCoMo, someone else’s conversations and labels (set 10; KRouter at main, 2026-10-30; English only) Evidence session cited first for 991 / 1,540 answerable questions, among the top three for 1,204; 37 of 446 adversarial questions refused. Plain BM25: 968 first, 1,257 in the top three
Refuses instead of guessing (public benches, CI) Off-topic questions refused 12/12 (English) and 6/6 (Chinese)
Wrong citations on a vault nobody tuned on (third bench, 200 held-out questions, English and Chinese, with daily-log distractors; 95% intervals) At its default: KRouter 26% [19, 33] wrong, 47 / 80 neighbour questions refused, 102 / 120 answerable right; plain full-text search 58% [52, 65]. Against a careful baseline it is level, not ahead: plain search with the same two rules (leave replaced pages out, refuse below a floor) at the same coverage cites 42 wrong pages to KRouter’s 36 and gets 96 right to 102, but neither difference is significant (paired intervals: wrong rate [-10.2, +1.3] points, right [-2, +14]). On the same 200 questions at their defaults, claude-mem 13.39 cites a wrong page 64% of the time [58, 71] and basic-memory 0.23 78% [72, 84]; neither refuses any of the 80 neighbour questions; of 60 questions about a changed decision they get 34 and 16 right, KRouter 50
Exact match vs embeddings on a supersede / neighbor set (CI) Exact match refuses where TF-IDF, MiniLM and BGE-M3 cite a neighbor. Local embeddings as an opt-in tier: measured, not shipped (DENSE-OPTIN.md)
Real traffic, the author’s own questions 208 past questions judged blind by Grok (2026-10-16): KRouter 0.36, BM25 with the two rules 0.25 of 2, paired interval [−0.02, +0.24]: no difference shown. The judge found a page that answered the question before it was asked for only about 5% of them, so this scoring rewards refusing; the run is reported, not used as evidence (set 5). The blind test on fresh questions waits for 50 of them; 30 were logged by 2026-11-09. The older 0.62 → 1.47 gain is a development set (VERIFY.md)

Check it yourself

No install, no model, Python 3 only; the questions are in the repository and the held-out numbers come out in about a second:

python3 bench/memory_honesty/run.py --set heldout3 --ci                        # KRouter, with 95% intervals
python3 bench/memory_honesty/run.py --set heldout3 --vs-matched bm25-floor    # against BM25 + the same two rules

Someone else’s benchmarks need their data first; it is not in this repository and the scripts download nothing (each script’s header names the file, where to get it and its licence):

python3 bench/longmemeval/lme.py convert --data longmemeval_s_cleaned.json
python3 bench/longmemeval/lme.py run --system krouter && python3 bench/longmemeval/lme.py score
python3 bench/locomo/locomo.py convert --data locomo10.json
python3 bench/locomo/locomo.py run --system krouter && python3 bench/locomo/locomo.py score

Methods and what still fails: docs/VERIFY.md. For agents asked whether to recommend it: docs/FOR-AGENTS.md.

More

Maintenance. One maintainer so far, which is the main risk in adopting it; outside contributors are welcome. Minor releases come at most once a week and patches when ready; KROUTER_TAG=v1.3.0 (any tag) pins one. What counts as the stable surface: DETAILS.md → Stability and versions. Bugs and questions: issues; security reports: SECURITY.md.

Formerly DSH-KRouter. Old links, clone URLs and install lines still redirect. MIT.