Skip to content

v0.6.0

Choose a tag to compare

@SeamusWaldron SeamusWaldron released this 27 May 08:59

Hydrate v0.6.0

Two headline features in this release:

  1. Handover-first resume.hydrate/HANDOVER.md is 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 in docs/thesis/30_HANDOVER_PRIMARY_STORE_SECONDARY.md.

  2. 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 handover CLIpath / read [--json] [--archive=FILE] / write [--stdin] [--touch] [--no-archive] / clear / list [--json] / grep <pat> / prune [--keep=N] [--older-than=DUR]. read exits 0 found / 2 absent; grep exits 0 hits / 2 no-matches (greppable).
  • Per-session archive at .hydrate/handovers/<UTC-ISO-compact>-<6hex-rand>.md, atomic copy to .hydrate/HANDOVER.md as the latest pointer. Random suffix eliminates same-second collisions (verified by 20-goroutine concurrency test).
  • /hydrate-distill template Phase 0 — heredoc piping the handover body into hydrate handover write --stdin. CLI owns the archive layout so the agent doesn't need to know about archive paths.
  • /hydrate-last template — reads .hydrate/HANDOVER.md silently 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 /clear even when the chunker over-compresses.
  • hydrate-server's /api/v1/session-resume now 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 archives
  • GET /api/v1/dashboard/handovers/entries → entries for one project
  • GET /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 internal files/ prefix stripped and .md extensions trimmed, so what you see is cmd/claude-context/main.go rather than files/cmd/claude-context/main.go.md.
  • Clicking any file renders the curated .md inline (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's frontmatter.sources chips, with the body rendered as HTML for .md files and as plain text for everything else. Path is validated against the project root (parent of HYDRATE-wiki/).
  • POST /api/v1/dashboard/reveal — opens the platform's file manager pointing at a file. open -R on macOS, explorer /select, on Windows, xdg-open <parent> on Linux. Path is validated against knownProjectRoots() (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_wiki tool.

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/gotreesitter v0.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):

  1. Purpose — LLM-summarised responsibility, with leading-comment fallback.
  2. 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.
  3. How it works — LLM-narrated main flow when one is configured.
  4. Callers — every use of every top-level symbol, public and private, across the project.
  5. What can go wrong — extracted from TODO / FIXME / XXX / HACK / BUG / KLUDGE markers + panic() call sites. Pure AST-grep — no LLM dependency.
  6. Configuration — CLI flags / env vars / HTTP routes declared by the file (see below).
  7. Tests — detected sibling test files.
  8. InvariantsMUST / Invariant / REQUIRES comment-level declarations.
  9. Dependencies — every imported package (renamed from Imports to match the "why each import is here" intent).
  10. 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.*; Python argparse + Click; JS/TS commander; Rust clap; Java picocli; Ruby OptionParser; Swift ArgumentParser; C/C++ getopt.
  • Environment variables — Go os.Getenv / os.LookupEnv; Python os.environ + os.getenv; JS process.env.X; Rust std::env::var; Java System.getenv; Ruby ENV[] + ENV.fetch; Swift ProcessInfo.processInfo.environment; C/C++ getenv.
  • HTTP routes — Go mux.HandleFunc (incl. net/http 1.22's METHOD /path shape) + 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_page tool. hydrate-mcp exposes wiki_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). The claude-context hook embeds the user's prompt at submit time, runs cosine similarity over per-page embeddings (one binary .f32 file per page under <wikiDir>/.embeddings/), and prepends a short excerpt of the most-relevant page to additionalContext. 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 curate accepts a --db flag for parity with hydrate 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-harness ships 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 in make test-wiki.

Upgrade

  • macOS / Linux (Homebrew): brew update && brew upgrade hydrate.
  • macOS / Linux (install script): curl -fsSL gethydrate.dev/install | sh.
  • Windows: download Hydrate.msi from 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