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.
The same hooks for Codex and Vibe
Claude Code is not the only runtime Hydrate hooks into. OpenAI Codex (CLI and macOS app) and Mistral Vibe each have their own per-event binary family that does the same job:
| Event | Claude Code | Codex | Vibe |
|---|---|---|---|
| SessionStart | claude-session-start | codex-session-start | vibe-session-start |
| UserPromptSubmit | claude-context | codex-context | vibe-context |
| PreCompact | claude-precompact | n/a | vibe-precompact |
| PreToolUse | claude-tool-pre | codex-pretooluse | vibe-tool-pre |
| PostToolUse | claude-tool-post | n/a | vibe-tool-post |
| Stop | claude-capture | codex-capture | vibe-capture |
| PermissionRequest | n/a | codex-permission | n/a |
Internally the Claude and Codex binaries share an adapter layer
(internal/runtimebridge) that translates each runtime's
on-the-wire JSON to and from a single canonical event model. Vibe
ships its own family of standalone binaries that read the
equivalent shared helpers without going through the adapter. Either
way the user-visible result is the same: a fact you capture in
Claude Code is immediately retrievable from Codex, and vice versa.
The cross-runtime architecture is documented in chapter 27 of the thesis. See /integrations/claude-code, /integrations/codex, and /integrations/vibe for per-runtime install steps.