Skip to content

hook_augment PreToolUse augmenter is a structural no-op on Windows (POSIX-only path guards) #618

Description

@catsmonster

Summary

codebase-memory-mcp hook-augment (the non-blocking Claude Code PreToolUse Grep/Glob augmenter) is a structural no-op on Windows. It runs, inits, and exits 0 with no additionalContext for every input, because the path guards in src/cli/hook_augment.c require POSIX-style /-prefixed absolute paths, which a Windows drive-letter cwd (C:\... / C:/...) can never satisfy.

Net effect: on Windows the Grep/Glob graph augmentation never fires, even for an exactly-indexed symbol. (The "never block a tool" guarantee is intact — it just never contributes anything.)

  • Version: codebase-memory-mcp 0.8.1
  • Platform: Windows (x64)
  • Install channel: install.ps1
  • Binary variant: standard

What happened, and what did you expect?

Expected: running a Grep on an indexed symbol fires the PreToolUse hook and injects matching graph symbols as additionalContext.

Actual: hook-augment emits 0 bytes of stdout for any Grep/Glob payload on Windows; no context is ever added.

Reproduction

Platform-level, no proprietary code needed — reproduces with any indexed project on Windows.

  1. On Windows, index any repo (e.g. a clone of a public repo) so it appears in list_projects with a root_path like C:/Users/me/proj.

  2. Invoke the augmenter exactly as the installed PreToolUse hook does, with a realistic Claude Code payload:

    echo '{"hook_event_name":"PreToolUse","tool_name":"Grep","cwd":"C:/Users/me/proj","tool_input":{"pattern":"someIndexedSymbol"}}' \
      | codebase-memory-mcp hook-augment
    
  3. Result: empty stdout (no hookSpecificOutput). Expected: a {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"[codebase-memory] N graph symbol(s) match ..."}} payload.

search_graph for the same project/token returns correct hits, confirming the index and project name are fine — only hook-augment's path handling fails.

Root cause

src/cli/hook_augment.c — two POSIX-only guards:

  1. cbm_cmd_hook_augment, the _WIN32 branch (~L330):

    if (!cwd || cwd[0] != '/') {   // Windows cwd starts with a drive letter → always true → bail
        ...
        return 0;
    }

    A Windows absolute path (C:\... or C:/...) never has cwd[0] == '/', so this returns early on every invocation. This alone makes the hook a guaranteed no-op on Windows.

  2. ha_resolve_and_query walk-up loop (~L254):

    for (int level = 0; level < HA_MAX_WALKUP && dir[0] == '/'; level++) {

    The loop only iterates while the path starts with /, and the parent-climb terminator (slash == dir, ~L277) assumes a /-root. So even if guard Windows support: CGO/tree-sitter build fails — WSL2 workaround included #1 were relaxed, a C:/... path would never enter the loop / would mis-terminate.

cbm_project_name_from_path (src/pipeline/fqn.c) already handles Windows paths correctly (it produced the indexed project name from the C:\... root), so the project-name derivation is not the problem — only these /-prefix assumptions are.

The _WIN32 branch comment already acknowledges the walk-up loop "requires POSIX-style absolute paths" and chooses to bail — i.e. this is effectively unfinished Windows support for the augmenter rather than a subtle regression.

Proposed fix

Teach both guards about Windows drive roots and normalize \/:

/* absolute = POSIX "/..." OR Windows drive "X:/..." */
static bool ha_is_abs(const char *d) {
    if (!d || !d[0]) return false;
    if (d[0] == '/') return true;
    return isalpha((unsigned char)d[0]) && d[1] == ':' && (d[2] == '/' || d[2] == '\0');
}
  • Guard 1: normalize cwd backslashes to /, then if (!ha_is_abs(cwd)) return 0;
  • Guard 2: loop while ha_is_abs(dir); stop the parent-climb at the drive root (X:) as well as the POSIX root.

Happy to open a PR with this (I'll mark it build-unverified for Windows CI to confirm, since I don't have the full C toolchain locally).

Related

Fits under the Windows umbrella tracker #394 (not currently listed there). Distinct from #513 (stdio hang), #548 (UI drive selection), and #409 (install wiring the legacy gate).

Confirmations

  • I searched existing issues and this is not a duplicate.
  • My reproduction uses shareable steps (platform-level, any public repo), not proprietary code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingeditor/integrationEditor compatibility and CLI integrationpriority/normalStandard review queue; useful PR with ordinary maintainer urgency.windowsWindows-specific issues

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions