Repository navigation
hook-augment restarts full daemon on every invocation, causing ~3s latency per call and hook timeouts #2058
Description
Summary
The cbm-code-discovery-gate hook (installed by codebase-memory-mcp install into
Claude Code's PreToolUse:Grep hook) calls codebase-memory-mcp.exe hook-augment on
every single Grep tool call. In practice this takes ~3 seconds per invocation, and
occasionally exceeds the client's hook execution timeout entirely, blocking the tool
call it's supposed to only augment.
Environment
- codebase-memory-mcp v0.10.8 (confirmed latest via GitHub releases at time of filing)
- Windows 11, Claude Code CLI
- Project graph DB: ~21MB (
C-Users-...-TC_PayrollChecker.db)
Observed behavior
Direct timing of codebase-memory-mcp.exe hook-augment run 3x consecutively from the
project directory: 2.98s / 3.32s / 2.98s — consistent, not a cold-start fluke.
~/.cache/codebase-memory-mcp/logs/cbm-daemon.log shows the daemon fully tearing down
and cold-restarting on each invocation:
level=info msg=daemon.runtime_stopping reason=last_committed_client_disconnected
level=info msg=watcher.unwatch project=...
level=info msg=daemon.lifetime_end reason=runtime_exited
level=info msg=watcher.stop
level=info msg=daemon.stop
level=warn msg=mem.allocator.preloading_completed ...
level=info msg=mem.init budget_mb=3572 total_ram_mb=14290 source=ram_fraction
level=info msg=watcher.start interval_ms=multi-sec
level=info msg=ui.serving url=http://127.0.0.1:9749 port=9749
level=info msg=daemon.start version=0.10.8 pid=...
Each hook call appears to pay full daemon cold-start cost: memory allocator init,
binding the HTTP UI server on :9749, and establishing a git-based file-watcher
baseline — before it can answer. Real-world impact observed in Claude Code transcripts:
3 recorded PreToolUse:Grep hook runs in a 15-day window all hit the hook timeout
(6.1s, 7.3s, 7.7s), blocking those Grep calls entirely.
Also noticed in the same log: an indexing worker failure
(index.supervisor.worker_failed outcome=exit_nonzero exit_code=1) and a stray
24MB .stage.a05564 staging file left in the cache dir, possibly from an
interrupted reindex — may or may not be related.
Expected behavior
hook-augment should reuse a warm/persistent daemon (or otherwise avoid full
daemon boot — allocator init, UI server, watcher baseline) for what's meant to be
a lightweight per-tool-call augmentation hook, so it doesn't add multi-second
latency to every Grep call in the host CLI.
Workaround
Disabled the exe call in ~/.claude/hooks/cbm-code-discovery-gate.cmd (early
exit /b 0) since no config flag (codebase-memory-mcp config list) exposes
daemon-reuse or a lighter-weight hook path. The MCP server tools themselves
(search_graph, trace_path, etc.) are unaffected and still used heavily.
Activity
Langsuyar64 commentedon Sep 4, 2026
Follow-up: confirmed this is not specific to a large project. Timed
hook-augmentdirectly in two other tracked projects with much smaller graph DBs, same machine:The tax is flat regardless of graph size (~3s in all three), which points to daemon boot overhead (allocator init, UI server bind, watcher baseline) as the dominant cost rather than index/query size — i.e. this will affect any project, not just large ones.
Langsuyar64 commentedon Sep 4, 2026
Workaround in place on my end for now: disabled the
hook-augmentcall in~/.claude/hooks/cbm-code-discovery-gate.cmd(earlyexit /b 0before it reaches the exe), since no config flag exposes daemon reuse or a lighter-weight hook path.Confirmed across all 3 tracked projects that the hook script itself now returns in ~110-170ms instead of ~2.8-3.3s:
This is just a local workaround (skips the augmentation hook entirely) — leaving this open since the underlying daemon-restart-per-call behavior in
hook-augmentitself is still present in v0.10.8. The MCP server tools (search_graph, trace_path, etc.) are unaffected and still in regular use.AmirF194 commentedon Sep 5, 2026
Reproduced independently on Linux (built from HEAD 5c8ce58, in Docker): hook-augment costs about 2.0s on every invocation regardless of daemon state. With a permanent daemon already warm (
daemon start), three back-to-back calls still logged ~2.0s each, andcbm-daemon.loggained zero new lines during an isolated run, so it isn't restarting the daemon process itself. Even a trivial{}stdin payload (no event, no work to do) pays the same ~2.0s before any project logic runs.That lines up with your own finding that the cost is flat across project sizes instead of scaling with graph data, which points away from daemon boot as the mechanism.
The fixed cost traces to
cbm_daemon_build_fingerprint_native_fileinsrc/daemon/service.c, which SHA-256s the whole executable on every process start to build the version-cohort identity used for daemon rendezvous. On a build this size that's the 2-3s everyone here is timing. #1335 measured this in detail back in July, and PR #1767 (open, in review) already caches that fingerprint keyed by device/inode/size/mtime/ctime to fix it.Might be worth closing this as a duplicate of #1335 once #1767 lands.
fix(hook-augment): cache the image fingerprint per process and announ…
DeusData commentedon Sep 19, 2026
Thank you for distinguishing the daemon-lifetime behavior from invocation latency. Current executable fingerprint caching lasts only for one process, so keeping the daemon warm does not remove the first hash from a new CLI process. That does not establish the cause of the reported daemon-lifetime behavior; those observations should remain separate rather than being closed as one fingerprinting issue.
AmirF194 commentedon Sep 20, 2026
Agreed, that's a fair split. Our repro only measured the flat per-call cost (fingerprint hash, independent of daemon state); we never tested a separate daemon-lifetime symptom, so closing this as a pure #1767 duplicate would have been premature on our part.
perf(daemon): hash the executable image once per process; announce mi…