Claude Code hooks
Hydrate plugs into Claude Code via four first-party hooks. They're wired in during
hydrate setup and are invisible during normal use - you run
claude exactly as you always have.
The four hooks
UserPromptSubmit - context inject
Fires the instant you hit return on a prompt, before Claude Code sends anything to the model. Hydrate queries its local SQLite store for facts scoped to the current project (plus your user- and org-scope facts) and injects the relevant ones into the context.
Relevance is scored by a blend of embedding similarity to your prompt, recency, and
reinforcement (how often the fact has been confirmed or referenced). The hook has a
soft budget - it will not inject more than a few hundred tokens of facts unless
you override that via hydrate config set inject.max_tokens.
Stop - transcript capture
Fires when a session ends. Hydrate receives the full transcript, runs a small extractor that pulls atomic facts out of what the model and tools actually did, and stores them scoped to the project. Also writes a session summary used later for retrieval.
Extraction uses whichever LLM provider you've configured (OPENAI_API_KEY,
ANTHROPIC_API_KEY, or a local HYDRATE_LLM_ENDPOINT). You
bring your own key - Hydrate doesn't meter or proxy.
PreToolUse - large-file redirect
Fires before each tool call. When Claude Code is about to read a large file that Hydrate
already has summarised in its store, this hook substitutes a compressed version instead
- saving hundreds of input tokens per call. Disabled by default; enable with
hydrate config set tool_guard.enabled=true.
PostToolUse - tool-output capture
Fires after each tool call and captures tool outputs (file reads, bash results) into
Hydrate's store for future injection. Disabled by default; enable with
hydrate config set tool_capture.enabled=true.
Where they live
All four hooks are registered in ~/.claude/settings.json under the
hooks key. Each one runs a lightweight binary installed to
~/.local/bin/ that reads the server port from
~/.hydrate/server.port at runtime:
{
"hooks": {
"UserPromptSubmit": [
{"hooks": [{"type": "command", "command": "~/.local/bin/claude-context", "timeout": 3}]}
],
"Stop": [
{"hooks": [{"type": "command", "command": "~/.local/bin/claude-capture", "timeout": 15}]}
],
"PostToolUse": [
{"hooks": [{"type": "command", "command": "~/.local/bin/claude-tool-post", "timeout": 3}]}
],
"PreToolUse": [
{"hooks": [{"type": "command", "command": "~/.local/bin/claude-tool-pre", "timeout": 3}]}
]
}
}
If hydrate-server isn't running when a hook fires, the hook no-ops in
under 50 ms and your Claude Code session continues normally - Hydrate is
designed to fail soft.
Turning hooks off for a session
Set HYDRATE_DISABLE=1 in the environment Claude Code is launched from to
skip all hooks for that invocation. Useful when you explicitly want a fresh mind:
greenfield exploration, debugging Hydrate itself, or a one-off prompt where
context would be noise.
Verifying they ran
hydrate facts diff --last-session
Prints the exact set of facts injected into the last session, plus any new facts
extracted from it. If the output is empty, check hydrate doctor -
the daemon is probably down.