Repowise builds a wiki for your repository at index time: a page per source
file, per selected public symbol, per subsystem, per dependency cycle, per
infrastructure file and per API surface, plus a repository overview and an
onboarding collection. It is refreshed incrementally on every commit, and it is
what get_answer, search_codebase, the CLI and the local dashboard read from.
Almost all of it is rendered from your code's structure with no model in the loop. A provider key adds prose to the subsystem layer and the top-level narrative pages. It does not switch the layer on: a repository indexed with no key gets a complete wiki, not a placeholder.
repowise init # builds the wiki as part of indexing
repowise init --no-prose # keyless and free, guaranteed no spend
repowise update # re-renders only what your commits touched
repowise generate # fill in the subsystem prose later
repowise restyle reference # re-render every page in a different voice
repowise serve # browse it at localhost:3000
repowise export --format markdown # write it out as filesPages are produced in ordered levels, most local first, so a page that quotes another is generated after it.
| Level | Page type | One per | Written by |
|---|---|---|---|
| 0 | api_contract |
API spec (OpenAPI, proto, GraphQL) or FastAPI / ASP.NET route module | structure |
| 1 | symbol_spotlight |
selected public symbol | structure |
| 2 | file_page |
eligible source file | structure |
| 3 | scc_page |
dependency cycle | structure |
| 4 | module_page |
subsystem in the concept tree | model, structure when keyless |
| 5 | flow_page |
operation walked end to end (3 to 6 per repo) | model, structure when keyless |
| 6 | repo_overview |
repository | model, structure when keyless |
| 7 | infra_page |
Dockerfile, Makefile, Terraform file or container entrypoint script | structure |
| 8 | onboarding |
slot | model, structure when keyless |
The onboarding slots are Project Overview, Getting Started, Key Concepts, How It Works, Active Landscape and Glossary. Project Overview is not generated separately, the repository overview is tagged into that slot, and Glossary is rendered from mined terms with no model in every run, keyed or not.
A flow page follows one operation, such as a CLI command, a route handler or
an MCP tool, from the function that starts it through the calls that carry it.
The operations and their steps are traced from the call graph, so a keyed and a
keyless index pick the same ones; a model explains each step, and a keyless run
lists the steps with their line spans. Every step is cited as path:start-end,
and an edit to any step's file marks the page stale.
Layers are grouping rows in the docs tree, built from provenance stamped on their members, not pages of their own. The repository overview carries the system map, a tiered diagram of who uses the system, the ways in, the server, the engine and the data store. Structure picks its boxes and arrows; a configured model only names them.
By default there is no page budget. Every page type below the concept tree is rendered from structure and costs no tokens, and the concept partition covers every production file, so rationing it would stop it being a map of the repository. Each bucket takes every candidate that clears its eligibility floor.
The one exception is opt-in and owner-chosen. max_file_pages bounds the file
bucket, highest importance first, for repositories large enough that the tail
costs more in bytes and retrieval noise than it pays back. Unset lets a size
policy decide, 0 means one page per eligible file however many that is, and a
positive value is a hard cap. It does not reduce model spend, because file pages
are rendered from structure either way.
Selection does not depend on whether a key is present: a keyed and a keyless index of the same commit agree about which files have pages.
Four page types are model-written when a provider is configured: module_page,
flow_page, repo_overview and onboarding. These pages explain how the codebase fits
together above the file level. Everything else is rendered from the parse, the
import graph and git history, and no model ever sees it.
A model-written page is not prompted with raw source. It is prompted with assembled material: parsed structure and signatures, what the subject imports and what imports it, ownership and churn signals, the significant commits from its history with merges, dependency bumps and lint-only commits filtered out, and cross-references to the pages it should link to. The result explains why instead of restating what.
repowise init never requires a key. Without one it renders the whole wiki from
structure and exits 0. Ask for it explicitly with --no-prose, which is what
free-tier, CI and air-gapped runs want.
What you give up is the subsystem prose, and semantic search until an embedder is configured. Full-text and symbol search work either way. File pages, symbol pages, hotspots, ownership, dead code, the dependency graph, code health and decision archaeology are identical.
Each page records two separate facts:
provider_nameanswers has a model written this page yet. It is what the docs tree's "not written yet" marker and the reader's upgrade affordance read. A page rendered from structure carries nomodel_name.confidenceanswers how far should a reader trust the statements. A structure-rendered page is1.0, because everything on it is extracted from the code. A model-written page is0.8: grounded in the assembled material and checked against it, but a summary of the code instead of an extraction. Nothing gates on the difference; it is reported.
The axis is trust, not completeness. A page can be thin and still be entirely
true. A 0.3 marks a page that was meant to carry prose and lost it to a
provider outage, the one state a reader cannot infer from the page itself. A
keyless run produces 1.0 pages throughout, because an index built
without a key is that shape by design.
Upgrading is in place and incremental. Neither command re-indexes: the graph and git metadata are rehydrated from SQL, and only the per-file parse and the generation you asked for run.
repowise generate # every subsystem page still unwritten
repowise generate --path src/api # under a path prefix or glob
repowise generate --stale # pages whose code changed since writing
repowise generate --all # rewrite the prose everywhere
repowise update --full # the whole wiki at oncegenerate writes the model-written pages and only those. Naming a structural
page with --page is an actionable error instead of a silent LLM re-render,
because those pages refresh on repowise update for free. Run it bare on a
terminal and it prints the wiki's state, defaults to the unwritten pages, and
ends at the normal cost confirmation.
repowise update does not rebuild the wiki. It finds the files changed since
the last sync, walks the dependency graph for the pages those changes affect,
and re-renders only those, typically a handful per commit.
Two mechanisms decide what is stale:
- Model-written pages compare a hash of the rendered prompt against the stored one. Same prompt and same model means the prior page is reused verbatim, with no tokens spent.
- Structure-rendered pages fold the subject's own hash together with a fingerprint of the renderer: the template source, the resolved style and the output language. Comparing the stored key against a freshly computed one turns a released template change into exactly one regeneration.
So a new Repowise release that edits a template re-renders every page of that type once. That is intended, not drift.
Cycle, API-contract and infra pages follow the rebuilt graph on every update: a new cycle or newly selected file gets its page, a changed infra file is re-rendered, and a page selection no longer picks is removed. A deleted file's page stays as a tombstone for 30 days, a renamed file's as a redirect.
--cascade-budget N caps how many pages a single update may regenerate from
cascading changes. It is adaptive when unset, which is what you want except on a
very large refactor commit.
Pages also carry a freshness status of fresh, stale, expired or unknown.
Expiry by age takes priority, then a source-hash mismatch marks a page stale.
A style controls the voice and density of the prose without changing the structural markdown. Headings and sections stay the same, so search, the table of contents and cross-links keep working across a style change.
| Style | Best for | What it reads like |
|---|---|---|
comprehensive |
The default. Humans and AI. | Full, narrative documentation. |
caveman |
AI agents, token budgets. | Token-condensed fragments, ~70% smaller. |
reference |
Library consumers. | API-manual: signature-dense, minimal narrative. |
tutorial |
New contributors. | Guided, beginner-friendly walkthroughs. |
List the available styles and the repo's current one:
repowise wiki-stylesAt init (full mode), pick a style with a flag or the interactive prompt:
repowise init --wiki-style cavemanThe choice is saved to .repowise/config.yaml as wiki_style:, so update
keeps regenerated pages in the same style.
Switching re-renders every page in the new voice. Use the dedicated command: it reuses the existing index and git data, so nothing is re-resolved or re-blamed.
repowise restyle referenceIn the web app, Settings > Documentation style does the same, and an individual page can be regenerated in a one-off style from its Regenerate control.
Editing
wiki_styleinconfig.yamlby hand and runningrepowise updatewill not regenerate existing pages, that path only re-scores health. Userepowise restyleto apply a style change.
Define your own under .repowise/styles/<name>/style.yaml:
# .repowise/styles/terse/style.yaml
description: Ultra-terse internal style
onboarding_condenses: true # also condense the onboarding pages
style_version: 1 # bump when you edit this file to force regen
system_note: |
Write for senior engineers who know the domain. Be extremely concise.
user_directive: |
Write in TERSE style.
- Keep every required ## heading; bodies are short fragments.
- No filler, no restating the heading, no closing summary.
- Keep code identifiers and paths verbatim.Then apply it:
repowise restyle terseA style may also ship per-page-type Jinja templates in
.repowise/styles/<name>/templates/, using the same filenames as the built-ins
(file_page.j2 and so on). They override the built-in template for the page
types you supply; anything you leave out falls back to the default.
Guard rails: style names must match [a-z0-9][a-z0-9_-]*, directive and note
text are length-bounded, and a style with neither a directive nor a note is
ignored. Built-in style names always take precedence over a custom directory of
the same name.
language in .repowise/config.yaml, or init --language <code>, sets the
natural language of the wiki. It reaches both the model-written prose and the
headings and fixed sentences of the structure-rendered pages, for the languages
that have a label catalog. A supported language without one keeps English
headings on those pages while the model-written prose is still translated, and
an unknown code falls back to English with a warning.
Code, file paths and symbol names are never translated, in any language.
Changing the language later does not retranslate existing pages. Re-run
init --force --language <code> to rebuild the wiki in the new language.
- Agents:
get_answerretrieves and quotes from it,search_codebaseranks it,get_contextpulls the page for a file or symbol. Hybrid retrieval merges SQLite full-text and vector results through Reciprocal Rank Fusion, biased by PageRank, then expands one to two hops along the imports and projected-calls graph for flow-shaped questions. Full-text works with no embedder; semantic search needs one configured. A module page's agent digest (the questions it answers, its concept index, public API and git signals) is stored beside the page body, indexed with it, and returned byget_contextasdigest_mdwithinclude=["full_doc"]. - CLI:
repowise ask,repowise search,repowise context. - Dashboard:
repowise serve, then the Docs tab. - Files:
repowise export --format markdown|html|json, written to.repowise/exportby default.
INTELLIGENCE_LAYERS.mdfor how this layer sits next to graph, git, decisions and code health.CONFIG.mdforwiki_style,language,max_file_pagesand the rest of the generation settings.CLI_REFERENCE.mdforinit,update,generate,restyle,wiki-stylesandexportin full.AUTO_SYNC.mdfor keeping the wiki fresh automatically on every commit.