
Company News
AWS Security Hub Adds Socket for Supply Chain Security
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.
wikimoth
Advanced tools
Deterministic, token-minimal, reproducible memory for Claude and agents: wikilink-graph retrieval, then compaction, then a Claude reader.
wikimoth.com · pip install wikimoth
Deterministic, token-minimal, auditable memory for Claude and agents. Point WikiMoth at a
folder of [[wikilink]] notes (an Obsidian vault, or Claude's own memory folder) and it
follows the authored links to the answer flat search can't reach, shows you the exact note-chain
behind it, and feeds the reader ~99% fewer tokens than pasting the whole vault. Pure markdown,
no GPU, no vector DB, no LLM in the retrieval loop.
pip install wikimoth
wikimoth demo # instant multi-hop recall over a bundled demo vault (no setup)
Already have a [[wikilink]] vault (an Obsidian vault, a notes folder)? Point WikiMoth at it and get the full connect-the-dots view in one command, no capture, no waiting:
wikimoth serve --vault /path/to/your/vault # browse + "what memory fed this answer"
wikimoth recall --vault /path/to/your/vault "a connect-the-dots question"
Want it to build memory from your Claude Code sessions? Install the capture hooks; each session you run and close is written into a [[wikilink]] vault:
wikimoth install # capture: turn your Claude Code sessions into a [[wikilink]] vault
wikimoth serve # once you have captured sessions, browse them
We benchmarked exactly that. An agent that browses the notes folder and prunes its own context reaches the same answers, multi-hop included (12/12 in our run). It just pays for it: 4 to 6 model round-trips and roughly 10x the billed tokens per question, because it re-sends a growing transcript every step. WikiMoth retrieves the same note-chain in one deterministic pass, no model in the loop, and shows you the exact notes behind the answer.
Real run, Claude Sonnet 4.6, 12 multi-hop questions on a reproducible vault. The ~10x counts a
reader on both sides; it is corpus-specific, not a universal law. Reproduce it with
python scripts/run_agentic_benchmark.py. Full breakdown in Honest limits.
Most agent memory is either paste the whole notes folder into context (expensive, and the model
gets lost in the middle) or LLM-summarised similarity search (lossy, and non-deterministic:
the same question can return different memory next week). WikiMoth takes a different bet: your notes
are the store (plain markdown), the graph is authored (your [[wikilinks]], no embeddings
to train or drift), and retrieval is code, not a model, so it's reproducible and you can read
exactly why each note was chosen.
| WikiMoth | BM25 | Vector RAG | claude-mem | LLM Wiki (Karpathy) | |
|---|---|---|---|---|---|
Connects the dots (multi-hop over authored [[links]]) | ✅ | ❌ | ❌ | ❌ | ✅ (agentic) |
| Deterministic retrieval (same query → same result) | ✅ | ✅ | ✅ | ❌ | ❌ |
| No LLM call to retrieve | ✅ | ✅ | ✅ | ~ | ❌ |
| Auditable note-chain (which notes produced the answer) | ✅ | ~ | ❌ | ❌ | ~ |
| Direct-lookup recall@8 (real vault) | 1.00 | 1.00 | 1.00 | ~ | ~ |
| No GPU / no vector DB / no index build | ✅ | ✅ | ❌ | ~ | ✅ |
| Plain-markdown store (open in any editor) | ✅ | ~ | ❌ | ❌ | ✅ |
| Token-minimal vs dumping the vault | ✅ −99% | ✅ −99% | ✅ −99% | ✅ | ~ |
| Deterministic, API-free auto-capture | ✅ | ❌ | ❌ | ❌ | ❌ |
| Hygiene without an LLM (conflicts · dupes · stale · supersede) | ✅ | ❌ | ❌ | ~ | ❌ |
LLM Wiki follows links and skips the vector DB like WikiMoth, but an LLM writes and reads the wiki, so retrieval is agentic (an LLM call per recall, not reproducible), while its curated pages are richer. ~ = partial / not independently benchmarked.
The edge is the combination, not higher recall: WikiMoth matches flat search on the basics and adds connect-the-dots + determinism + an audit trail + a plain-markdown store. See Honest limits for exactly where it ties and where it wins.
WikiMoth shares the substrate Andrej Karpathy's LLM Wiki pattern popularised: plain-markdown
[[wikilink]] notes, no vector DB, but flips the engine. In the LLM-Wiki pattern an LLM
writes and reads the wiki: rich, source-cited pages, but recall is agentic (it costs an LLM
call and the path isn't reproducible). WikiMoth computes the edges in code and retrieves with a
fixed algorithm, no LLM in the loop → the same note-chain every time, reproducible and
auditable. They're complementary, not competing: point WikiMoth at a Karpathy-style wiki and you get
deterministic multi-hop retrieval over it. (We don't claim to be "better" than the LLM Wiki: it
curates richer pages; we retrieve deterministically.)
from wikimoth import MemoryRAG, EchoReader
rag = MemoryRAG(reader=EchoReader()) # API-free default reader
rag.index("/path/to/your/wikilink/vault") # notes → ~400-token chunks, graph built
chunks, tokens = rag.retrieve("a connect-the-dots question?", top_k=8)
print(f"{len(chunks)} chunks, {tokens} tokens to feed the reader") # the headline win
# EchoReader is a deterministic stub for wiring/tests: it prints a diagnostic
# `[echo] ...` line, NOT a natural-language answer. Swap in ClaudeReader (below)
# for real prose. The retrieval + token numbers above are the same either way.
print(rag.answer("a connect-the-dots question?"))
Swap in a real Claude answer (only touches the API when constructed):
from wikimoth import MemoryRAG, ClaudeReader
rag = MemoryRAG(reader=ClaudeReader(model="claude-sonnet-4-6")) # needs ANTHROPIC_API_KEY
wikimoth servewikimoth serve # serves http://127.0.0.1:8765 (local-only)
wikimoth serve --vault PATH --port 8080
A zero-dependency local web viewer (pure stdlib, no Flask, no JS framework, no network):
[[wikilink]] graph (the same edges the retriever walks),−N%
vs dumping the whole vault. Retrieval only: no LLM call, no API key, deterministic.Because the store is plain markdown, you can equally open the same vault in Obsidian or VS Code; the viewer is a convenience, not a lock-in.
wikimoth mcpwikimoth serve is for you. The MCP server is for the model: it exposes the same deterministic
retrieval over the Model Context Protocol, so Claude calls it itself instead of you fetching context
by hand.
# 1. install into the Python that runs your Claude Code
python -m pip install wikimoth
# 2. verify the command resolves (prints status, then exits)
python -m wikimoth status
# 3. register the MCP server with Claude Code
claude mcp add wikimoth -- python -m wikimoth mcp
Step 2 is the check that matters: if python -m wikimoth status prints a status line, then
python -m wikimoth mcp will run for Claude too. Use the same python in all three steps (it is
python3 on some systems); that is the one thing that has to match.
Prefer the Node world, or no Python set up? One line, no toolchain matching:
claude mcp add wikimoth -- npx -y wikimoth-mcp
The wikimoth-mcp launcher finds a Python that has
WikiMoth (or uvx-installs one on the fly), injects the vault path so the server never reads an
empty folder from the client's working directory, and passes the MCP channel through untouched. The
same npx -y wikimoth-mcp works as the server command in any mcpServers config (Claude Desktop,
Cursor, Windsurf); set WIKIMOTH_VAULT to your vault.
Now Claude has a recall(query) tool. Ask it something that lives in your notes and it calls
recall; WikiMoth walks the [[links]] and hands back the exact note-chain (no LLM call to
retrieve, token-minimal, the same result every time), and Claude answers from it. A status tool
reports the connected vault. For any other MCP client, use python -m wikimoth mcp as the server
command (stdio transport); point it at a specific vault with --vault PATH.
python -m wikimoth mcp is the portable form (it runs wherever the package is installed). The bare
wikimoth mcp works too when the console script is on your PATH. It is pure stdlib: a hand-rolled
JSON-RPC 2.0 stdio server, no MCP SDK dependency.
mcp-name: io.github.juliangeymonat-jpg/wikimoth
Retrieval needs a [[wikilink]] vault; hand-authoring one is the friction. wikimoth.capture builds
it automatically by installing Claude Code lifecycle hooks that turn each session into one
deterministic markdown note.
The invariant that matters: a note's [[wikilinks]] (the graph edges) are computed by code
(string/path matching), never by a model. An LLM may optionally draft the summary prose
(WIKIMOTH_LLM_PROSE=1), but any [[...]] it emits is stripped, never parsed as an edge. So the
graph is reproducible (same session + vault → same edges) and auditable. Default capture is fully
deterministic and makes zero API calls.
wikimoth install # writes 5 hooks into ./.claude/settings.json (absolute interpreter path)
wikimoth install --user # ~/.claude/settings.json instead
wikimoth install --vault PATH # choose where notes go (sets WIKIMOTH_VAULT)
wikimoth status # vault, note/session/buffer counts, hook state
wikimoth uninstall # remove the hooks again
Lifecycle: SessionStart recalls recent sessions into context · UserPromptSubmit / PostToolUse buffer the session · Stop / SessionEnd write one note. The captured notes are exactly what the read pipeline indexes; capture and retrieval close the loop.
A memory that only grows rots. Notes go stale, two notes start disagreeing, the same fact gets saved twice, an old fact is replaced but never retired. Other agent-memory tools resolve this with an LLM that silently overwrites the old state. WikiMoth ships six commands that surface it deterministically, and never delete anything: git is your audit trail.
| command | finds | writes? |
|---|---|---|
wikimoth conflicts | two notes asserting a different value for the same fact (type-aware, valid-time precision) | no |
wikimoth lint | broken links, orphans, stubs, stale notes, supersession cycles | no |
wikimoth dedup | exact + near-duplicate notes (MinHash + LSH, confirmed by exact Jaccard) | no |
wikimoth decay | notes going cold: old, rarely linked, rarely recalled (a review queue, never auto-delete) | no |
wikimoth recall --as-of <date> | what your memory asserted on a past date (bitemporal time-travel, no DB) | no |
wikimoth supersede OLD NEW | retire a fact: invalidate, don't delete | yes |
Three principles hold across all of them:
supersede marks a note superseded and links it to its replacement
in frontmatter. The old body drops out of retrieval, but its [[link]] to the current note stays
live, so a query that lands on the stale note hops free to the new one. Nothing is ever rm'd;
the history lives in git.recall --as-of 2026-01-01 replays what the vault asserted on that
date from frontmatter validity windows alone. No event log, no vector store, no migration.Same invariants as the rest of WikiMoth: pure stdlib, deterministic (byte-identical output),
read-only except the single supersede writer, plain markdown you can diff. The seven commands are
also exposed over MCP (list_conflicts, list_lint, list_duplicates, list_fading, supersede,
plus recall gaining as_of / show_superseded), so the agent can keep its own memory clean.
WikiMoth's core is pure stdlib (dependencies = []): the retrieval engine, chunker, wikilink
graph, pipeline and capture are all vendored under wikimoth/: nothing extra to install, no GPU, no
vector DB.
pip install wikimoth
# optional extras:
pip install "wikimoth[hybrid]" # optional BM25-seeded retriever variant
pip install "wikimoth[claude,tokens]" # real Claude reader + exact tiktoken counts
Extras: hybrid = BM25-seeded retriever (rank_bm25) · claude = the anthropic reader ·
tokens = exact token counts (tiktoken) · dense = the dense benchmark baseline · headroom =
reversible CCR compaction.
retrieve → compact → read. index() splits each note into ~400-token chunks (~50 overlap),
keeping per-chunk note identity so the [[wikilink]] graph still connects across chunks (multi-hop
at chunk granularity). GraphRetriever(source="wikilinks") seeds lexically, then walks the authored
links, so a passage not lexically similar to the question but reachable by a link still gets
pulled. An optional compaction stage (reversible CCR via
chopratejas/headroom) shrinks passages further before
the (paid) reader; it degrades to a no-op if headroom isn't installed.
A pure-navigation hub (a table-of-contents like MEMORY.md) can be indexed as graph edges only
(exclude_content, default ("MEMORY.md",)): its [[links]] build edges and it stays a BFS
waypoint, but its own chunks never reach the reader.
Every stage is constructor-injectable via MemoryRAG(retriever=…, compactor=…, reader=…), so you can
swap the retriever (e.g. the BM25-seeded HybridRetriever), the compactor, or the reader.
wikimoth.benchmark.harness measures tokens fed to the reader (what you actually pay for) across
arms over the same vault and questions:
| arm | feeds the reader | status |
|---|---|---|
dump | the whole vault | baseline |
deterministic | wikilink-graph retrieval | implemented |
deterministic_compacted | retrieval + Headroom | implemented |
agentic | an LLM browses and prunes its own context | implemented (Claude tool-use) |
No paid API calls run by default; every arm's reader defaults to the API-free EchoReader.
WikiMoth's value is deterministic, auditable, token-minimal, plain-markdown memory with a real multi-hop capability, not "better retrieval than BM25". Specifically:
agentic arm, real run against Claude
Sonnet 4.6, 12 multi-hop questions): the agent reaches the same answers, multi-hop included
(12/12). The difference is cost. It takes 4 to 6 paid round-trips and about 10x the billed tokens
per question, because it re-sends a growing transcript each step, where WikiMoth answers from one
deterministic pass with no model call in the retrieval loop and an auditable note-chain. The
multiple is corpus-specific, not a law. Reproduce it: python scripts/run_agentic_benchmark.py.MemoryRAG(retriever=…, compactor=…, reader=…); defaults GraphRetriever(source="wikilinks") /
NoOpCompactor / EchoReader. Anything satisfying the small Protocols drops in.
Apache-2.0; see LICENSE. © 2026 Julian Geymonat.
FAQs
Deterministic, token-minimal, reproducible memory for Claude and agents: wikilink-graph retrieval, then compaction, then a Claude reader.
The pypi package wikimoth receives a total of 55 weekly downloads. As such, wikimoth popularity was classified as not popular.
We found that wikimoth demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.

Research
/Security News
Popular npm packages keyv and cacheable compromised.

Security News
A misconfiguration gave three Anthropic models internet access, and one, believing it was in a simulation, shipped a credential-stealing package to PyPI.