Skip to content

Hooks — Claude Code automation

Claude Code supports shell hooks that fire in response to lifecycle events. HCS uses one hook: a UserPromptSubmit hook that monitors session context size and triggers a structured memory dump when the context approaches the limit.


check-context.ps1 — context watch hook

Event: UserPromptSubmit — fires on every user prompt before Claude Code processes it Location (running): ~/.claude/hooks/check-context.ps1 Location (source): scripts/hooks/check-context.ps1 in this repo Timeout: 30 seconds

What it does

  1. Reads the hook input JSON from stdin — this includes the path to the current session transcript
  2. Walks backward through the transcript to find the most recent assistant turn with token usage data
  3. Calculates total context = input_tokens + cache_creation_input_tokens + cache_read_input_tokens
  4. If the total exceeds 90,000 tokens, injects a [CONTEXT-WATCH] system reminder into the session
  5. Falls back to character-count estimation (total_chars / 4) if no usage data is found in the transcript
  6. Always exits 0 — never blocks a prompt, never throws an error to the user

What the reminder does

When [CONTEXT-WATCH] fires, Claude Code writes a comprehensive memory dump to the project's auto-memory directory before responding to the user's actual message. The dump covers:

  • In-flight work: branches, files modified, PR/issue numbers, mid-implementation state
  • Decisions made and their reasoning
  • Bugs found and fixes applied (non-obvious ones only)
  • Blockers and open questions
  • Verification status
  • User feedback observed this session

After the dump, Claude Code ends its turn with:

Memory saved (N files updated). Run /clear when ready — your next session will auto-load.

The user then runs /clear manually. The hook never clears the session automatically.

Why /clear instead of compaction

Session compaction (the default Claude Code behavior when context fills up) produces a lossy summary that the model treats as whole context. This leads to subtle loss of reasoning detail. The explicit /clear + structured memory approach is honest about what has been kept — the next session loads the memory files and knows exactly what was saved and what was not.

Hook configuration in settings.json

"hooks": {
  "UserPromptSubmit": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "pwsh.exe -NoProfile -ExecutionPolicy Bypass -File \"C:/Users/KristopherTurner/.claude/hooks/check-context.ps1\"",
          "timeout": 30
        }
      ]
    }
  ]
}

The path must be absolute. Use forward slashes or escaped backslashes in the JSON.

Keeping the hook in sync

The running copy at ~/.claude/hooks/check-context.ps1 and the source copy at scripts/hooks/check-context.ps1 in this repo should stay identical. When updating the hook:

  1. Edit scripts/hooks/check-context.ps1 in this repo
  2. Copy it to ~/.claude/hooks/check-context.ps1
  3. Test by submitting a prompt in a session with a large transcript
  4. Commit the update: fix(hooks): <description>

Adjusting the threshold

The threshold is defined at the top of the script:

$THRESHOLD = 90000

90,000 tokens was chosen because: - The Anthropic prompt cache has a 5-minute TTL at approximately 100k tokens - Triggering at 90k gives enough headroom to write the memory dump without hitting the hard context limit - It fires early enough to save meaningful state without firing too aggressively on short sessions

Raise the threshold if you find it fires too often on normal work. Lower it if you want earlier warnings.


Hook output format

Hooks communicate back to Claude Code via stdout JSON:

{
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "The text to inject as a system reminder..."
  }
}

Anything written to stderr is logged but does not reach Claude Code. Exit code 0 always — any non-zero exit would block the prompt.


Adding new hooks

Additional hooks can be added to settings.json. Supported events: - UserPromptSubmit — fires before Claude Code processes a user message - PreToolUse — fires before a tool call (can block it) - PostToolUse — fires after a tool call completes - Stop — fires when Claude Code finishes a turn

For each new hook, add a script under scripts/hooks/ in this repo and copy it to ~/.claude/hooks/. Document what it does and why.