Skip to content

Commit cd3b9fd

Browse files
committed
search_code v2: graph-augmented code search with modes + path_filter
Rewrites search_code from a raw grep wrapper into a 4-phase pipeline: grep scan → graph block expansion → batch degree ranking → context assembly. - Scoped grep: queries indexed file paths from graph, passes to xargs grep — eliminates scanning vendored/generated code (Fixes #102) - Graph dedup: grep matches grouped into containing functions with in_degree, out_degree, qualified_name, label - Three output modes: compact (default, metadata only — token efficient), full (with function source), files (just file paths) - path_filter: regex on file paths (e.g. "^src/") to scope results - context: N lines around each match (like grep -C) in compact mode - directories: summary showing match distribution by top-level directory - Ranking: project source first, vendored demoted, tests penalized - Batch degree query via cbm_store_batch_count_degrees (2 SQL queries instead of 52 individual ones) - Fix yyjson pointer bugs: use strcpy variants for heap/stack strings - Add cbm_store_list_files() for indexed file enumeration - Code discovery gate hook: per-session block (PPID-keyed) nudging Claude toward codebase-memory-mcp tools before grep fallback
1 parent c38853f commit cd3b9fd

File tree

5 files changed

+608
-52
lines changed

5 files changed

+608
-52
lines changed

src/cli/cli.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,11 +1310,7 @@ int cbm_remove_antigravity_mcp(const char *config_path) {
13101310
/* ── Claude Code pre-tool hooks ───────────────────────────────── */
13111311

13121312
#define CMM_HOOK_MATCHER "Grep|Glob|Read|Search"
1313-
#define CMM_HOOK_COMMAND \
1314-
"echo 'Reminder: prefer codebase-memory-mcp search_graph/trace_call_path/" \
1315-
"get_code_snippet over Grep/Glob/Read/Search for code discovery. " \
1316-
"Use get_code_snippet(qualified_name) instead of Read to view a function. " \
1317-
"Fall back only if MCP returns insufficient results.' >&2"
1313+
#define CMM_HOOK_COMMAND "~/.claude/hooks/cbm-code-discovery-gate"
13181314

13191315
/* Old matcher values from previous versions — recognized during upgrade so
13201316
* upsert_hooks_json can remove them before inserting the current matcher. */
@@ -1470,6 +1466,45 @@ int cbm_remove_claude_hooks(const char *settings_path) {
14701466
return remove_hooks_json(settings_path, "PreToolUse", CMM_HOOK_MATCHER);
14711467
}
14721468

1469+
/* Install the code discovery gate script to ~/.claude/hooks/.
1470+
* Blocks the first Grep/Glob/Read/Search call per session (exit 2 + stderr),
1471+
* nudging Claude toward codebase-memory-mcp. All subsequent calls in the same
1472+
* session pass through (gate file keyed on PPID). */
1473+
static void cbm_install_hook_gate_script(const char *home) {
1474+
if (!home) {
1475+
return;
1476+
}
1477+
char hooks_dir[1024];
1478+
snprintf(hooks_dir, sizeof(hooks_dir), "%s/.claude/hooks", home);
1479+
cbm_mkdir_p(hooks_dir, 0755);
1480+
1481+
char script_path[1024];
1482+
snprintf(script_path, sizeof(script_path), "%s/cbm-code-discovery-gate", hooks_dir);
1483+
1484+
FILE *f = fopen(script_path, "w");
1485+
if (!f) {
1486+
return;
1487+
}
1488+
fprintf(f, "#!/bin/bash\n"
1489+
"# Gate hook: nudges Claude toward codebase-memory-mcp for code discovery.\n"
1490+
"# First Grep/Glob/Read/Search per session -> block. Subsequent -> allow.\n"
1491+
"# PPID = Claude Code process PID, unique per session.\n"
1492+
"GATE=/tmp/cbm-code-discovery-gate-$PPID\n"
1493+
"find /tmp -name 'cbm-code-discovery-gate-*' -mtime +1 -delete 2>/dev/null\n"
1494+
"if [ -f \"$GATE\" ]; then\n"
1495+
" exit 0\n"
1496+
"fi\n"
1497+
"touch \"$GATE\"\n"
1498+
"echo 'BLOCKED: For code discovery, use codebase-memory-mcp tools first: "
1499+
"search_graph(name_pattern) to find functions/classes, trace_call_path() for "
1500+
"call chains, get_code_snippet(qualified_name) to read source. If the graph "
1501+
"is not indexed yet, call index_repository first. Fall back to Grep/Glob/Read "
1502+
"only for text content search. If you need Grep, retry.' >&2\n"
1503+
"exit 2\n");
1504+
fclose(f);
1505+
chmod(script_path, 0755);
1506+
}
1507+
14731508
#define GEMINI_HOOK_MATCHER "google_search|read_file|grep_search"
14741509
#define GEMINI_HOOK_COMMAND \
14751510
"echo 'Reminder: prefer codebase-memory-mcp search_graph/trace_call_path/" \
@@ -2218,13 +2253,14 @@ int cbm_cmd_install(int argc, char **argv) {
22182253
}
22192254
printf(" mcp: %s\n", mcp_path2);
22202255

2221-
/* PreToolUse hook */
2256+
/* PreToolUse hook + gate script */
22222257
char settings_path[1024];
22232258
snprintf(settings_path, sizeof(settings_path), "%s/.claude/settings.json", home);
22242259
if (!dry_run) {
22252260
cbm_upsert_claude_hooks(settings_path);
2261+
cbm_install_hook_gate_script(home);
22262262
}
2227-
printf(" hooks: PreToolUse (Grep|Glob reminder)\n");
2263+
printf(" hooks: PreToolUse (code discovery gate)\n");
22282264
}
22292265

22302266
/* Step 5: Install Codex CLI */

0 commit comments

Comments
 (0)