Files: auto-generated project notes
hydrate wiki curate writes a self-maintaining set of
markdown pages under <project>/HYDRATE-wiki/,
regenerated periodically from your codebase using the LLM you
already have. The pages live in your repo, so every runtime that
can read the filesystem (Claude Code, Codex, Vibe, Cursor, Cline,
Zed, plain editors) sees the same notes. Surfaced in the dashboard
as the Files page. New in v0.6.0.
The CLI verb and on-disk folder retain the older wiki
naming (hydrate wiki curate,
HYDRATE-wiki/): internal concern. What you see in the
dashboard sidebar, and on this page, is Files.
What you get
HYDRATE-wiki/
├── 00-overview.md
├── 01-architecture.md
├── 02-commands.md
├── 03-mcp-and-integrations.md
├── 04-onboarding.md
├── 05-canon.md
├── 06-configuration.md
└── files/
├── cmd/.../*.md
└── internal/.../*.md One folder per source directory, one markdown page per source file, plus a handful of project-level pages that aggregate across the whole codebase. Each page is omitted entirely when it would be empty: this is the no-stubs rule.
File-page sections (the canonical 10)
Per-source-file pages under files/ are composed of
these sections. Empty sections are dropped:
- 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 andpanic()call sites. Pure AST-grep, no LLM dependency. - Configuration: CLI flags, env vars, and HTTP routes declared by the file.
- Tests: detected sibling test files.
- Invariants:
MUST/Invariant/REQUIREScomment-level declarations. - Dependencies: every imported package, with 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 sections are missing or below their minimum-content threshold, with a one-line description of what should go in each. When no LLM is available, pages still render with structure-only content and a "no LLM available" hint.
Project-level pages (the canonical 7)
| File | Generated from |
|---|---|
00-overview.md | LLM summary of README (omitted without LLM) |
01-architecture.md | cmd/ binaries and 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 and 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 from across the codebase |
Drift detection
Every page carries YAML frontmatter recording the SHA of every 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
Two parsing backends ship 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 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, and 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 (which is why
hydrate grew from ~23 MB in v0.5.1 to ~50 MB in
v0.6.0). Lazy loading means a grammar only consumes RAM when
actually used, so the runtime cost stays low.
Configuration extraction across 11 languages
The ## 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.
Trigger paths
- Automatic, every six hours, via
claude-session-start. Cadence marker at~/.hydrate/auto-wiki/<project-slug>.last; delete it to force an earlier re-curate. Worker logs at~/.hydrate/logs/auto-wiki.log. - Manual via
hydrate wiki curate [DIR] [--max-pages-per-cycle=N] [--dry-run]. - From the dashboard at the Files page: project picker, page list, rendered body, "Curate now" button.
- From any MCP client via the new
curate_wikitool.
A file lock at ~/.hydrate/auto-wiki/<slug>.lock
guarantees one worker per project at a time. Stale locks (older
than 2 hours) are reclaimed automatically.
Wiki + product integration (three layers)
The wiki participates in Hydrate's prompt loop in three ways:
- CLAUDE.md pointer: first curate appends a sentinel-wrapped pointer block to the project's
CLAUDE.mdso the LLM sees the wiki exists. Idempotent; user edits to the block prose are preserved. - MCP
wiki_pagetool:hydrate-mcpexposeswiki_page(project, path)so any MCP-capable client fetches a single rendered page on demand. Follows redirect stubs. - 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, capped at roughly 450 tokens. Fail-open.
Stable UUIDs and redirects
Every wiki page carries an 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.
Cross-runtime: the differentiator
Other tools in this space ship a wiki locked to a single runtime (e.g. a Claude Code plugin marketplace entry). Hydrate's wiki is plain markdown in your repo. Any runtime that reads the filesystem reads it; any MCP-capable client triggers it. Same wiki, every runtime.
What's where on disk
| Path | Purpose |
|---|---|
<project>/HYDRATE-wiki/ | The wiki itself (markdown, frontmatter, 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 |
The Files page in the dashboard is the read-only browser over this content; CLI usage is in the CLI reference.