Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 26 additions & 23 deletions bin/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand Down
27 changes: 23 additions & 4 deletions docs/context-monitor.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
{
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions hooks/gsd-context-monitor.js
Original file line number Diff line number Diff line change
@@ -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).
Expand Down Expand Up @@ -109,7 +109,7 @@ process.stdin.on('end', () => {

const output = {
hookSpecificOutput: {
hookEventName: "PostToolUse",
hookEventName: process.env.GEMINI_API_KEY ? "AfterTool" : "PostToolUse",
additionalContext: message
}
};
Expand Down