v0.8.12026-08-27
A gate in front of grep, and a skill you can actually change. Nothing stored
changed shape and no pass has to run again: both additions read the graph that
is already published.
kivgraph hook installregisters a gate that runs before the agent’s own tools and refuses a search when the graph answers it better. It closes on one fact — two or more things declare the name, so a text search cannot separate what it finds — and that is the only threshold the measurements support. Over the six questions ofbenchmarks/mcp-token-costthe factor splits by how many things share a name and not at all by how many references a symbol has: the three we lose (DiscoverGo0,83x,MergeAll0,85x,CanonicalColumns0,91x) are all unambiguous names, and the two we win biggest (Publish6,42x,BuildPlan1,92x) are the shared ones. A reference-count floor was written first and removed: the corpus has nothing above four references, so any number would have been invented.- The refusal names the call to make instead, and quotes the rows it is
talking about, because a refusal without a next step is an obstacle rather
than a redirect.
KIVGRAPH_DISABLE_HOOK=1runs one anyway. - Four clients host it: Claude Code, Claude Desktop, Codex and OpenCode. The
first three read the same verdict off stdout, so one command serves them and
only the file it is registered in differs. OpenCode gets a generated plugin,
because its
tool.execute.beforereturnsPromise<void>and the only way to stop a tool there is to throw. Oh My Pi is the one that cannot: its own documentation calls its hook subsystem legacy. - It costs
2 mson the path that allows and5,6 mswhen it asks the daemon, measured on this repository’s graph. Classification is pure and runs before the configuration is read, so nearly every call leaves by the first path. Every failure — unreadable payload, no configuration, a directory no registered repository holds, no daemon — writes nothing and exits0. An explicit allow on that wire does not mean “carry on”, it means “skip the permission prompt”, so the gate never sends one. kivgraph skill installnow writes one file and links the clients to it. Three installed clients used to mean three copies and no source, which left the obvious question unanswered: what you do to change it. Editing one copy did not reach the others and the next install took it away. The canonical file is~/.config/kivgraph/skills/kivgraph/SKILL.md, besideconfig.yaml, and one edit reaches every client.- An upgrade keeps that edit. Reinstalling is what an upgrade does, so
installwrites the canonical only when it is absent or still holds the shipped skill;skill statussays when it carries local edits, and--forcetakes the shipped version back. A copy from an earlier install becomes a link without asking, because the bytes are the ones we would have written. Project scope still copies: that path is committed, and a link to an absolute path under one machine’s home would arrive broken on every other clone. - The desktop app is detected by the entry it actually ships. The Linux
marker this repository looked for,
claude.desktop, does not exist — the package installscom.anthropic.Claude.desktop— somcp installandskill installwere not detecting Claude Desktop either.