BETA In open beta. Install live. Lock $5/mo for your first 12 months. See pricing →
Docs / Concepts

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.