v0.6.0
Hydrate v0.6.0
Two headline features in this release:
-
Handover-first resume —
.hydrate/HANDOVER.mdis now the primary high-fidelity channel for resuming a session after/clear, with a per-session archive at.hydrate/handovers/for cross-sprint mining. The structured store (chunks, facts, canon) stays for cross-session / cross-runtime work; the handover file is for "what was I doing 90 seconds ago." Architectural rationale indocs/thesis/30_HANDOVER_PRIMARY_STORE_SECONDARY.md. -
The autonomous project wiki (now surfaced in the dashboard as Files) — a self-maintaining set of markdown pages, regenerated periodically from your codebase using the LLM you already have, that ships in your repo and is visible to every runtime Hydrate supports. Cortex (cdeust/Cortex v3.17.0) lit this idea up first; v0.6.0 is Hydrate's cross-runtime answer.
Handover-first resume (Phases A–F)
The chunker-only resume failed at scale — a probe quiz on a 22-canon-item project scored 1.5/14 (≈11%) because the Claude Code harness truncates session-start additional-context payloads to ~2 KB inline. After moving the primary channel to .hydrate/HANDOVER.md (which the agent reads via the Read tool, bypassing the cap), the same quiz scored 13/14 + 1 partial (≈96%).
What's new:
internal/handover/— atomic-write Go package owning the file layout (Path,Read,Write,WriteArchived,Clear,List,Prune).hydrate handoverCLI —path / read [--json] [--archive=FILE] / write [--stdin] [--touch] [--no-archive] / clear / list [--json] / grep <pat> / prune [--keep=N] [--older-than=DUR].readexits 0 found / 2 absent;grepexits 0 hits / 2 no-matches (greppable).- Per-session archive at
.hydrate/handovers/<UTC-ISO-compact>-<6hex-rand>.md, atomic copy to.hydrate/HANDOVER.mdas the latest pointer. Random suffix eliminates same-second collisions (verified by 20-goroutine concurrency test). /hydrate-distilltemplate Phase 0 — heredoc piping the handover body intohydrate handover write --stdin. CLI owns the archive layout so the agent doesn't need to know about archive paths./hydrate-lasttemplate — reads.hydrate/HANDOVER.mdsilently into agent context and emits a one-line confirmation, instead of dumping the full body verbatim. Visible-token cost dropped from ~2k to ~50; the agent still has the full content available.- Pre-distill self-review checklist — promotes decisions/goals/facts into the lossless rails (canon + goals + facts) before distillation, so they survive
/cleareven when the chunker over-compresses. hydrate-server's/api/v1/session-resumenow surfaces## Active goals+## Recent canon (last 30 days)as dedicated sections, before the chunk bullets.
Both .hydrate/HANDOVER.md and .hydrate/handovers/ are gitignored by default — per-developer ephemeral state.
Dashboard — /handovers (Handovers nav)
Browse the per-project handover archive from the dashboard. Two-pane layout:
- Left rail: every project that has at least one entry in
.hydrate/handovers/, sorted by most-recent archive mtime DESC, with name / entry count / "Xd ago" badge. - Right pane: archive entries for the selected project (timestamp + size + first H1 heading), with a viewer that toggles between server-rendered HTML (goldmark + GFM) and raw markdown.
Three JSON endpoints back the page:
GET /api/v1/dashboard/handovers→ projects with archivesGET /api/v1/dashboard/handovers/entries→ entries for one projectGET /api/v1/dashboard/handovers/entry→ one entry + rendered HTML
Project cwds come from transcript JSONL cwd fields, not from claude_usage_sessions.project_cwd (which mangles usernames containing _ into / on some installs).
Dashboard — /wiki is now Files
The wiki page in the dashboard was a hybrid of prose overview + per-file notes; in practice the file browser turned out to be the useful part. Renamed in the sidebar + page title to Files, with the tree pane re-organised:
- Top-level prose (00-overview … 10-themes) collapses into a small "Generated overview" section at the top of the tree, closed by default.
- The real project tree mirrors the actual source layout (
cmd/,internal/, etc.) with the wiki's internalfiles/prefix stripped and.mdextensions trimmed, so what you see iscmd/claude-context/main.gorather thanfiles/cmd/claude-context/main.go.md. - Clicking any file renders the curated
.mdinline (same renderer as before, now with GFM tables — the previous default-goldmark setup silently dropped table syntax).
New plumbing supporting Files + Handovers:
GET /api/v1/dashboard/wiki/source— serves any source file referenced from a wiki page'sfrontmatter.sourceschips, with the body rendered as HTML for.mdfiles and as plain text for everything else. Path is validated against the project root (parent ofHYDRATE-wiki/).POST /api/v1/dashboard/reveal— opens the platform's file manager pointing at a file.open -Ron macOS,explorer /select,on Windows,xdg-open <parent>on Linux. Path is validated againstknownProjectRoots()(the union of transcript-derived handover cwds and curated wiki project roots), so a hostile-but-loopback caller can't pop Finder on/etc/passwd— that request returns 403.
Reveal-in-Finder buttons appear on every wiki source chip, the wiki page header (reveals the wiki .md itself), and each handovers entry viewer.
Headline — hydrate wiki curate + auto-curate on session start
Five canonical project pages, one file template emitting five sections per source file, all written to <project>/HYDRATE-wiki/ and stamped with YAML frontmatter recording the SHA of every source they cite.
What you get on a Go project:
HYDRATE-wiki/
├── 00-overview.md
├── 01-architecture.md
├── 02-commands.md
├── 03-mcp-and-integrations.md
├── 04-onboarding.md
└── files/
├── cmd/.../*.md
└── internal/.../*.md
Each file page has: Purpose, Public API, Callers, Tests, Invariants. Structure comes from Go's stdlib parser (go/parser); the prose Purpose section uses your configured LLM (claude CLI on PATH preferred, falling back to env keys). No LLM available → pages still render, with structure-only content and a verbatim "no LLM available" hint where prose would have lived.
Trigger paths:
- Automatic, every six hours, via
claude-session-start— same detached-subprocess pattern shipped in v0.5.1 for CLAUDE.md auto-prime. Cadence-marker at~/.hydrate/auto-wiki/<project-slug>.last. - Manual via
hydrate wiki curate [DIR] [--max-pages-per-cycle=N] [--dry-run]. - From the dashboard at
/wiki— project picker, page list, rendered body, "Curate now" button. - From any MCP client via the new
curate_wikitool.
The on-disk file lock at ~/.hydrate/auto-wiki/<slug>.lock guarantees one worker per project at a time; stale locks (>2h) are reclaimed automatically.
Drift detection
Every page carries frontmatter recording the SHA of each source it cites:
---
hydrate-wiki:
generated: 2026-05-22T12:00:00Z
hydrate-version: v0.6.0
sources:
- path: cmd/hydrate/dehydrate.go
sha: 4009ec2…
---A page is queued for re-author when any cited source's SHA changes, any source is deleted, or the page is older than 60 days. Structural pages with zero source refs stay current until the 60-day window — they always re-enumerate cmd/ and internal/ from disk.
Multi-language: real tree-sitter, embedded in the binary
The codebase intelligence layer (internal/codebaseintel) ships two parsing backends, both real, both in every binary:
- Go — Go's standard-library parser (
go/parser). Faster than tree-sitter for Go, surfaces doc comments natively. - Everything else — a pure-Go tree-sitter runtime (
github.com/odvcencio/gotreesitterv0.18.0), with 206 grammars lazy-loaded from embedded blobs.
v0.6.0 ships hand-written tree-sitter Queries for 11 languages: Go, Python, JavaScript, TypeScript / TSX, Rust, Java, Ruby, Swift, C, C++. File pages for any source file in these languages are populated with real symbol / import / caller data extracted from the actual parse tree.
There is no installer. There is no opt-in download. There are no stubs. The grammars are part of the binary.
Tradeoff: binary size. The hydrate CLI binary grew from ~23 MB (v0.5.1) to ~50 MB (v0.6.0). That's the cost of bundling 206 grammar blobs. We considered shipping them as a separate download to keep the binary small but rejected it because (a) a feature that needs a follow-up download to work is a stub by another name and we don't ship stubs, and (b) lazy loading means the grammars only consume RAM when actually used, so the runtime cost stays low.
File pages on non-Go projects
A Python repo gets per-file pages with: add (func, line 4), Calculator (type, line 8), multiply (func, line 9), plus imports of os and typing. Same for JS / TS / Rust / Java / etc.
Dashboard — /wiki page
Read-only viewer. Project picker reads ~/.hydrate/auto-wiki/<slug>.dir sidecars (written by the curate worker so the dashboard can discover projects without scanning the filesystem). Page list, rendered body pane, manual "Curate now" button. Live SSE updates are deferred to v0.6.1; the page has a manual Refresh button.
MCP — curate_wiki tool
Inputs: project (defaults to cwd basename), apply (default false). Returns the priority-ordered authoring queue and, when apply=true, spawns hydrate wiki curate. Lets any MCP-capable client (Claude Code, Codex CLI, Codex app, Vibe, Cursor, Cline, Zed) trigger the worker.
Cross-runtime — the differentiator
Cortex's wiki is locked to Claude Code's plugin marketplace. Hydrate's wiki is plain markdown in your repo. Any runtime that can read the filesystem reads it; any MCP-capable client triggers it. Same wiki, every runtime. Architectural rationale in docs/thesis/22_AUTONOMOUS_WIKI.md (and a section appended to docs/thesis/21_CROSS_RUNTIME_MEMORY.md ties the property back to the cross-runtime architecture).
File-page sections (the canonical 10)
Per-source-file pages under HYDRATE-wiki/files/ are composed of these sections, each omitted entirely when empty (the no-stubs rule):
- Purpose — LLM-summarised responsibility, with leading-comment fallback.
- API — split into Public (exported) and Private (package-internal) subsections. Both are documented because the private surface is the file's contract with its package siblings.
- How it works — LLM-narrated main flow when one is configured.
- Callers — every use of every top-level symbol, public and private, across the project.
- What can go wrong — extracted from
TODO/FIXME/XXX/HACK/BUG/KLUDGEmarkers +panic()call sites. Pure AST-grep — no LLM dependency. - Configuration — CLI flags / env vars / HTTP routes declared by the file (see below).
- Tests — detected sibling test files.
- Invariants —
MUST/Invariant/REQUIREScomment-level declarations. - Dependencies — every imported package (renamed from
Importsto match the "why each import is here" intent). - See also — sibling files sharing at least one import.
When an LLM is configured, a gap banner at the top of the page lists which canonical sections are missing or below their minimum-content threshold, with a one-line description of what should go in each.
Configuration extraction across 11 languages
A new ## Configuration section on every file page surfaces three categories of operational documentation:
- CLI flags — Go stdlib
flag.*; Pythonargparse+Click; JS/TScommander; Rustclap; Javapicocli; RubyOptionParser; SwiftArgumentParser; C/C++getopt. - Environment variables — Go
os.Getenv/os.LookupEnv; Pythonos.environ+os.getenv; JSprocess.env.X; Ruststd::env::var; JavaSystem.getenv; RubyENV[]+ENV.fetch; SwiftProcessInfo.processInfo.environment; C/C++getenv. - HTTP routes — Go
mux.HandleFunc(incl. net/http 1.22'sMETHOD /pathshape) + chi/gin; Flask + FastAPI + Django; Express + Fastify + NestJS; Rust actix + axum + rocket; Spring + JAX-RS; Rails + Sinatra; Vapor.
Plus a new project-level page 06-configuration.md that aggregates every flag, env var, and route across the whole codebase with clickable per-line source links. Answers "what does this thing read at startup?" in one place.
Project-level pages (the canonical 7)
| File | Generates from |
|---|---|
00-overview.md |
LLM summary of README (omitted without LLM) |
01-architecture.md |
cmd/ binaries + internal/ packages enumerated from disk |
02-commands.md |
Parsed Makefile targets |
03-mcp-and-integrations.md |
Detected cmd/*mcp* binaries |
04-onboarding.md |
Entry-point links + LLM-generated first-steps |
05-canon.md |
Read-only mirror of the project's pinned facts in ~/.hydrate/data.db |
06-configuration.md |
Aggregated CLI flags / env vars / HTTP routes |
Each page is omitted entirely when it would be empty.
Wiki ↔ product integration (three layers)
The wiki participates in Hydrate's prompt loop:
- Layer 1 — CLAUDE.md pointer. First curate appends a sentinel-wrapped pointer block to the project's CLAUDE.md so the LLM sees the wiki exists. Idempotent; user edits to the block prose are preserved.
- Layer 2 — MCP
wiki_pagetool.hydrate-mcpexposeswiki_page(project, path)so any MCP-capable client can fetch a single rendered page on demand. Follows redirect stubs. - Layer 3 — Retrieval injection (opt-in via
HYDRATE_WIKI_INJECT=1). Theclaude-contexthook embeds the user's prompt at submit time, runs cosine similarity over per-page embeddings (one binary.f32file per page under<wikiDir>/.embeddings/), and prepends a short excerpt of the most-relevant page toadditionalContext. Min similarity 0.30; ≤1800 chars (~450 tokens) excerpted. Fail-open.
Stable UUIDs + redirects
Every wiki page carries a id: <uuid> in its frontmatter, minted once on first render and preserved across re-renders. When a source file is renamed (same content SHA, different path), the curate worker writes a redirect stub at the old wiki path carrying the original UUID and points readers at the new path. Inbound links survive rename refactors. The MCP wiki_page tool follows redirects transparently.
Deferred to v0.6.1
- SSE live updates on
/wiki— manual Refresh covers the v0.6.0 use case. - Pandoc / BibTeX / KaTeX / Mermaid — Cortex's "write papers" angle. Open-ended; gated on pull.
- CodeMirror in-dashboard editor — read-only viewer is enough for v1.
- Symbol queries for languages beyond the v0.6.0 set of 11 — the gotreesitter registry ships 206 grammars; v0.6.0 has hand-written tree-sitter Queries for the 11 most common. Adding a new language is a small per-language change to
internal/codebaseintel/queries.go(one symbol query + one call query); contributions welcome.
Other deliberate scope reductions
hydrate wiki curateaccepts a--dbflag for parity withhydrate dehydrate's surface, but the current worker doesn't read the DB. Reserved for future wiki↔facts integration.- The Phase-6 verification suite in
siteengine-test-harnessships as a self-contained Go test (internal/wikie2e/) rather than YAML scenario manifests, because the harness's existing manifest format is heavily specialised for HTTP-API session captures and doesn't fit the "spawn binary, assert on files" shape. Coverage is equivalent: five end-to-end scenarios inmake test-wiki.
Upgrade
- macOS / Linux (Homebrew):
brew update && brew upgrade hydrate. - macOS / Linux (install script):
curl -fsSL gethydrate.dev/install | sh. - Windows: download
Hydrate.msifrom the v0.6.0 release.
After upgrade, the first Claude Code session you start in any existing Go project triggers the first wiki curate within a few minutes. Logs at ~/.hydrate/logs/auto-wiki.log. Delete ~/.hydrate/auto-wiki/<slug>.last to force an earlier re-curate.
What's where on disk
| Path | Purpose |
|---|---|
<project>/HYDRATE-wiki/ |
The wiki itself (markdown, frontmatter, lives in your repo) |
~/.hydrate/auto-wiki/<slug>.last |
Cadence marker (RFC3339 timestamp) |
~/.hydrate/auto-wiki/<slug>.lock |
Single-instance lock (released on worker exit) |
~/.hydrate/auto-wiki/<slug>.dir |
Dashboard discovery pointer (absolute wiki dir) |
~/.hydrate/logs/auto-wiki.log |
Worker stdout/stderr |