Skip to main content
TRW
TRWDocumentation

Hooks

Hooks enforce quality automatically — running shell commands at phase boundaries and session events without configuration. They load learnings at startup, save checkpoints before compaction, block delivery without passing tests, and warn when knowledge would be lost. TRW ships 12 hooks that cover the full session lifecycle.

How Hooks Work

Claude Code fires hook events at specific points in its lifecycle — when a session starts, before a tool runs, after a file is modified, and when the session ends. TRW registers shell scripts against these events in .claude/settings.json. When an event fires, Claude Code runs the matching script and reads its output.

Each hook follows a fail-open pattern: if the script errors, it exits 0 silently so your session is never broken by hook infrastructure. Hooks that enforce gates (like the delivery blocker) use exit code 2 to signal a block with an explanation message.

Info

Hooks run in the project's git root directory. They use lib-trw.sh for shared utilities like finding the active run, reading config, and logging execution telemetry.

Hook Events

Claude Code provides the hook events. TRW registers scripts against each one.

Session

EventWhen it firesWhat TRW does
SessionStartSession opens (startup, resume, compact, clear)Loads prior learnings, recovers interrupted runs, emits tier guidance
UserPromptSubmitBefore every user prompt is sent to the modelInjects phase-aware context reminders (research, plan, implement, etc.)
PreCompactBefore context window compactionSaves emergency checkpoint so progress survives compaction
SessionEndSession closes normallyWarns if trw_deliver was not called, preventing knowledge loss
StopUser presses Escape or session is interruptedBlocks if delivery was skipped (max 2 blocks, then advisory)

Tools

EventWhen it firesWhat TRW does
PreToolUseBefore a tool call executesGates trw_deliver until build check passes; validates PRD write scope
PostToolUseAfter Write or Edit tool completesLogs file_modified events to the active run for change tracking

Agents

EventWhen it firesWhat TRW does
SubagentStartA subagent is spawnedInjects abbreviated TRW protocol and active run context
SubagentStopA subagent completesLogs subagent completion and captures telemetry
TeammateIdleAn Agent Teams teammate has no pending tasksNotifies the lead so work can be redistributed
TaskCompletedAn Agent Teams task finishesBlocks teammates who skipped build check or checkpoints

Warning

Hooks are synchronous — they block until the script completes or times out. Each hook has a configured timeout (3–10 seconds). Keep custom hooks fast to avoid delaying the agent's workflow.

Built-in Hooks

TRW ships these 12 hook scripts. They are installed into .claude/hooks/ and registered in .claude/settings.json automatically.

ScriptEventPurpose
session-start.shSessionStartLoads learnings, checks for interrupted runs, emits tier-calibrated ceremony guidance
user-prompt-submit.shUserPromptSubmitInjects phase-specific reminders before each prompt (under 150 tokens)
pre-compact.shPreCompactSaves active run state to a recovery file before context compaction
session-end.shSessionEndWarns if events were logged but trw_deliver was never called
stop-ceremony.shStopBlocks exit if delivery was skipped (max 2 blocks, then falls through)
pre-tool-deliver-gate.shPreToolUseBlocks trw_deliver until trw_build_check has passed
post-tool-event.shPostToolUseLogs file modifications after Write/Edit tool calls
validate-prd-write.shPreToolUseRestricts planning agents to writing only PRD and run directory files
subagent-start.shSubagentStartInjects TRW protocol context and phase guidance into spawned subagents
subagent-stop.shSubagentStopCaptures subagent completion telemetry and logs results
task-completed.shTaskCompletedQuality gate for Agent Teams: blocks if build check or checkpoints are missing
teammate-idle.shTeammateIdleNotifies the lead agent when a teammate has no remaining tasks

Tip

The most impactful hook is pre-tool-deliver-gate.sh. It blocks trw_deliver until trw_build_check has passed, preventing the agent from closing a session with untested code. This single gate catches the most common failure mode in AI-assisted development.

Hook Registration

Hooks are registered in .claude/settings.json under the hooks key. Each event maps to an array of matchers, and each matcher contains a shell command and timeout. The TRW installer generates this configuration automatically.

.claude/settings.json (excerpt)
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [{
          "type": "command",
          "command": "sh .claude/hooks/session-start.sh",
          "timeout": 5000
        }]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "mcp__trw__trw_deliver",
        "hooks": [{
          "type": "command",
          "command": "sh .claude/hooks/pre-tool-deliver-gate.sh",
          "timeout": 5000
        }]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [{
          "type": "command",
          "command": "sh .claude/hooks/stop-ceremony.sh",
          "timeout": 10000
        }]
      }
    ]
  }
}

The matcher field filters when the hook fires. An empty string matches all events of that type. A specific value like mcp__trw__trw_deliver matches only that tool call. SessionStart uses source matchers ( startup, resume, compact, clear) to fire on each session source.

Custom Hooks

You can add your own hooks alongside TRW's built-in ones. Add a new entry to the appropriate event array in .claude/settings.json. Your hook script receives the same JSON payload from stdin that TRW's hooks receive.

adding a custom PostToolUse hook
// In .claude/settings.json, add to the PostToolUse array:
{
  "matcher": "Bash",
  "hooks": [{
    "type": "command",
    "command": "sh .claude/hooks/my-bash-audit.sh",
    "timeout": 3000
  }]
}

Custom hooks follow the same conventions: exit 0 to allow, exit 2 to block (with a message on stderr). Use the fail-open pattern — trap 'exit 0' EXIT — so errors never break the agent's session.

Troubleshooting

Hooks not firing at all

Cause: The .claude/settings.json file is missing or the hooks section was not generated by the installer.

Fix: Re-run the TRW installer or copy the hooks config from settings.json into your project.

Hook exits with "permission denied"

Cause: Shell scripts need execute permissions on Unix systems.

Fix: Run chmod +x .claude/hooks/*.sh to fix permissions.

Hook times out (no output)

Cause: Hooks have timeouts (3-10 seconds). A slow filesystem or missing jq can cause delays.

Fix: Install jq for faster JSON parsing. Check that .trw/ directory exists and is not on a network mount.

Next Steps