From a1d60b7160dbec252d57858d1b51e287f421f9ac Mon Sep 17 00:00:00 2001 From: superresistant Date: Wed, 21 Jan 2026 19:43:03 +0100 Subject: [PATCH] fix(install): use absolute paths for hook commands on Windows (#207) Replace $HOME with actual resolved path in hook command strings. $HOME is a Unix shell variable that is not expanded by cmd.exe or PowerShell on Windows, causing hooks to fail with MODULE_NOT_FOUND. The fix uses a new buildHookCommand() helper that: - Uses the actual claudeDir path instead of $HOME - Normalizes backslashes to forward slashes for Node.js compatibility --- bin/install.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bin/install.js b/bin/install.js index 7f39cb561..47b893636 100755 --- a/bin/install.js +++ b/bin/install.js @@ -105,6 +105,16 @@ function expandTilde(filePath) { return filePath; } +/** + * Build a hook command path using forward slashes for cross-platform compatibility. + * On Windows, $HOME is not expanded by cmd.exe/PowerShell, so we use the actual path. + */ +function buildHookCommand(claudeDir, hookName) { + // Use forward slashes for Node.js compatibility on all platforms + const hooksPath = claudeDir.replace(/\\/g, '/') + '/hooks/' + hookName; + return `node "${hooksPath}"`; +} + /** * Read and parse settings.json, returning empty object if doesn't exist */ @@ -390,10 +400,10 @@ function install(isGlobal) { const settingsPath = path.join(claudeDir, 'settings.json'); const settings = cleanupOrphanedHooks(readSettings(settingsPath)); const statuslineCommand = isGlobal - ? 'node "$HOME/.claude/hooks/gsd-statusline.js"' + ? buildHookCommand(claudeDir, 'gsd-statusline.js') : 'node .claude/hooks/gsd-statusline.js'; const updateCheckCommand = isGlobal - ? 'node "$HOME/.claude/hooks/gsd-check-update.js"' + ? buildHookCommand(claudeDir, 'gsd-check-update.js') : 'node .claude/hooks/gsd-check-update.js'; // Configure SessionStart hook for update checking