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

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:

  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 and panic() call sites. Pure AST-grep, no LLM dependency.
  6. Configuration: CLI flags, env vars, and HTTP routes declared by the file.
  7. Tests: detected sibling test files.
  8. Invariants: MUST / Invariant / REQUIRES comment-level declarations.
  9. Dependencies: every imported package, with 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 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)

FileGenerated from
00-overview.mdLLM summary of README (omitted without LLM)
01-architecture.mdcmd/ binaries and internal/ packages enumerated from disk
02-commands.mdParsed Makefile targets
03-mcp-and-integrations.mdDetected cmd/*mcp* binaries
04-onboarding.mdEntry-point links and LLM-generated first-steps
05-canon.mdRead-only mirror of the project's pinned facts in ~/.hydrate/data.db
06-configuration.mdAggregated 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.*, 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.

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_wiki tool.

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:

  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.
  2. MCP wiki_page tool: hydrate-mcp exposes wiki_page(project, path) so any MCP-capable client fetches a single rendered page on demand. Follows redirect stubs.
  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, 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

PathPurpose
<project>/HYDRATE-wiki/The wiki itself (markdown, frontmatter, in your repo)
~/.hydrate/auto-wiki/<slug>.lastCadence marker (RFC3339 timestamp)
~/.hydrate/auto-wiki/<slug>.lockSingle-instance lock (released on worker exit)
~/.hydrate/auto-wiki/<slug>.dirDashboard discovery pointer (absolute wiki dir)
~/.hydrate/logs/auto-wiki.logWorker stdout/stderr

The Files page in the dashboard is the read-only browser over this content; CLI usage is in the CLI reference.