Skip to content

guidanceOnce() throttle does not work on Windows — guidance injected on every tool call instead of once per session #298

@HossyKoki

Description

@HossyKoki

Description

Problem

The guidanceOnce() function in hooks/core/routing.mjs uses process.ppid to create session-scoped marker directories in /tmp/. On Windows with Git Bash, each hook invocation spawns a new bash.exe process, causing process.ppid to differ on every call. This means:

  1. The file-based throttle marker lands in a new directory each time
  2. The in-memory Set is always empty (new Node.js process per invocation)
  3. Result: Read/Bash/Grep guidance tips are injected on EVERY tool call, not once per session

Evidence

  • 716 stale marker directories accumulated in /tmp/context-mode-guidance-* over ~3 days
  • Within a single 2-minute window, 5 different PIDs were observed (25712, 20372, 8512, 8648, 17724)
  • node -e "process.ppid" run from Bash returns a different PID than what the hook's Node.js process sees

Impact

  • Every Read call gets a "use ctx_execute_file instead" system reminder (~200 chars)
  • Every Bash call gets a "use ctx_batch_execute instead" system reminder (~200 chars)
  • Every Grep call gets a "use ctx_execute instead" system reminder (~200 chars)
  • In a 50+ tool call session, this adds 10KB+ of repetitive context noise
  • User-reported symptom: Claude stops mid-task after reading files — the conflicting "use a different tool" advice disrupts multi-step planning

Environment

  • Windows 11 Pro (10.0.26100)
  • Shell: Git Bash (bash.exe)
  • Claude Code CLI
  • Node.js (invoked via node hooks/pretooluse.mjs as a hook command)

Root Cause

In routing.mjs line 31:

const _guidanceId = process.env.VITEST_WORKER_ID
  ? `${process.ppid}-w${process.env.VITEST_WORKER_ID}`
  : String(process.ppid);

On macOS/Linux, the parent process (shell) may persist across hook invocations, keeping process.ppid stable. On Windows/Git Bash, a new bash.exe is spawned for each hook command, making process.ppid unique per invocation.

Suggested Fix

Use a more stable session identifier. Options:

  1. Environment variable: Claude Code could set a CLAUDE_SESSION_ID env var that persists across hook invocations
  2. Grandparent PID: Use process.ppid of the bash parent (the Claude Code process), though this requires an extra syscall
  3. Startup timestamp: Use a marker from SessionStart (e.g., write a session ID file in /tmp/ during sessionstart.mjs and read it in pretooluse.mjs)
  4. Single file with atomic check: Instead of per-ppid directories, use a single file per guidance type with a session timestamp

Option 3 seems most pragmatic — sessionstart.mjs already runs once per session and could write a stable session ID.

Workaround

Remove Read and Grep from the PreToolUse matcher in settings.json (they aren't in context-mode's default hooks.json PreToolUse entries anyway). This eliminates the most disruptive guidance while keeping Bash routing (curl/wget blocking) functional.


Update (2026-04-17)

  • Bug confirmed still present in context-mode v1.0.75 (latest at time of writing) at hooks/core/routing.mjs:31:
    const _guidanceId = process.env.VITEST_WORKER_ID
      ? `${process.ppid}-w${process.env.VITEST_WORKER_ID}`
      : String(process.ppid);
  • Claude Code 2.1.104 also affected (verified on Windows 11 Pro 10.0.26100, Git Bash).
  • Workaround in continuous use for 8 daysRead/Grep removed from PreToolUse matcher, no regressions observed. Bash routing (curl/wget scheme blocking, etc.) remains functional.
  • Supplementary mitigation: a SessionStart hook (session-cleanup.sh) was added locally to purge stale /tmp/context-mode-guidance-* directories, preventing the accumulation symptom. This treats the symptom, not the root cause — the upstream fix is still needed for correct throttle behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions