On this page
Claude Code Hooks
A Rust binary (kg) that Claude Code invokes before and after every tool call. It captures session data in milliseconds, invisibly.
What it is
Claude Code supports hooks - shell commands that fire at specific lifecycle events. KeepGoing registers the kg binary as a hook handler for PreToolUse, PostToolUse, and Stop events.
The binary is written in Rust and ships as a pre-built binary in the Claude plugin package. It's designed to be invisible - it reads from stdin, updates a JSON file with file locking, and exits. It never blocks Claude Code and never prints output.
Hook types
kg heartbeat Fires before Claude uses a tool and at session start. Sends a heartbeat to keep the session marked as active. Used by the tray to show real-time "Claude is working" state.
kg task-update Fires after Edit, Write, or MultiEdit tool calls. Records which file was just edited and accumulates the touched-files list for the session.
keepgoing save --hook Fires when Claude finishes a response or the session ends. Runs the KeepGoing CLI to auto-save a checkpoint: captures commit hashes, touched files, and a smart summary generated from the session activity. This is the safety net — even without a manual /save, your work is captured.
kg statusline Not a hook — a Claude Code status line renderer. Runs after each Claude response and renders the momentum dashboard at the bottom of the terminal. Amber warnings only appear when work is genuinely at risk: uncommitted edits with no checkpoint after 30+ minutes.
What it captures
Session identity
A stable session ID derived from the Claude Code process. Ties all tool calls in one conversation to a single session record.
Work phase
Whether Claude is in planning or active mode. Transitions one-way from planning to active when the first file edit happens.
Touched files
Deduplicated list of files edited during the session (capped at 200). Appended on each PostToolUse event and shown as the ✎ count in the statusline.
Heartbeat timing
Timestamps for each tool call. Used to calculate session duration and detect when a session has gone idle.
Session start SHA
The git HEAD SHA at first heartbeat. Used at render time to count commits made during the session (shown as the ↑ count).
Active task
The current task description (from the Claude Code context), stored in current-tasks.json for the tray and statusline.
Performance requirement
Claude Code hooks are synchronous - a slow hook delays Claude's response. The kg binary is therefore written to be fast above all else: no network calls, no SQLite, just a file read-modify-write on current-tasks.json using file locking.
Any error in the hook (file not found, malformed JSON, permission issue) is silently swallowed. The hook always exits 0. This ensures a failing hook never interrupts your AI workflow.
Why Rust?
Node.js startup time (~100ms) is noticeable on every Claude tool call. A compiled Rust binary starts in under 5ms. Over a long coding session with hundreds of tool calls, that's the difference between invisible and annoying.