f38b5b85bc
* docs: add investigation reports for 5 open GitHub issues Comprehensive analysis of issues #543, #544, #545, #555, and #557: - #557: settings.json not generated, module loader error (node/bun mismatch) - #555: Windows hooks not executing, hasIpc always false - #545: formatTool crashes on non-JSON tool_input strings - #544: mem-search skill hint shown incorrectly to Claude Code users - #543: /claude-mem slash command unavailable despite installation Each report includes root cause analysis, affected files, and proposed fixes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(logger): handle non-JSON tool_input in formatTool (#545) Wrap JSON.parse in try-catch to handle raw string inputs (e.g., Bash commands) that aren't valid JSON. Falls back to using the string as-is. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(context): update mem-search hint to reference MCP tools (#544) Update hint messages to reference MCP tools (search, get_observations) instead of the deprecated "mem-search skill" terminology. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(settings): auto-create settings.json on first load (#557, #543) When settings.json doesn't exist, create it with defaults instead of returning in-memory defaults. Creates parent directory if needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(hooks): use bun runtime for hooks except smart-install (#557) Change hook commands from node to bun since hooks use bun:sqlite. Keep smart-install.js on node since it bootstraps bun installation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: rebuild plugin scripts * docs: clarify that build artifacts must be committed * fix(docs): update build artifacts directory reference in CLAUDE.md * test: add test coverage for PR #558 fixes - Fix 2 failing tests: update "mem-search skill" → "MCP tools" expectations - Add 56 tests for formatTool() JSON.parse crash fix (Issue #545) - Add 27 tests for settings.json auto-creation (Issue #543) Test coverage includes: - formatTool: JSON parsing, raw strings, objects, null/undefined, all tool types - Settings: file creation, directory creation, schema migration, edge cases 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(tests): clean up flaky tests and fix circular dependency Phase 1 of test quality improvements: - Delete 6 harmful/worthless test files that used problematic mock.module() patterns or tested implementation details rather than behavior: - context-builder.test.ts (tested internal implementation) - export-types.test.ts (fragile mock patterns) - smart-install.test.ts (shell script testing antipattern) - session_id_refactor.test.ts (outdated, tested refactoring itself) - validate_sql_update.test.ts (one-time migration validation) - observation-broadcaster.test.ts (excessive mocking) - Fix circular dependency between logger.ts and SettingsDefaultsManager.ts by using late binding pattern - logger now lazily loads settings - Refactor mock.module() to spyOn() in several test files for more maintainable and less brittle tests: - observation-compiler.test.ts - gemini_agent.test.ts - error-handler.test.ts - server.test.ts - response-processor.test.ts All 649 tests pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(tests): phase 2 - reduce mock-heavy tests and improve focus - Remove mock-heavy query tests from observation-compiler.test.ts, keep real buildTimeline tests - Convert session_id_usage_validation.test.ts from 477 to 178 lines of focused smoke tests - Remove tests for language built-ins from worker-spawn.test.ts (JSON.parse, array indexing) - Rename logger-coverage.test.ts to logger-usage-standards.test.ts for clarity 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(tests): phase 3 - add JSDoc mock justification to test files Document mock usage rationale in 5 test files to improve maintainability: - error-handler.test.ts: Express req/res mocks, logger spies (~11%) - fallback-error-handler.test.ts: Zero mocks, pure function tests - session-cleanup-helper.test.ts: Session fixtures, worker mocks (~19%) - hook-constants.test.ts: process.platform mock for Windows tests (~12%) - session_store.test.ts: Zero mocks, real SQLite :memory: database Part of ongoing effort to document mock justifications per TESTING.md guidelines. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(integration): phase 5 - add 72 tests for critical coverage gaps Add comprehensive test coverage for previously untested areas: - tests/integration/hook-execution-e2e.test.ts (10 tests) Tests lifecycle hooks execution flow and context propagation - tests/integration/worker-api-endpoints.test.ts (19 tests) Tests all worker service HTTP endpoints without heavy mocking - tests/integration/chroma-vector-sync.test.ts (16 tests) Tests vector embedding synchronization with ChromaDB - tests/utils/tag-stripping.test.ts (27 tests) Tests privacy tag stripping utilities for both <private> and <meta-observation> tags All tests use real implementations where feasible, following the project's testing philosophy of preferring integration-style tests over unit tests with extensive mocking. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * context update * docs: add comment linking DEFAULT_DATA_DIR locations Added NOTE comment in logger.ts pointing to the canonical DEFAULT_DATA_DIR in SettingsDefaultsManager.ts. This addresses PR reviewer feedback about the fragility of having the default defined in two places to avoid circular dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
280 lines
8.8 KiB
Markdown
280 lines
8.8 KiB
Markdown
# Issue #555 Analysis: Windows Hooks Not Executing - hasIpc Always False
|
|
|
|
**Date:** 2026-01-05
|
|
**Version Analyzed:** 8.5.9
|
|
**Claude Code Version:** 2.0.76
|
|
**Platform:** Windows 11 (Build 26100), Git Bash (MINGW64)
|
|
**Status:** INVESTIGATION COMPLETE - Root cause identified
|
|
|
|
## Issue Summary
|
|
|
|
On Windows 11 with Git Bash, Claude-mem plugin hooks are not executing at all. While the worker service starts successfully and responds to health checks, no observations are being saved and no hook-related logs appear.
|
|
|
|
### Reported Symptoms
|
|
|
|
```json
|
|
// /api/health
|
|
{
|
|
"status": "ok",
|
|
"build": "TEST-008-wrapper-ipc",
|
|
"managed": false,
|
|
"hasIpc": false,
|
|
"platform": "win32",
|
|
"pid": 3596,
|
|
"initialized": true,
|
|
"mcpReady": true
|
|
}
|
|
|
|
// /api/stats
|
|
{
|
|
"observations": 0,
|
|
"sessions": 1
|
|
}
|
|
```
|
|
|
|
### Key Observations
|
|
|
|
1. Worker starts and responds correctly to HTTP requests
|
|
2. `hasIpc` is `false` (this is **expected behavior**, not a bug)
|
|
3. `observations` remains at `0` - no data being captured
|
|
4. No `[HOOK]` entries in worker logs - hooks never execute
|
|
5. This differs from issue #517 which was about PowerShell escaping
|
|
|
|
## Root Cause Analysis
|
|
|
|
### Primary Cause: Hook Commands Not Executing
|
|
|
|
The hooks defined in `plugin/hooks/hooks.json` are never being invoked by Claude Code on Windows.
|
|
|
|
### Understanding hasIpc
|
|
|
|
The `hasIpc` field is a **red herring** and is working as intended:
|
|
|
|
```typescript
|
|
// src/services/server/Server.ts:152
|
|
hasIpc: typeof process.send === 'function'
|
|
```
|
|
|
|
This checks if the worker process was spawned with an IPC channel (via `fork()` or `spawn()` with `stdio: 'ipc'`). Plugin hooks execute as independent command-line processes, NOT as forked child processes with IPC channels. Therefore, `hasIpc: false` is the **expected, normal behavior** for all hook executions.
|
|
|
|
### Actual Problem: Hook Command Execution Failure
|
|
|
|
The hooks.json uses Unix-style environment variable syntax:
|
|
|
|
```json
|
|
{
|
|
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start"
|
|
}
|
|
```
|
|
|
|
**On Windows, this fails because:**
|
|
|
|
1. **Shell Interpreter Mismatch**: Claude Code on Windows likely uses `cmd.exe` or PowerShell to execute hook commands, not Git Bash. The `${VARIABLE}` syntax only works in Bash; cmd.exe uses `%VARIABLE%`.
|
|
|
|
2. **PATH Environment Differences**: The user runs Claude in Git Bash where `bun` and `node` are in PATH. However, Claude Code executes hooks in its own shell context (likely cmd.exe), which may not inherit Git Bash's PATH configuration.
|
|
|
|
3. **CLAUDE_PLUGIN_ROOT Resolution**: If Claude Code doesn't properly set or expand `CLAUDE_PLUGIN_ROOT` before executing the command, the entire path becomes invalid.
|
|
|
|
## Code Investigation Findings
|
|
|
|
### Affected Files
|
|
|
|
| File | Purpose | Issue |
|
|
|------|---------|-------|
|
|
| `plugin/hooks/hooks.json` | Hook command definitions | Uses `${CLAUDE_PLUGIN_ROOT}` Unix syntax |
|
|
| `plugin/scripts/smart-install.js` | Dependency installer | Executed via hooks.json, never runs on Windows |
|
|
| `plugin/scripts/worker-service.cjs` | Worker CLI | Executed via hooks.json, never runs on Windows |
|
|
| `plugin/scripts/*.js` | Hook scripts | None execute because hooks.json commands fail |
|
|
|
|
### hooks.json Analysis
|
|
|
|
Current hooks.json commands:
|
|
|
|
```json
|
|
{
|
|
"SessionStart": [{
|
|
"hooks": [
|
|
{ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/smart-install.js\"" },
|
|
{ "command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start" },
|
|
{ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js\"" }
|
|
]
|
|
}],
|
|
"PostToolUse": [{
|
|
"hooks": [
|
|
{ "command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start" },
|
|
{ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js\"" }
|
|
]
|
|
}]
|
|
}
|
|
```
|
|
|
|
**Problems identified:**
|
|
|
|
1. `${CLAUDE_PLUGIN_ROOT}` - Unix variable expansion, fails in cmd.exe
|
|
2. `bun` command - May not be in system PATH on Windows
|
|
3. `node` command - May not be in system PATH accessible to Claude Code
|
|
|
|
### Worker hasIpc Usage
|
|
|
|
The hasIpc field is used only for admin endpoint IPC messaging, which is a separate concern from hook execution:
|
|
|
|
```typescript
|
|
// src/services/server/Server.ts:209-216
|
|
const isWindowsManaged = process.platform === 'win32' &&
|
|
process.env.CLAUDE_MEM_MANAGED === 'true' &&
|
|
process.send;
|
|
|
|
if (isWindowsManaged) {
|
|
process.send!({ type: 'restart' });
|
|
}
|
|
```
|
|
|
|
This IPC mechanism is for managed process scenarios and is unrelated to why hooks aren't executing.
|
|
|
|
## Relationship to Issue #517
|
|
|
|
| Aspect | Issue #517 | Issue #555 |
|
|
|--------|------------|------------|
|
|
| **Problem** | PowerShell `$_` variable misinterpreted by Bash | Hooks not executing at all |
|
|
| **Location** | ProcessManager.ts (worker internals) | hooks.json execution by Claude Code |
|
|
| **Fix Applied** | Replaced PowerShell with WMIC | N/A (new issue) |
|
|
| **Scope** | Worker process management | Claude Code hook invocation |
|
|
|
|
Issue #517 fixed internal worker operations (orphaned process cleanup). Issue #555 is a completely different layer - it's about Claude Code's plugin system failing to invoke hooks on Windows.
|
|
|
|
## Proposed Fix
|
|
|
|
### Option 1: Cross-Platform Wrapper Script (Recommended)
|
|
|
|
Create a platform-aware wrapper that handles path resolution:
|
|
|
|
```javascript
|
|
// plugin/scripts/hook-runner.js
|
|
#!/usr/bin/env node
|
|
const path = require('path');
|
|
const { spawn } = require('child_process');
|
|
|
|
// Resolve CLAUDE_PLUGIN_ROOT or compute from script location
|
|
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT ||
|
|
path.dirname(__dirname);
|
|
|
|
const hookScript = process.argv[2];
|
|
const hookPath = path.join(pluginRoot, 'scripts', hookScript);
|
|
|
|
// Execute the actual hook
|
|
require(hookPath);
|
|
```
|
|
|
|
Update hooks.json to use relative paths:
|
|
|
|
```json
|
|
{
|
|
"command": "node ./scripts/hook-runner.js context-hook.js"
|
|
}
|
|
```
|
|
|
|
### Option 2: Windows-Specific hooks.json
|
|
|
|
Create a Windows-compatible version using `%CLAUDE_PLUGIN_ROOT%` syntax:
|
|
|
|
```json
|
|
{
|
|
"command": "node \"%CLAUDE_PLUGIN_ROOT%\\scripts\\smart-install.js\""
|
|
}
|
|
```
|
|
|
|
**Drawback:** Requires maintaining two hooks.json versions or using conditional logic.
|
|
|
|
### Option 3: Use Absolute Paths
|
|
|
|
Generate hooks.json at install time with resolved absolute paths:
|
|
|
|
```json
|
|
{
|
|
"command": "node \"C:\\Users\\username\\.claude\\plugins\\marketplaces\\thedotmack\\plugin\\scripts\\smart-install.js\""
|
|
}
|
|
```
|
|
|
|
**Drawback:** Less portable, requires install-time generation.
|
|
|
|
### Option 4: Ensure bun/node in System PATH
|
|
|
|
Add installation validation to ensure `bun` and `node` are in the system-wide PATH, not just Git Bash's PATH:
|
|
|
|
```powershell
|
|
# In smart-install.js for Windows
|
|
if (IS_WINDOWS) {
|
|
// Add to system PATH if not present
|
|
// Or use absolute paths to node/bun executables
|
|
}
|
|
```
|
|
|
|
## Debugging Steps for Users
|
|
|
|
1. **Verify plugin registration:**
|
|
```powershell
|
|
claude /status
|
|
```
|
|
|
|
2. **Check plugin installation:**
|
|
```powershell
|
|
dir $env:USERPROFILE\.claude\plugins\marketplaces\thedotmack\plugin\hooks
|
|
```
|
|
|
|
3. **Test environment variable:**
|
|
```powershell
|
|
$env:CLAUDE_PLUGIN_ROOT = "$env:USERPROFILE\.claude\plugins\marketplaces\thedotmack\plugin"
|
|
node "$env:CLAUDE_PLUGIN_ROOT\scripts\smart-install.js"
|
|
```
|
|
|
|
4. **Check if node/bun are in system PATH:**
|
|
```powershell
|
|
where.exe node
|
|
where.exe bun
|
|
```
|
|
|
|
5. **Enable Claude Code debug logging:**
|
|
- Check Claude Code settings for debug/verbose mode
|
|
- Look for hook execution errors in logs
|
|
|
|
## Impact Assessment
|
|
|
|
- **Severity:** High - Complete loss of memory functionality on Windows
|
|
- **Scope:** All Windows users, especially those using Git Bash
|
|
- **Workaround:** None currently - hooks must execute for memory to work
|
|
- **Affected Versions:** Likely affects 8.5.x on Windows with Claude Code 2.0.76+
|
|
|
|
## Recommended Actions
|
|
|
|
1. **Immediate:** Document the issue and potential workarounds
|
|
2. **Short-term:** Implement Option 1 (cross-platform wrapper script)
|
|
3. **Long-term:** Request clarification from Anthropic on Windows hook execution behavior
|
|
4. **Testing:** Add Windows CI/CD testing for hook execution
|
|
|
|
## Files to Modify
|
|
|
|
1. `plugin/hooks/hooks.json` - Update command syntax
|
|
2. `plugin/scripts/hook-runner.js` - New cross-platform wrapper (create)
|
|
3. `plugin/scripts/smart-install.js` - Add PATH validation for Windows
|
|
4. `docs/public/troubleshooting.mdx` - Document Windows hook issues
|
|
|
|
## Appendix: Technical Details
|
|
|
|
### Environment Variable Expansion by Shell
|
|
|
|
| Shell | Syntax | Works in hooks.json |
|
|
|-------|--------|---------------------|
|
|
| Bash | `${VAR}` or `$VAR` | Yes (if Bash executes) |
|
|
| cmd.exe | `%VAR%` | Yes (if cmd executes) |
|
|
| PowerShell | `$env:VAR` | Yes (if PS executes) |
|
|
|
|
### Claude Code Hook Execution Flow
|
|
|
|
1. Claude Code loads hooks.json from plugin directory
|
|
2. On hook event (SessionStart, PostToolUse, etc.), executes defined commands
|
|
3. Commands are executed via system shell (platform-dependent)
|
|
4. Hook process receives JSON via stdin, outputs response to stdout
|
|
5. Claude Code processes hook output
|
|
|
|
The failure occurs at step 3 when the shell cannot resolve the command or environment variables.
|