Hydrate for Mistral Vibe (forked) — full hook parity
After this page: all six Hydrate hooks fire in Vibe — including automatic context injection before every prompt, compact-survival snapshots, tool-use visibility, and session-start re-injection — giving Vibe the same memory quality as Claude Code.
Why fork
Stock Mistral Vibe ships one experimental hook: post_agent_turn. This gives
Hydrate one surface — after each turn — to capture sessions. Context injection before prompts
is not possible; the model must call hydrate_recall via MCP tools on its own
initiative.
The Hydrate fork of Mistral Vibe adds five new hook events:
| Hook event | Shim | What it enables |
|---|---|---|
user_prompt_submit | vibe-context | Automatic context injection before every prompt (matches Claude Code's UserPromptSubmit) |
session_start | vibe-session-start | Recovery snapshot re-injection at session open (matches Claude Code's SessionStart) |
pre_compact | vibe-precompact | Compact-survival snapshot before context is wiped (matches Claude Code's PreCompact) |
pre_tool_use | vibe-tool-pre | Tool-guard suggestions before tool execution |
post_tool_use | vibe-tool-post | Tool invocation capture for dashboard visibility |
The original post_agent_turn → vibe-capture is retained unchanged.
Planned (post-launch): pre_model_call — interpose Hydrate's
compression algorithm between message-array assembly and the LLM POST. This is the only hook
that allows reducing context size mid-session (not just adding to it).
Prerequisites
- Hydrate installed and the stock Vibe integration working. See stock Vibe install.
- Python 3.12+ and
uv(orpip). - The Hydrate fork is at
github.com/getHydrate/mistral-vibe.
Install the forked binary
Replace your existing vibe binary with the fork:
# Using uv (recommended)
uv tool install git+https://github.com/getHydrate/mistral-vibe.git
# Or using pip
pip install git+https://github.com/getHydrate/mistral-vibe.git Confirm the fork is running:
vibe --version The version string will be the same as stock Vibe (the fork tracks upstream closely) but you can confirm hook support by checking:
python3 -c "from vibe.core.hooks import HookEventName; print([e.value for e in HookEventName])"
Expected output includes user_prompt_submit, session_start,
pre_compact, pre_tool_use, post_tool_use alongside
post_agent_turn.
Wire the hooks
hydrate vibe install
If you already ran hydrate vibe install for stock Vibe, running it again is safe
— it is idempotent. The hooks that were no-ops on stock Vibe (user_prompt_submit,
session_start, pre_compact, pre_tool_use,
post_tool_use) now fire because the forked binary recognises them.
Verify
hydrate vibe doctor All checks should be green.
Then run a Vibe prompt and confirm all hook surfaces fired:
# Check that user_prompt_submit fired (context injection)
sqlite3 ~/.hydrate/data.db \
"SELECT COUNT(*) FROM hook_events WHERE event_type='prompt_submit' AND source='mistral-vibe' AND ts > strftime('%s','now','-10 minutes')"
# Check pre_compact is being written (only fires when context compaction threshold is hit)
ls -la ~/.hydrate/last-precompact.json 2>/dev/null && echo "precompact snapshot exists" Parity demo against stock Vibe
If you have both stock and forked Vibe available, the difference in context injection is
measurable. On stock Vibe, open a session and ask about a project decision you made a week
ago. The model has to call hydrate_recall to find it. On forked Vibe, the same
query gets the relevant fact injected before the model even sees your prompt — you see "I can
see from your Hydrate memory that…" without the model explicitly invoking a tool first.
To confirm injection is happening:
sqlite3 ~/.hydrate/data.db <<'SQL'
SELECT
datetime(retrieved_at) AS at,
endpoint AS hook,
latency_ms
FROM hydrate_retrievals
WHERE source LIKE 'hydrate-mcp/vibe%'
OR source = 'mistral-vibe'
ORDER BY id DESC
LIMIT 10;
SQL
On stock Vibe you will see only post_agent_turn events. On forked Vibe you will
also see user_prompt_submit entries timestamped before each agent turn.
Hook wire format
The fork's hook wire format for user_prompt_submit (from the verified spec):
Stdin (JSON):
{
"hook_event_name": "user_prompt_submit",
"prompt": "<the user's prompt text>",
"session_id": "<uuid>",
"cwd": "/path/to/project",
"transcript_path": "",
"timestamp": "2026-05-15T12:00:00Z",
"vibe_version": "2.9.6"
} Stdout (vibe-context returns):
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "<Hydrate-injected context>"
}
}
An empty stdout (or non-JSON) is treated as allow with no injection. The hook denies a prompt
by returning {"decision": "deny", "reason": "..."}.
For pre_tool_use, a deny response blocks the tool call and returns a synthetic
error to the model explaining why.
Updating the fork
The fork tracks the upstream mistralai/mistral-vibe main branch. To update:
pip install --upgrade git+https://github.com/getHydrate/mistral-vibe.git
# or
uv tool upgrade mistral-vibe
After upgrading, run vibe --version and verify the new hook events are still
present.
Upstream contribution status
The five new hook events are designed to be contributed upstream to
mistralai/mistral-vibe. The work is broken into four self-contained
patch sets, each landed in the Hydrate fork and ready for upstream submission:
- Patch 1 —
user_prompt_submit· merged into the Hydrate fork at SHA2140602· upstream PR pending - Patch 2 —
session_start+pre_compact· merged into the Hydrate fork at SHA353aa67· upstream PR pending - Patch 3 —
post_tool_use· merged into the Hydrate fork at SHA3bf1415· upstream PR pending - Patch 4 —
pre_tool_use(deny-only) · merged into the Hydrate fork at SHA4055f8e· upstream PR pending
All SHAs reference github.com/getHydrate/mistral-vibe, not
mistralai/mistral-vibe. If upstream Mistral merges the patches,
this fork becomes unnecessary and Hydrate switches back to the official binary
transparently.
How the fork was built — Hydrate dogfooding itself
Building five new hook events into a Python codebase you don't own, while
keeping every patch self-contained enough to land upstream, is exactly the
kind of multi-runtime task Hydrate's orchestrator was designed for. The
fork was built using three coding agents coordinated by
hydrate orchestrator:
| Pane | Runtime | Role |
|---|---|---|
dev | Claude Code (Sonnet 4.6) | Read the stock Vibe codebase, designed the HookEventName enum additions, and authored the Python diffs. Claude Code's tool calling discipline kept each patch self-contained. |
vibe | Forked Mistral Vibe (under test) | Ran the new hook events against the Hydrate shims (vibe-context, vibe-session-start, etc.) to confirm the wire format. Every patch was bench-tested in this pane before commit. |
vibe-codex | Codex CLI (gpt-5.5) | Wrote the upstream-facing PR descriptions and the new tests in tests/core/test_hooks.py. Codex's strictly-on-task style was a good fit for boilerplate-heavy test scaffolding. |
The orchestrator carried one shared canon across all three panes — what the
hook wire format was, which patches were in-flight, what the next blocker
was — so no pane double-dispatched and no decision was lost when one of
them got compacted. The canon lived in Hydrate's local SQLite store
(~/.hydrate/data.db); the orchestrator broadcast updates with
hydrate orchestrator dispatch and gated handoffs with
hydrate orchestrator set <task> done.
The dogfood matters: Hydrate is built around the claim that you can run a real multi-runtime workflow without losing context at every boundary. The fork is the proof. Two distinct vendor agents (Claude + Codex) plus the target runtime itself (Vibe) coordinated to extend Vibe's own hook surface, using Hydrate as the shared memory layer that let them disagree, reconcile, and ship.
If you want to reproduce the workflow, the orchestrator's standing
instructions live at docs/plans/2026-05-14-vibe-hooks-fork/ in
the Hydrate repo, and the dispatch pattern is documented at
Orchestration overview.
Differences from stock Vibe
This fork makes no changes to Vibe's UI, model configuration, or tool execution logic. The only changes are in the hook system:
- New
HookEventNameenum values. - New
HookPayloadshapes for each event. - Wiring in
agent_loop.pyat the appropriate call sites. - New tests (
tests/core/test_hooks.py).
No Hydrate-specific code or branding is in the fork — the hook events are general-purpose and work with any hook consumer.
What changed on your machine
Same as stock Vibe install plus the forked binary replaces the stock vibe
executable. No other file changes.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
user_prompt_submit still not firing after install | Still running stock binary | which vibe — confirm it points at the fork; python3 -c "from vibe.core.hooks import HookEventName; print(list(HookEventName))" should include user_prompt_submit |
| Import error on install | Python version below 3.12 | Upgrade Python; check python3 --version |
| Fork out of date with upstream changes | New upstream commit broke something | File an issue at github.com/getHydrate/mistral-vibe; in the meantime, pin to the last-known-good SHA |
pre_compact hook never fires | Compaction threshold not hit | This is normal in short sessions; the hook fires when Vibe determines the context window is near its limit |
Next steps
- Claude Code integration — understand what full parity looks like on Claude Code
- Codex integration — add Codex to the same memory substrate
- Free install — if you need to start from scratch