diff --git a/bin/install.js b/bin/install.js index 8a265e643e..aa62fd27c8 100755 --- a/bin/install.js +++ b/bin/install.js @@ -1403,24 +1403,26 @@ function uninstall(isGlobal, runtime = 'claude') { } } - // Remove GSD hooks from PostToolUse - if (settings.hooks && settings.hooks.PostToolUse) { - const before = settings.hooks.PostToolUse.length; - settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(entry => { - if (entry.hooks && Array.isArray(entry.hooks)) { - const hasGsdHook = entry.hooks.some(h => - h.command && h.command.includes('gsd-context-monitor') - ); - return !hasGsdHook; + // Remove GSD hooks from PostToolUse and AfterTool (Gemini uses AfterTool) + for (const eventName of ['PostToolUse', 'AfterTool']) { + if (settings.hooks && settings.hooks[eventName]) { + const before = settings.hooks[eventName].length; + settings.hooks[eventName] = settings.hooks[eventName].filter(entry => { + if (entry.hooks && Array.isArray(entry.hooks)) { + const hasGsdHook = entry.hooks.some(h => + h.command && h.command.includes('gsd-context-monitor') + ); + return !hasGsdHook; + } + return true; + }); + if (settings.hooks[eventName].length < before) { + settingsModified = true; + console.log(` ${green}✓${reset} Removed context monitor hook from settings`); + } + if (settings.hooks[eventName].length === 0) { + delete settings.hooks[eventName]; } - return true; - }); - if (settings.hooks.PostToolUse.length < before) { - settingsModified = true; - console.log(` ${green}✓${reset} Removed context monitor hook from settings`); - } - if (settings.hooks.PostToolUse.length === 0) { - delete settings.hooks.PostToolUse; } } @@ -2031,7 +2033,8 @@ function install(isGlobal, runtime = 'claude') { } // Configure statusline and hooks in settings.json - // Gemini shares same hook system as Claude Code for now + // Gemini uses AfterTool instead of PostToolUse for post-tool hooks + const postToolEvent = runtime === 'gemini' ? 'AfterTool' : 'PostToolUse'; const settingsPath = path.join(targetDir, 'settings.json'); const settings = cleanupOrphanedHooks(readSettings(settingsPath)); const statuslineCommand = isGlobal @@ -2080,17 +2083,17 @@ function install(isGlobal, runtime = 'claude') { console.log(` ${green}✓${reset} Configured update check hook`); } - // Configure PostToolUse hook for context window monitoring - if (!settings.hooks.PostToolUse) { - settings.hooks.PostToolUse = []; + // Configure post-tool hook for context window monitoring + if (!settings.hooks[postToolEvent]) { + settings.hooks[postToolEvent] = []; } - const hasContextMonitorHook = settings.hooks.PostToolUse.some(entry => + const hasContextMonitorHook = settings.hooks[postToolEvent].some(entry => entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-context-monitor')) ); if (!hasContextMonitorHook) { - settings.hooks.PostToolUse.push({ + settings.hooks[postToolEvent].push({ hooks: [ { type: 'command', diff --git a/docs/context-monitor.md b/docs/context-monitor.md index b312bd8340..24272d8213 100644 --- a/docs/context-monitor.md +++ b/docs/context-monitor.md @@ -1,6 +1,6 @@ # Context Window Monitor -A PostToolUse hook that warns the agent when context window usage is high. +A post-tool hook (`PostToolUse` for Claude Code, `AfterTool` for Gemini CLI) that warns the agent when context window usage is high. ## Problem @@ -37,7 +37,7 @@ Statusline Hook (gsd-statusline.js) /tmp/claude-ctx-{session_id}.json ^ reads | -Context Monitor (gsd-context-monitor.js, PostToolUse) +Context Monitor (gsd-context-monitor.js, PostToolUse/AfterTool) | injects v additionalContext -> Agent sees warning @@ -63,9 +63,9 @@ GSD's `/gsd:pause-work` command saves execution state. The WARNING message sugge Both hooks are automatically registered during `npx get-shit-done-cc` installation: - **Statusline** (writes bridge file): Registered as `statusLine` in settings.json -- **Context Monitor** (reads bridge file): Registered as `PostToolUse` hook in settings.json +- **Context Monitor** (reads bridge file): Registered as `PostToolUse` hook in settings.json (`AfterTool` for Gemini) -Manual registration in `~/.claude/settings.json`: +Manual registration in `~/.claude/settings.json` (Claude Code): ```json { @@ -88,6 +88,25 @@ Manual registration in `~/.claude/settings.json`: } ``` +For Gemini CLI (`~/.gemini/settings.json`), use `AfterTool` instead of `PostToolUse`: + +```json +{ + "hooks": { + "AfterTool": [ + { + "hooks": [ + { + "type": "command", + "command": "node ~/.gemini/hooks/gsd-context-monitor.js" + } + ] + } + ] + } +} +``` + ## Safety - The hook wraps everything in try/catch and exits silently on error diff --git a/hooks/gsd-context-monitor.js b/hooks/gsd-context-monitor.js index f86ac2f591..cae8fc930f 100644 --- a/hooks/gsd-context-monitor.js +++ b/hooks/gsd-context-monitor.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -// Context Monitor - PostToolUse hook +// Context Monitor - PostToolUse/AfterTool hook (Gemini uses AfterTool) // Reads context metrics from the statusline bridge file and injects // warnings when context usage is high. This makes the AGENT aware of // context limits (the statusline only shows the user). @@ -109,7 +109,7 @@ process.stdin.on('end', () => { const output = { hookSpecificOutput: { - hookEventName: "PostToolUse", + hookEventName: process.env.GEMINI_API_KEY ? "AfterTool" : "PostToolUse", additionalContext: message } };