Stop telling assistants to read GRAPH_REPORT.md first (#580)#891
Conversation
) The current install writes "ALWAYS read graphify-out/GRAPH_REPORT.md before reading any source files, running grep/glob searches, or answering codebase questions" into CLAUDE.md and equivalents, plus a PreToolUse hook with the same instruction. On real corpora that report is 47-91K characters, so Claude Code sessions pay roughly 12-25K tokens of context up front for every search-able question. Three users on Graphify-Labs#580 reported this making token usage worse than no install at all. Reproduced on a 1500-file Go monorepo: a "where is X defined" question takes 5 tool calls and 34k agent tokens with stock graphify, 4 calls and 30k tokens with no install, and 1 call and 30k tokens after this patch. Stock graphify's Read of GRAPH_REPORT.md hit Claude Code's 25k token cap and failed entirely, then recovered via a partial read plus graphify explain. Demote GRAPH_REPORT.md to a fallback for broad architecture review and route first action to the existing scoped commands: graphify query, path, explain. The 2k-budget BFS subgraph already exists in serve.py; the install just wasn't pointing at it. Updated across all ten install surfaces: _SETTINGS_HOOK, _CLAUDE_MD_SECTION, _AGENTS_MD_SECTION, _GEMINI_MD_SECTION, _GEMINI_HOOK, _VSCODE_INSTRUCTIONS_SECTION, _ANTIGRAVITY_RULES, _KIRO_STEERING, _CURSOR_RULE, _OPENCODE_PLUGIN_JS. Plus the matching sentence in README.md, which also fixes an inaccuracy about Codex hooks (Codex's installed hook is intentionally a no-op because Codex rejects additionalContext, so the guidance there comes from AGENTS.md, not the hook). Five installers (claude, agents, vscode, gemini, kiro, cursor) were also writing their section only when no marker was present, so users who installed pre-fix kept the old "ALWAYS read" text after upgrading. Added _replace_or_append_section helper that updates in place when the graphify marker is found. claude_install also no longer returns before re-running _install_claude_hook, so stale settings.json hook payloads get refreshed on upgrade. Tests: - tests/test_install_strings.py (3): every install constant still mentions `graphify query` and matches no banned report-first regex. - tests/test_install_upgrade.py (7): seeds each platform's instruction file with pre-fix text, runs install, asserts the on-disk file reflects the new policy. - test_claude_md.py idempotency tests still pass. Fixes Graphify-Labs#580.
|
I’ve encountered the same issue where token usage suddenly jumps, and I don’t think it’s happening because of Graph_report.md—I don’t see it being read. The problem I see is that the query CLI returns a default limit of 2000 tokens, and many times it does not include all the relevant nodes in the response. The response gets cut due to the 2000-token budget, and many of the returned nodes are not meaningful. Because of this, Claude Code ends up doing additional reasoning, making multiple query and explain calls, which further fills the context (another ~2K tokens per query command). I think the seed scoring mechanism needs significant improvement so that the query command returns more meaningful and relevant nodes. And when I run the same query with disabled Graphify, it returns faster and less token count. Another thing: why do we need the /graphify skill for query and explain? Internally, it is just running CLI commands anyway, and CLAUDE.md already instructs Claude to use Graphify query, explain, and path commands. Claude can directly invoke the Graphify CLI using the bash tool. |
Fixes #580.
Three users on that issue reported Claude Code using more tokens with graphify installed than without. The cause is the install-time instruction set, which writes
ALWAYS read graphify-out/GRAPH_REPORT.md before reading any source files, running grep/glob searches, or answering codebase questionsinto the project'sCLAUDE.md(and the equivalent intoAGENTS.md,GEMINI.md,.cursor/rules/, etc.), plus aPreToolUsehook with the same instruction. On real corpora the report is 47-91K characters, so sessions pay roughly 12-25K tokens of context up front for every search-able question.Reproduced on a 1500-file Go monorepo using a "where is the Studio type defined" question:
grep -rn "type Studio"graphify query "..."Stock graphify is measurably worse than no graphify at all on this corpus, which is the user's complaint. With the patch it matches the no-install token count, drops to one tool call, and surfaces 6 related entities for free from the same BFS subgraph.
What changed
Demote
GRAPH_REPORT.mdto a fallback for broad architecture review. Route first action to the scoped commands that already exist:graphify query,graphify path,graphify explain. The 2k-budget BFS subgraph is already inserve.py; the install just wasn't pointing at it.Applied across all ten install surfaces for consistency:
_SETTINGS_HOOK(Claude CodePreToolUse)_CLAUDE_MD_SECTION_AGENTS_MD_SECTION(Codex / OpenCode / OpenClaw / Aider / Trae)_GEMINI_MD_SECTION_GEMINI_HOOK_VSCODE_INSTRUCTIONS_SECTION(Copilot)_ANTIGRAVITY_RULES_KIRO_STEERING_CURSOR_RULE_OPENCODE_PLUGIN_JSPlus the matching sentence in
README.md. The README also had an inaccuracy: it claimed hooks on Claude Code, Codex, and Gemini CLI all fire before tool calls, but the Codex hook is intentionally a no-op (hook-checkdoes nothing because Codex rejectsadditionalContext). Reworded to distinguish payload-bearing hooks from instruction-file-only platforms.Upgrade-in-place fix
Five installers (
claude,agents,vscode,gemini,kiro,cursor) were writing their section only when no marker was present, so users who installed graphify pre-fix and rangraphify <platform> installagain after upgrading kept the old "ALWAYS read" text on disk. The bug would have stayed live for them.Added
_replace_or_append_sectionhelper that updates in place when the graphify marker is found, treating the section as everything from the marker line to the next H2 heading (or EOF). For wholly-graphify-owned files (.kiro/steering/graphify.md,.cursor/rules/graphify.mdc) the installer now overwrites when content differs.claude_installalso no longer returns before_install_claude_hook, so a stale.claude/settings.jsonhook payload gets refreshed on upgrade rather than left in place.Tests
tests/test_install_strings.py(3 tests): every install constant still mentionsgraphify query; regex check for banned report-first phrasing (read .*GRAPH_REPORT.md.*before,first tool call.*GRAPH_REPORT,always read.*GRAPH_REPORT);GRAPH_REPORT.mdis still referenced in MD sections as the demoted fallback.tests/test_install_upgrade.py(7 tests): seeds each platform's instruction file (CLAUDE.md,AGENTS.md,GEMINI.md,.github/copilot-instructions.md,.cursor/rules/graphify.mdc,.kiro/steering/graphify.md, plus the stale Claude hook payload in.claude/settings.json) with pre-fix text, runsinstall, asserts the on-disk file now containsgraphify queryand no longer contains the old report-first phrasing.test_claude_md.pyidempotency tests still pass (the existing "already configured" wording is preserved).Full suite: 819 pass, 11 pre-existing failures unchanged, zero regressions.
Note on
ALWAYSThe regex check intentionally does not ban the bare word
ALWAYS.alwaysApply: true(Cursor) andtrigger: always_on(Antigravity) are legitimate platform metadata. The banned patterns target report-first semantics, not the keyword.Scope
10 install constants changed, 1 README sentence, 1 new helper, 6 installer updates, 2 new test files. No architecture changes, no marketing-claim touches, no new artifacts. Happy to split the upgrade-in-place changes out as a follow-up PR if preferred, but they share a load-bearing dependency on the helper.