# repowise documentation > repowise is an open-source (AGPL-3.0) codebase intelligence platform that indexes any repository once and serves both AI coding agents and the humans accountable for the code. For agents, it provides a queryable architecture wiki, dependency graph, git intelligence, architectural decisions, and nine MCP tools for Claude Code, Cursor, Cline, and Codex. For teams, it provides a defect-validated code-health score (cross-project ROC AUC 0.74 across 21 repos and 9 languages), change-risk analysis, dead code detection, and agent provenance tracking. The core engine is free, self-hosted, and requires no cloud account. ## Auto-sync URL: https://docs.repowise.dev/auto-sync Five ways to keep your repowise wiki current as code changes: post-commit hook, file watcher, GitHub webhook, GitLab webhook, and a polling safety net. A typical single-commit update touches 3 to 10 pages and completes in under 30 seconds. The question isn't *whether* to auto-sync; it's which method fits your workflow. Pick one (or combine them). Method Command / setup Best for Post-commit hook `repowise hook install` Solo dev, set-and-forget File watcher `repowise watch` Active iteration without committing GitHub webhook server + `REPOWISE_GITHUB_WEBHOOK_SECRET` Teams, CI/CD GitLab webhook server + `REPOWISE_GITLAB_WEBHOOK_TOKEN` Teams on GitLab Polling fallback automatic with `repowise serve` Safety net for missed webhooks ### Post-commit hook Runs `repowise update` in the background after every local commit without blocking the terminal. The hook is marker-delimited, so it coexists safely with other hooks (linters, formatters). If it doesn't fire, make sure `.git/hooks/post-commit` is executable: `chmod +x .git/hooks/post-commit`. ### File watcher Watches the working directory for file saves and triggers an update without requiring a commit. Best when you want the wiki current between commits. Changes inside `.repowise/` are ignored to prevent loops. Press `Ctrl+C` to stop. Best for short bursts, not a long-running daemon. ### GitHub webhook Self-hosted teams point GitHub at `repowise serve`'s webhook endpoint; push events trigger incremental updates. HMAC-SHA256 signature verification is mandatory. Then in GitHub: **Settings → Webhooks → Add webhook** **Payload URL**: `https://your-server.example.com/api/webhooks/github` **Secret**: same value as `REPOWISE_GITHUB_WEBHOOK_SECRET` **Events**: Push events only Successful deliveries return `200` with `{"status": "accepted"}`. Bad signatures return `401`. Check **Settings → Webhooks → Recent Deliveries** for diagnostics. ### GitLab webhook Same idea, token-based auth via the `X-Gitlab-Token` header. In GitLab: **Settings → Webhooks** **URL**: `https://your-server.example.com/api/webhooks/gitlab` **Secret token**: same value as `REPOWISE_GITLAB_WEBHOOK_TOKEN` **Trigger**: Push events Tokens are verified via constant-time comparison. ### Polling fallback When `repowise serve` is running, a background job polls registered repos every 15 minutes. If a webhook delivery fails, polling catches the missed push and triggers an update. No configuration needed. Just don't rely on this alone: it has a 15-minute lag. ### Hosted version If you're on repowise.dev, webhook setup is automatic. Installing the GitHub App registers the webhook, and pushes auto-sync the index without you doing anything. **Belt and braces**: combine the post-commit hook (local) with a GitHub webhook (server). Local commits sync instantly; pushes from other branches keep the server in sync. The polling fallback catches the rare miss. ## Contributing URL: https://docs.repowise.dev/contributing How to contribute to the OSS Repowise repo. See the CONTRIBUTING.md in the OSS repo for the full guide. Highlights: Open an issue first for non-trivial changes Run `ruff format .` and `npm run lint` before pushing Tests live under `tests/` and `packages/*/__tests__/` We label good-first-issues with `good first issue` ## Dashboard URL: https://docs.repowise.dev/dashboard The local web dashboard that reads your .repowise index and answers architecture, health, ownership and history questions without sending anything off your machine. `repowise serve` gives you a local dashboard over the index you already built. It reads the same `.repowise/wiki.db` that the CLI and the MCP server read, so nothing leaves your machine, and no view calls an LLM unless you click something that says it will (Chat, refactoring code generation, doc regeneration). `serve` starts the API and the web UI together. See Server and watch for every flag. The URL shape is `/repos//`. Every view is directly linkable, tab state included, so a link you paste into a PR lands on exactly what you were looking at. ### What works without an API key You can index a repo without a key at all (`repowise init --yes`, or `--docs deterministic` / `--index-only` to be explicit, or the index-only option in the setup wizard). Everything derived from the AST, the dependency graph, and git history works in both modes. The views that read generated pages are the difference: Needs a model or an embedder Works on any indexed repo Chat (needs a provider), semantic Search (needs an embedder) Docs, Doc freshness, Present mode, Overview, Architecture, Knowledge Graph, Code Health, Refactoring, Files, Symbols, Commits, Contributors, Decisions, Stats, Usage, Settings, all Workspace views Every indexed repo has a wiki, including one indexed without a key, so the Docs views are populated either way. What a keyless index lacks is model-written prose and semantic search: the Docs view offers to upgrade pages with `repowise generate`, and `repowise reindex` builds semantic search once an embedder is configured. Either upgrade works in place, with no re-index from scratch. See Deterministic wiki. ### The views View Path Answers Overview `/repos//overview` What is this repo, and what should I look at first? Docs `/repos//docs` How does this system work, in prose someone can read? Doc freshness `/repos//docs/coverage` Which docs still describe the code, and which have drifted? Architecture `/repos//architecture` What talks to what? Knowledge Graph `/repos//knowledge-graph` Where does this file or symbol sit in the whole system? Code Health `/repos//code-health` Which files are likely to break next, and why? Refactoring `/repos//refactoring` Given that this file is in trouble, what exactly do I change? Files `/repos//files`, `/repos//files/` What is in this file, and should I be careful with it? Symbols `/repos//symbols/` Where is this function defined, who calls it, how often has it broken? Search `/repos//search` Where is the thing I half-remember? Commits `/repos//commits` What has been happening here, and how risky was it? Contributors `/repos//owners` Who knows this code? Decisions `/repos//decisions` Why is this code shaped this way? Chat `/repos//chat` Anything, asked in plain language against the index. Stats `/repos//stats` Activity trend, punch card, size class, superlatives. Usage and savings `/repos//costs` What has indexing cost, and what has it saved? Settings `/repos//settings`, `/settings` Exclusions, generation options, sync, provider keys, MCP config. ### Overview The landing view: repo KPIs (files, symbols, entry points, dead exports, health averages), an attention panel that promotes whatever currently deserves it (declining health, a stale doc set, an alert-band file), a decisions timeline, quick actions, and a live banner while an index or generation job is running. If a job is in flight, its progress and log stream here. ### Docs The generated wiki: a page tree on the left, the rendered page in the middle with mermaid diagrams, code blocks that link into the file views, a confidence badge, a freshness indicator, backlinks, and a regenerate action for a single page. Reader personas re-filter the prose for the audience you pick. Human notes you attach to a page survive regeneration. The sidebar auto-collapses to icons here so the page gets the width, then restores when you leave. **Present mode** lives behind a button in the docs header. It turns the wiki you already generated into a full-screen, keyboard-driven presentation. Nothing is generated for it: the deck is derived synchronously from the pages already loaded, so there is no LLM call, no network round trip, and no extra cost. The button appears only when the repo has a `repo_overview` page, and the mode lives in the URL (`?present=deck` or `?present=walkthrough`) so it is shareable. **Deck** is a slide view assembled in a fixed order: a title slide from the overview page, up to two architecture-diagram slides, up to five layer slides (prose on the left, the layer's mermaid diagram on the right when it has one), up to five module slides, a "where to start" slide built from the guided tour metadata, and a closing slide. Each slide carries a freshness dot and an "open in reader" link. **Walkthrough** is the guided-reading version of the same content: one step per guided-tour stop, each with a "why this matters" callout, a longer excerpt from the target page, and a reading-time estimate. A left rail tracks finished steps and the total estimate. With no guided tour in the index, the walkthrough falls back to the deck's sections rather than showing an empty pane. Deck and Walkthrough each keep their own position, so toggling between them does not lose your place. This is the fastest way to hand a repo to a new joiner. ### Doc freshness A coverage donut, a drift banner when generated pages fall behind the commits they describe, a per-page freshness table, and a confidence-by-freshness matrix that separates "we were never sure about this page" from "we were sure and the code has since moved". Use it to decide what to regenerate instead of regenerating everything. ### Architecture Five sub-views behind `?view=`: `?view=` What you get `map` (default) The layered architecture map. `explore` The dependency-graph canvas with ELK layout, a context drawer per node, a centrality leaderboard, and detected communities. `deps` The external dependency registry. `symbols` The symbol index. `coupling` Change coupling: files that keep changing together with no import edge between them, which is the coupling static analysis cannot see. All of it is computed from the parse and git history, so it works on a keyless index. ### Knowledge Graph A continuous-zoom canvas over the full graph: repo at the top, then modules, files, and symbols as you zoom, rendered by a custom camera and culling engine so it stays smooth on large repos. Deep-link with `?focus=` to land zoomed on one node. The older `/c4` and `/zoom` URLs redirect here. ### Code Health Tabs behind `?tab=`: `?tab=` What you get `triage` (default) The health ring, the band distribution, the three co-equal KPIs (defect risk, maintainability, performance), and the lowest-scoring files. `findings` Every marker finding, filterable by dimension and severity. `hotspots` Churn-versus-complexity and churn-versus-bus-factor scatters, with the refactor quadrant tinted. `coverage` Ingested test coverage joined against risk, so untested hotspots stand out. `dead-code` Unreachable files, unused exports, and zombie packages, tiered by confidence. `impact` Blast radius for a file or a set of changed files. `security` The security findings table, by directory and by severity. Clicking any file opens the health drawer: its markers, its file signals (owners, churn, dependents), its score trend as a sparkline, and its bug history. The per-file score trend lives on the file's own Health tab and in the drawer rather than as a separate top-level tab. The scoring model is documented in Code health. ### Refactoring A board of structured plans (Extract Class, Extract Helper, Move Method, Break Cycle, Split File). Each card shows its split groups, the evidence that justifies it, its impact delta, an effort bucket, and the blast radius that has to move with it. Filter by type with `?type=`. Two actions per card: **copy-to-agent**, which produces a prompt you can hand to a coding agent, and **Generate code**, an opt-in LLM expansion into code plus a unified diff. Everything except that last button is deterministic. More in Refactoring. ### Files and Symbols Files opens on a treemap of the repo sized by code volume and colored by health band, so where the risk sits is one glance rather than a sorted table. Drill into a file for its tabs: overview, its generated doc page, health, coverage, graph neighborhood, and history. `/repos//modules/` is the same idea one level up. The symbol index (`/repos//architecture?view=symbols`) has filters for kind, hot files, and a **Bug-fixed** facet that keeps only symbols with a counted bug fix inside the window. Each row carries a fix chip when it has one. The symbol detail page and drawer show the signature, the call graph around it, modification count, and a **Bug fixes** tile. That contrast, how often a symbol changes against how often it breaks, is the part worth reading. ### Search, Commits, Contributors, Decisions Search covers full-text, symbol, and semantic search over the index, scoped to one repo or the whole workspace. Semantic results need a configured embedder; symbol and full-text search work on any index. Commits gives the commit table with a per-commit risk score, a risk distribution, a code-evolution chart, commit-category breakdowns, and AI-agent provenance badges plus their trend over time where the commits carry agent trailers. Contributors is a directory with ownership distribution, bus-factor views, and a per-person profile showing what they own and where their knowledge is concentrated. Useful before a reorg, and before assuming a file has an owner. Decisions shows architectural decisions with their evidence drawer, supersession lineage, and a decision graph. Decisions are mined from history and PR discussion, and can be confirmed, edited, or added by hand. See Decisions. ### Chat Ask questions against the indexed repo. Answers cite the pages and files they came from, an artifacts panel collects code the answer produced, and you pick the model. This is the one view that always costs LLM tokens, and it needs generated pages to retrieve over. ### Workspace views These appear only when repowise is running over a multi-repo workspace. See Workspace setup. Route What it shows `/workspace` Repo cards across the workspace with per-repo status. `/workspace/system-map` The cross-repo dependency picture, including a design-structure matrix and package dependencies. `/workspace/conformance` Where repos diverge from the shared patterns. `/workspace/contracts` API contracts extracted on the producer side matched against their consumers, so a breaking change is visible before it ships. `/workspace/co-changes` Files in different repos that keep changing in the same window. ### Keyboard Key Does `⌘K` / `Ctrl+K` Command palette: jump to a page, file, or symbol `→` `Space` `PageDown` Present mode: next slide or step `←` `PageUp` Present mode: previous `Home` `End` Present mode: first / last `Esc` Close Present mode or the open drawer The dashboard and the MCP server serve the same data from the same index. Use the dashboard when you want to look at it, and MCP when your agent needs it. ## Welcome to repowise URL: https://docs.repowise.dev Repowise turns any git repository into a queryable knowledge graph that AI coding agents (Claude Code, Cursor, Windsurf, Claude Desktop, VS Code) can reason over through ten MCP tools. Self-hosted or hosted, same engine. Your AI coding agent reads files. It doesn't know who owns them, which ones change together, which ones are dead, or why they were built the way they were. Repowise indexes your codebase into five intelligence layers and exposes them to your editor through ten precisely designed MCP tools, so your agent answers *"why does auth work this way?"* instead of *"here is what auth.ts contains."* ### Let your agent set it up Paste this into Claude Code, Cursor, Codex, or whatever you use. No API key needed, and nothing in the flow stops to ask for one. More prompts, plugin installs, and the machine-readable llms.txt endpoints are on Set up with your agent. ### The five intelligence layers ### The hosted platform The fastest way to run Repowise: sign in at repowise.dev, index a repo, done: managed indexing, push-sync, private repos via a GitHub App, and everything the managed service adds on top of the engine. ### Jump in ### Benchmarked, not hand-waved On 48 paired SWE-QA tasks from `pallets/flask`, repowise-augmented Claude Code matches baseline answer quality while being dramatically leaner: Metric (per task, mean) Baseline + repowise Δ Cost $0.1396 **$0.0890** **−36%** Wall time 41.7 s **33.9 s** **−19%** Tool calls 7.4 **3.8** **−49%** Files read 1.9 **0.2** **−89%** **32 / 48 (67%) tasks are cheaper with repowise, at parity quality.** Methodology and per-task tables: repowise-bench. ### Two ways to run it Either way, your editor connects through the same MCP protocol and sees the same ten tools. **New here?** Start with the Quickstart and you'll be querying your codebase from Claude Code in about a minute. New to MCP? The ten-tool overview explains what your agent can ask for. ### Where to find help **Discord**: discord.gg/cQVpuDB6rh **GitHub**: github.com/repowise-dev/repowise **Email**: hello\@repowise.dev **Stuck on install?** See Troubleshooting or just run `repowise doctor`. ## Licensing URL: https://docs.repowise.dev/licensing AGPL for free use; commercial licensing available. Repowise OSS is released under **AGPL-3.0**. The hosted version at `repowise.dev` runs the same code with a managed-service exemption. For commercial use that conflicts with AGPL terms (closed-source distribution, embedded redistribution), email **hello\@repowise.dev**. ## Security & data handling URL: https://docs.repowise.dev/security What Repowise processes, what it persists, what leaves your machine under each deployment mode, and how to reduce that to zero. This page is written for the person who has to sign off before Repowise touches source code. Short version: Repowise is self-hosted by default. Your source is read from disk, parsed in memory, and never persisted. The only content that leaves your infrastructure is what you send to your own LLM provider under your own key, and even that is optional. Anonymous CLI telemetry is the one outbound channel we add, it contains no code, paths, or repo names, and it has three independent off switches. Looking for the security *product* (CVE scanning, secret detection, SBOM/VEX, compliance reports)? That is a different page: Security suite. This page is about data handling and compliance posture. ### What is processed vs what is persisted This is the distinction most security reviews turn on. Repowise reads a lot more than it keeps. Artifact Processed Persisted Where Raw source code Yes, read from disk and parsed into an AST in memory **No** transient only Dependency graph (NetworkX) Yes Yes local index (`.repowise/`) Embeddings (LanceDB) Yes Yes, as non-reversible vectors local index Generated wiki pages Yes Yes local index Git metadata (commits, authors, churn, co-change) Yes Yes local index Architectural decision records Yes Yes local index Code-health scores and findings Yes Yes local index Raw source is processed transiently and never persisted. What survives an index is a structural and statistical description of the codebase plus the documentation generated from it. **On embeddings.** LanceDB stores float vectors produced by the configured embedding model. They are not encrypted source and they are not reversible back into the original text. They are still derived from your code, so treat the index directory with the same access controls as the repository itself. **Where the index lives.** In the open-source distribution, everything above sits in the `.repowise/` directory inside the repository, on the machine that ran `repowise init`. Nothing is uploaded. A commercial on-prem install swaps the local stores for Postgres (metadata) and LanceDB or pgvector (embeddings) inside your own network. ### LLM usage, BYOK, and the layers that need no model Repowise splits cleanly into layers that call an LLM and layers that do not. **Zero-LLM layers.** Graph, git, dead code, code health, change risk, the security pattern scan, and the deterministic wiki are pure local computation over tree-sitter and git data. `repowise init --docs deterministic` (or `--index-only`) builds all of them, wiki pages included, with **no outbound LLM calls at all**. The health pass in particular is deterministic Python: no model, no network. An `init` run with no provider configured takes this path by default, so a machine that has never seen an API key still produces a complete, queryable wiki. **LLM layers.** Wiki and documentation generation, chat, decision extraction, and the opt-in refactoring code-gen call a model. These are the only paths that can send code-derived content off the machine. **BYOK.** You bring your own key: Anthropic, OpenAI, Azure OpenAI in your own tenant, or a local runtime. Calls go directly from your infrastructure to the provider you configured. We never see your LLM traffic, and we never proxy it. Zero data retention applies through your provider's own policy (Anthropic's API zero-retention terms, your Azure tenant's data-handling terms, and so on), which means the retention question is settled by a contract you already hold rather than by us. **Per-repository provider choice.** The provider is configured per repo (see Configuration and Environment variables), so a sensitive repository can run fully offline while a lower-sensitivity tooling repo uses a hosted model. **Fully offline.** Ollama plus a local embedding model means **zero external API calls**: no LLM provider, no embedding provider, nothing outbound from the indexing path. Combined with telemetry disabled, Repowise makes no network calls whatsoever. ### Telemetry, stated precisely The CLI reports anonymous, opt-out usage telemetry so we can prioritize work. It is anonymous and opt-out, not absent, and we would rather you read the exact fields than take a slogan. There are two event types: `command_run` (once per CLI invocation) and `mcp_tool_call` (once per MCP tool call). **What is collected:** an anonymous envelope (`anon_id`, `session_id`, `cli_version`, `os`, `arch`, `python_version` at major.minor only, `is_ci`), plus per-event properties: the command name, a known subcommand name, flag **names** only, a status enum, an exception **class name**, and a duration. For `init` and `update`, coarse buckets describe the shape of the run (file-count bucket, top language, docs mode on/off, provider and model, embedder, pages bucket). MCP tool calls report the tool name, status, duration, and coarse enums (confidence, retrieval quality, results bucket, index-behind flag). **What is never collected:** source code or file contents, file paths or directory names, repository names, package names, symbol or function names, generated documentation text, flag values, environment-variable values, API keys or credentials, error messages or stack traces, IP addresses, usernames, hostnames, email, or anything personally identifiable. **`anon_id` is a random UUID** stored in `~/.repowise/platform.json`. It is not derived from a hostname, username, or machine identifier, so it cannot be reversed to a person. Delete the file and a new, unrelated id is generated. **Retention:** events are kept for 90 days, then deleted. Only aggregate figures are used or shared. ### Verify before you trust us Print the exact payload without sending anything: ### Three independent off switches Any one of these is sufficient. Check the current state with `repowise telemetry status` (see Other commands). Running fully offline also means nothing is sent. ### Self-hosted vs hosted: where the boundary sits Self-hosted (OSS, `pip install repowise`) Self-hosted commercial (on-prem) Hosted platform Where source is read your machine your VPC the hosted indexer Where the index lives `.repowise/` on your machine Postgres + LanceDB/pgvector in your network Repowise-operated infrastructure Who calls the LLM you, with your key you, with your key the platform, or your key Outbound from your network anonymous telemetry (disableable), your LLM provider same, plus configured integrations not applicable, you are sending code to the platform Commercial security features (CVE triage, SBOM/VEX, secret history scan, compliance reports, audit trail) not included commercial layer GA today The honest framing: several commercial security capabilities are GA on the hosted platform first. If your requirement is on-prem *and* CVE-aware dependency analysis, SBOM/VEX, or compliance reporting, that sequencing is a scoping conversation, not a checkbox. See Hosted vs self-hosted for the feature split and Teams for the workspace tier. On the hosted secret-detection feature, only a fingerprint and a redacted preview are stored, never the secret value. ### On-prem and air-gapped topology A self-hosted commercial install is a set of containers on your infrastructure. The reference topology is Kubernetes; the same containers run on Nomad or plain Docker. The open-source Docker images are a full-stack image (API plus Web UI) and a lean MCP-only image that speaks JSON-RPC over stdio, carries no Web UI, and exposes no ports. Components: **API server** (FastAPI), **indexer workers**, and **dashboard** (Next.js). **Postgres** for metadata, **LanceDB** (or pgvector) for embeddings, and an in-memory NetworkX graph. **Optional Ollama container** for fully-offline LLM use. **Webhook receivers** for GitHub Enterprise, GitLab self-managed, or Azure DevOps, configured per tracked repository. **SSO** through your existing Entra ID / Okta tenant, and **outbound integrations** configured with signed service tokens held in the Repowise secret store. **Air-gapped.** All services run inside your VPC or air-gapped network. The LLM provider and the git server sit inside the same boundary. No outbound connectivity is required in air-gapped mode. A packaged air-gapped install bundle (bundled grammars, embedding model, optional Ollama runtime) is planned, not shipped; today an air-gapped install is assembled from the containers above rather than from a single bundle. **Indexing cost profile, for capacity planning.** The graph, git, dead-code, and code-health layers build with zero LLM calls, and so does the wiki when you run keyless (`repowise init --yes --docs deterministic`, see the Quickstart). One-time model-written wiki generation scales with repo size and can run in the background. Incremental updates after each commit complete in under 30 seconds. ### Compliance posture **Repowise holds no security certifications.** We do not claim SOC 2, ISO 27001, or any other audited attestation, and you should not accept a vendor answer that implies otherwise without a report to read. What does exist: **PCI-DSS 4.0 and SOC 2 control-coverage reports** are GA on the hosted platform (Teams+). They are derived from live security findings with per-control evidence drill-ins and JSON / Markdown export. They are framed in-product and in every export as coverage signals, not an audit and not a certification. They certify nothing. Controls that automated findings cannot evidence are marked for manual attestation rather than silently passed. **ISO 27001 Annex A** and **GDPR / data-residency mappings** are on the extended roadmap, not shipped. **SBOM (CycloneDX 1.6) with per-dependency license detection, plus VEX export** is GA on the hosted platform (Pro+). SPDX and cross-format conversion are roadmap. **Audit trail** covering the hosted security surface (scans, vulnerability and secret views, SBOM/VEX exports, compliance views, finding-status changes, and MCP reads by AI agents) is insert-only with user, IP, and timestamp, exportable to JSON/CSV, with an opt-in signed-webhook stream. Coverage beyond the security surface is in development. **Audit rights.** The commercial license grants you the right to audit Repowise's own security and compliance practices. **IP indemnification and a defensive patent grant** are GA under the commercial license. **Licensing, since it usually shares a review cycle:** the core engine is AGPL-3.0, free for individuals, teams, and companies using it internally. A commercial license removes the AGPL obligations for embedding Repowise in your own product and adds the layer above. Details on Licensing. ### Questions your security team will ask Question Answer Does our source code leave our infrastructure? Not in the self-hosted distribution. Code is read from disk and parsed in memory. The only path that can send code-derived content out is the LLM call for documentation, chat, and decision extraction, and that goes to the provider you configured with your key. Indexing with no provider (`--docs deterministic`) and offline mode remove it entirely, and you still get a full wiki. Is raw source stored anywhere? No. Raw source is processed transiently and never persisted. The index holds the graph, embeddings, wiki pages, git metadata, decisions, and health data. Can the embeddings be reversed back into our code? They are non-reversible vectors, not encrypted source. They are still derived from your code, so protect the index directory like the repo. Can we run with no network access at all? Yes. Ollama plus a local embedding model gives zero external API calls; disable telemetry and the process makes no outbound requests. In air-gapped mode the LLM provider and git server sit inside your boundary. Do you see our LLM API traffic? No. BYOK calls go directly from your infrastructure to your provider. We do not proxy them. What is your data retention on LLM prompts? Governed by your own provider contract (for example Anthropic's API zero-retention policy), not by us. What telemetry is sent, and can we turn it off? Anonymous command names and coarse environment only, with no code, paths, repo names, flag values, IPs, or identifiers. Disable via `repowise telemetry disable`, `DO_NOT_TRACK=1`, `REPOWISE_TELEMETRY_DISABLED=1`, or by running offline. Verify the exact payload with `REPOWISE_TELEMETRY_DEBUG=1`. How long is telemetry retained? 90 days, then deleted. Only aggregates are used. Can telemetry be tied back to a user or a repo? No. `anon_id` is a random UUID in `~/.repowise/platform.json`, not derived from any machine or user identifier, and no repo-identifying field is sent. Are you SOC 2 or ISO 27001 certified? No. We publish PCI-DSS 4.0 and SOC 2 **control-coverage reports** on the hosted platform, explicitly labeled as coverage signals rather than an audit or certification. ISO 27001 Annex A mapping is roadmap. Can we deploy on-prem or air-gapped? Yes. Containerized API, indexer workers, and dashboard, backed by Postgres and LanceDB/pgvector, with optional Ollama. No outbound connectivity is required in air-gapped mode. A single packaged air-gapped bundle is planned, not shipped. Do you support SSO and SCIM? SAML / OIDC SSO (Okta, Entra ID, Auth0, Google Workspace, generic SAML 2.0) and SCIM provisioning are rolling out commercially. RBAC and multi-tenant are planned. Is there an audit log? On the hosted platform, insert-only, covering the security surface, with user, IP, and timestamp, JSON/CSV export, and an opt-in signed-webhook stream. Broader coverage is in development. Do you store secrets you find? Only a fingerprint and a redacted preview. Never the secret value. What does the MCP server expose to an AI agent? Read-only query tools over the local index. The lean MCP container exposes no ports and speaks stdio only. What license are we accepting? AGPL-3.0 for the OSS engine, free for internal use. A commercial license is required to embed Repowise in a product without AGPL obligations. Who do we contact for a security review? security\@repowise.dev. Commercial scoping: hello\@repowise.dev. ### Reporting a vulnerability Send it to security\@repowise.dev. Please include reproduction steps and the affected version (`repowise --version`). ## Upgrading URL: https://docs.repowise.dev/upgrading Upgrade the repowise package, run repowise update, and your existing index keeps working. No reindex in the normal case; a full reindex is only ever recommended, never forced. repowise is built so that upgrading is painless: **upgrade the package, run `repowise update`, and your existing index keeps working.** A full reindex is only ever *recommended* for a genuinely breaking change, never forced, and repowise tells you exactly when and how. ### The short version That's it. No reindex in the normal case. ### What happens on upgrade When you run `repowise update` (or `repowise serve`) after upgrading, repowise: **Reads your store's format version** and compares it to the running build. The on-disk store records which version wrote it, so repowise knows exactly what, if anything, an upgrade needs. **Applies any automatic, no-cost adjustments in place.** New database columns are back-filled automatically. If your embedding model changed, vectors are re-embedded for you with **no LLM calls**. You don't run anything. **Keeps your parse cache warm.** Ordinary releases do not invalidate cached work, so updates stay fast across releases. **Shows you what changed.** A short "what's new" summary appears for the versions you crossed, and `repowise whats-new` shows release notes any time. The dashboard surfaces a dismissible "update available" banner and a what's-new view. ### When a reindex is recommended Rarely, a release changes the store format in a way an in-place migration can't cover. When that happens repowise **keeps your existing index working** and shows a clear notice with the exact command, for example: It is a recommendation, not a requirement. Nothing is wiped until you choose to run it. You can keep using the current index and reindex when convenient. ### Checking your version **CLI:** `repowise --version`, or `repowise doctor` for an update check with the right upgrade command for your install method. **Dashboard:** the version is shown in the sidebar footer, with a dot when a newer release is available. ### See also `repowise whats-new`: release notes since the version you last viewed. The full release history lives on PyPI. Prefer not to manage upgrades at all? The hosted version always runs the latest engine. ## Git worktrees URL: https://docs.repowise.dev/worktrees Index a linked git worktree without re-indexing from scratch, by seeding from the base checkout and catching up incrementally. Run `repowise init` or `repowise update` inside a fresh `git worktree` and it just works. No flags, no path arguments, no second full index. repowise notices the directory is a linked worktree, copies the base checkout's `.repowise/` index, and then runs an incremental update so only the files that differ on your branch get re-processed. You get a one-line notice when it happens: The base checkout is derived from git's own metadata, so you never pass a path. That makes the path safe for automation: a post-commit hook or a coding agent running `repowise update` inside an unindexed worktree gets seed-then-update instead of an error. The seeded index belongs to the worktree. The copied database is re-pointed at the worktree, so later updates, searches, and MCP queries stay coherent. Deleting the worktree deletes its index along with it, and the base checkout is never modified. ### When seeding is skipped Auto-seeding fires only when all four of these hold. Otherwise repowise falls back to a normal full init and prints a one-line notice explaining why: The directory is a linked worktree (its `.git` is a file pointing into the base checkout). The worktree has no `.repowise/state.json` yet, so an already-indexed worktree is left alone. The base checkout has a healthy index (`state.json` plus `wiki.db`). Base and worktree share the same initial commit, and the base's last synced commit is an ancestor of the worktree's HEAD. ### Overrides Flag Effect `--no-seed` Force a cold full init inside a worktree, skipping auto-detection entirely. `--seed-from ` Seed from an explicit checkout instead of the auto-detected base. Useful for unusual layouts, such as seeding one full clone from another. All the same validations apply. `--seed-from` also works outside worktrees: any two checkouts of the same repository qualify, as long as they share history. ### Workspaces `--seed-from` maps workspace members by relative path, so seeding a workspace root from another workspace root seeds each member repo from its counterpart. Auto-detection currently applies to single-repo worktrees. Workspace-member auto-seeding is planned but not shipped yet. See Workspace setup for the multi-repo side of things. ### Troubleshooting Message What it means `does not share the same initial commit` The seed source is an unrelated repository, or a shallow clone whose history was truncated. Run a full `repowise init` instead. `is not an ancestor of worktree HEAD` The base's index was built on a branch that has diverged from the worktree's branch. Run `repowise update` in the base checkout, or let it fall through to a full init. `missing .repowise state/db` The base checkout was never indexed, or was indexed with a version that predates the current store layout. Index the base first, and worktrees created afterwards seed instantly. ## Decisions: capture, list, govern URL: https://docs.repowise.dev/cli/decision Record architectural decisions so the why survives the team. Mine git history for proposals, confirm or dismiss them, deprecate stale ones, and check decision health. Decisions in repowise are linked to graph nodes, surfaced via `get_why`, and tracked for staleness as code evolves. Three sources feed them: git archaeology (auto-proposed), inline `# DECISION:` markers in source, and the CLI commands below. ### `repowise decision add` Interactively capture a new decision. Prompts for title, context, decision, rationale, alternatives, consequences, affected files, and tags. ### `repowise decision list` List decision records. By default shows everything; flags filter the view. ### `repowise decision show` Show full details of one decision. ### `repowise decision confirm` Confirm a proposed decision, setting status to `active`. ### `repowise decision deprecate` Deprecate an active decision. Optionally link the decision that replaces it. ### `repowise decision dismiss` Dismiss (delete) a proposed decision. Requires confirmation. ### `repowise decision health` The dashboard view: stale decisions, proposed-awaiting-review, ungoverned hotspots. The same data is available to your AI agent through `get_why()` (no arguments); that's the agent-facing equivalent of this command. ## Distill: compact command output URL: https://docs.repowise.dev/cli/distill Run noisy commands through repowise distill for an errors-first, fully reversible rendering that cuts 60 to 90% of the tokens on tests, builds, git, and searches, with zero error-line loss. Most of what an AI coding agent reads from a shell command is noise: 300 lines of passing tests around 4 failures, full commit bodies for "what changed recently". **Distill** compresses that output before the agent reads it: errors-first, structure preserved, and every omission reversible. It's a capability built *on* the intelligence layers (symbol bounds, graph centrality, hotspots decide what to keep), not a layer of its own. **Guarantees**, enforced by the engine: Every error/failure-classified line in the raw output survives. Raw output is stored *before* any marker renders, so `repowise expand` always round-trips it. Any filter problem falls back to the raw output, unchanged. Output is only distilled when it actually gets smaller (net-positive guard); small outputs pass through untouched. Exit codes are preserved, so it's a drop-in wrapper. Measured on a public OSS repo (paired runs, one per command): Command Raw → distilled tokens Saved `pytest -q` (11 failures) 3,374 → 1,317 **61%**, all 11 failure lines preserved `git log -50` 3,064 → 331 **89%** `git diff` (30 commits) 62,833 → 8,635 **86%** ### `repowise distill ` Run a command and print the compact rendering. Nine content filters cover test runs (pytest, jest, vitest, cargo, go), builds (npm, tsc, cargo, go), linters (eslint/biome, ruff/flake8/mypy, clippy, golangci-lint), `git status`/`log`/`diff`, grep/rg floods, file listings, and generic logs. The lint filter keeps every error verbatim and groups warnings by rule id with counts and `file:line` anchors, the shape that compresses best on the output agents run most. Dropped content is stored in `.repowise/omissions/` and referenced by an inline marker: ### `repowise expand REF` Restore the original output behind a marker. Accepts a bare 12-hex ref or a pasted whole marker. The omission store is durable across sessions (an agent resuming work tomorrow can still expand yesterday's markers), pruned by TTL + size cap (7 days / 50 MB by default, configurable). ### The command-rewrite hook (Claude Code + Codex) Opt-in. A PreToolUse hook rewrites noisy agent commands (`pytest -x` → `repowise distill pytest -x`) **pending your approval**: the default posture is `ask`, so the modified command is shown before it runs. The hook covers both Claude Code shell tools (Bash and, on Windows, PowerShell) and never rewrites pipes, redirections, compound commands, watch modes, PowerShell-native constructs (`Verb-Noun` cmdlets, `&` invocations, aliases like `ls` that don't mean their unix namesakes), or anything in a repo that hasn't opted into repowise. Declining the `init` prompt gates the repo off in config, so a hook installed globally from another repo stays inert. `repowise init` also adds an "Output Distillation" section to the managed `CLAUDE.md`, so any agent that runs shell commands prefers `repowise distill ` voluntarily, hook or no hook. **The allowlist trap.** A rewrite changes the command string, so a Claude Code permission rule you already had, say `Bash(git diff:*)`, no longer matches the rewritten `repowise distill git diff …`, and the prompt comes back for commands you'd already allowed. `repowise hook rewrite install` offers to seed `Bash(repowise distill:*)` / `PowerShell(repowise distill:*)` allow rules (or pass `--allow-rule` / `--no-allow-rule` non-interactively). The rule only stops *double*-asking. `repowise distill` runs the wrapped command unchanged and never widens what it can do. ### Codex When `~/.codex` exists, `install` also covers the Codex CLI, with two caveats its hook protocol imposes: Codex applies a PreToolUse command rewrite only from **version 0.137**; on older builds the hook entry is skipped (a rewrite response would error on every shell call). `repowise hook rewrite status` reports what your build can do. Codex has **no ask-with-mutation**: a rewrite can only be auto-allowed, never shown for approval. So under Codex, rewrites fire **only for command families you set to `permission: allow`**; `ask` families always pass through unchanged. The hook entry lands in `~/.codex/hooks.json` (run `/hooks` inside Codex to review and trust it). Independently of any hook, `install` maintains a marker-managed "Output Distillation" section in the repo's `AGENTS.md` that works on every Codex version; `uninstall` removes it and restores your file byte-for-byte. ### `repowise saved [PATH]` Report tokens (and estimated dollars) saved by `repowise distill`: direct invocations and hook rewrites. ### Missed savings `--missed` is the adoption feedback loop: it scans your local Claude Code transcripts for shell commands in this repo that were **not** routed through `repowise distill`, classifies each with the same router the engine uses, and estimates the foregone savings using each filter's *conservative* fixture floor; the estimate undersells on purpose. Plain `repowise saved` appends a one-line summary when there's anything to report. The scan is read-only, best-effort, and entirely local: commands are read from your own transcript directory (`~/.claude/projects/…`); nothing leaves the machine. The dashboard mirrors all of this: the Costs page's *Cache & savings* tab shows a Distill savings card with the same rollup plus the missed-savings secondary stat. The savings ledger covers the distill command/hook path only. MCP response truncation is not counted: those responses were always budget-capped, so nothing was "saved" relative to before. (Truncated MCP content is still recoverable: see `get_symbol` omission refs.) ### `repowise corrections [PATH]` The same transcript reader, pointed at a different waste: commands the agent got *wrong* and then fixed. The scan finds consecutive runs of the same base command where the first failed and a later variant succeeded, then classifies the fumble: wrong tool (bare `python` vs the venv interpreter), wrong path, unknown flag, missing argument. It reports the recurring rules. Classification is precision-first: apart from the structural wrong-tool case, a rule only forms when the error text actually names the dropped flag or path; a red-green dev loop re-running tests with different selections never becomes a "correction". Wrong-path rules consult the symbol index when available and note where the corrected target actually lives. `--write` maintains a short **"Known command corrections"** block (most-frequent rules first, capped at 10 lines) between managed markers in the repo's `CLAUDE.md` (and `AGENTS.md` when one exists), so the next agent session is told up front. Re-running refreshes the block in place; content outside the markers is never touched. The same privacy contract as the missed scan applies: read-only, entirely local. ### Configuration The `distill:` block in `.repowise/config.yaml`: `repowise doctor` validates the block, reports the omission store's size against its cap, and shows whether the rewrite hook is installed. ### Skeletons: the read-side counterpart For structure-level questions about a large indexed file, ask MCP for a **skeleton** instead of reading the whole file: every signature, the imports, and the bodies of only the most central symbols, typically \~15% of the full file's tokens, sliced from persisted symbol bounds with zero query-time parsing. After a large `Read`, the PostToolUse hook nudges the agent with the skeleton's cost (once per file per session), warns when a re-read follows an edit, and digests grep floods by graph centrality. See `get_context`. ## Code health: health, risk URL: https://docs.repowise.dev/cli/health repowise health scores every file from deterministic markers across three signals (defect risk, maintainability, performance); repowise risk scores the defect risk of a commit or diff range. Both are zero-LLM and run in seconds. ### `repowise health` Compute per-file code-health scores from deterministic markers (McCabe complexity, nesting, brain methods, LCOM4 cohesion, god classes, native clone detection, untested hotspots, coverage gradient, git-behavioural risk, and static performance risk), surfaced as three signals: defect risk, maintainability, and performance. Zero LLM calls, just pure Python over tree-sitter + git data. Coverage is ingested separately with `repowise coverage add `, and `repowise health` automatically folds in whatever coverage you have already ingested, no flag needed. `coverage add` also builds a per-test test-to-code map when the report carries contexts (a coverage.py `.coverage`, or `coverage run --contexts=test`). `repowise init` and `repowise update` populate the health tables automatically, no separate step needed. `repowise status` prints a one-line summary: Coverage markers (`untested_hotspot`, `coverage_gap`, `coverage_gradient`) only fire once you've ingested a report with `repowise coverage add`. Per-file marker overrides live in `.repowise/health-rules.json`. `--refactoring-targets` emits structured, graph-aware fix plans. See Refactoring intelligence. ### `repowise risk` Just-in-time **change-risk** scoring for a commit or diff range. Scores the defect risk of a change from the same calibrated signals the health layer uses. No LLM calls, and it works without `repowise init` (pure git + learned constants). The revision defaults to `HEAD`; pass a `base..head` range to score a whole branch or PR as one change. The headline is **repo-relative**: the change's percentile and review priority (`Below typical` / `Typical` / `Elevated`) within the repo's own recent commits, sampled live. The raw 0 to 10 model score is still shown, but as a secondary, corpus-anchored number. Use it in a pre-push hook or CI step to flag high-risk changes before review. For agentic workflows, `get_risk` exposes the same signals per file plus PR blast-radius analysis. ## Hooks: auto-sync on commit URL: https://docs.repowise.dev/cli/hook Install, check, and remove the post-commit git hook that keeps the repowise wiki current after every commit. The post-commit hook is the most popular auto-sync method. It runs `repowise update` after every successful commit, typically 3 to 10 pages in under 30 seconds. Other sync options (file watcher, GitHub webhook, polling) live in Auto-sync. ### `repowise hook install` Install the post-commit hook in the current repo (or every repo in a workspace). ### `repowise hook uninstall` Remove the repowise post-commit hook. ### `repowise hook status` Check whether the post-commit hook is installed. The hook is non-invasive: it appends to any existing `post-commit` hook rather than overwriting. `hook uninstall` removes only the repowise lines. ### `repowise hook rewrite install|uninstall|status` A separate, **opt-in** agent hook (Claude Code + Codex PreToolUse) that rewrites noisy agent commands (tests, builds, lint runs, `git status`/`log`/`diff`, searches, listings) to `repowise distill `, pending your approval, so the agent sees a compact errors-first rendering. Covers both Claude Code shell tools (Bash and, on Windows, PowerShell). `install` also re-enables the current repo's `distill.commands` config if a prior `repowise init` opt-out had gated it off; `uninstall` removes the global hook entries plus the repo's AGENTS.md awareness section and leaves per-repo config untouched. Per-repo posture (`permission: ask | allow`, per-family overrides) lives under `distill.commands` in `.repowise/config.yaml`. When `~/.codex` exists, `install` also writes a Codex hook entry to `~/.codex/hooks.json` (Codex ≥ 0.137 only) and maintains an "Output Distillation" section in the repo's `AGENTS.md` that works without any hook. Codex cannot show a rewritten command for approval, so there rewrites fire only for families set to `permission: allow`; `status` reports exactly what your build supports. Full guide: Distill. ## Indexing: init, update, reindex URL: https://docs.repowise.dev/cli/indexing The three commands that build and maintain repowise's intelligence layers. init parses everything from scratch, update is incremental on each commit, reindex rebuilds the vector store without re-running the LLM. ### `repowise init` Generate the wiki for a codebase. Runs full AST parsing, graph analysis, git history indexing, dead-code detection, and page generation. `init` never requires an API key. With a provider resolvable it writes the wiki with a model; without one it renders the whole wiki from the parsed structure and exits 0. See Deterministic wiki. **Cost gate.** Before any tokens are spent, `init` shows the estimate and asks. It never prompts when stdin is not a terminal: it auto-declines, keeps the index it already built, and renders the wiki from structure instead. The default answer is Yes up to $25 and flips to No above that, because Enter-through approving a bill that size is a footgun. **Unanswerable prompts do not end the run.** If the first interactive prompt reads EOF, which is what happens when an agent pipes stdin, `init` prints a notice and continues with defaults rather than aborting. **The canonical non-interactive command is `repowise init --yes`.** It needs no key, spends nothing without a provider configured, and exits 0. Add `--docs deterministic` to guarantee no spend even when a key happens to be present in the environment. This is what agents and CI should run. The graph, git, dead-code, and code-health layers build in minutes with **zero LLM calls**, and so does the wiki when you run keyless. The one-time cost is the model-written documentation layer, which scales with repo size and can run in the background. After that, each commit-triggered `update` takes under 30 seconds. Interrupted a run? Re-run with `--resume` to pick up from the last checkpoint. ### `repowise update` Incremental update for files changed since the last sync. Detects changed files via `git diff`, re-parses them, rebuilds the affected slice of the dependency graph, and regenerates the affected pages. A typical single-commit update touches 3 to 10 pages in under 30 seconds. `--full` is also the wholesale upgrade from a structure-rendered wiki to a model-written one. For a slice at a time, use `repowise generate` below. **After a package upgrade**, `repowise update` picks up the new version against your existing index (no reindex in the normal case) and shows a short "what's new" panel for the versions you crossed. It also prints a one-line, non-blocking notice when a newer release is available. See Upgrading for the full flow. ### `repowise generate` Write wiki pages with a model, on demand. This is the upgrade path for a repo indexed without a key: it turns the structure-rendered pages into model-written prose, one page, one directory, a ranked slice, or the whole wiki at a time, each behind a cost estimate. It also fills in the template tail a budgeted `init` leaves behind, and rewrites already-written pages. It reuses the persisted index. The graph and git metadata are rehydrated from SQL, so only the per-file parse and the generation for the pages you selected run. A provider is required here, and a missing one is an actionable error naming the key-setup path. Selection comes in two philosophies and they do not mix. *Explicit* names exactly which pages (`--unwritten` / `--all` / `--stale` / `--path` / `--page`, combined as a union). *Ranked* writes the most important pages by the same ranking `init` uses (`--coverage` / `--top`). Run `repowise generate` with no selection flag on a terminal and it opens a chooser rather than writing everything: it prints the wiki's state, then the same coverage menu `init` uses with page counts and cost per tier, and ends at the normal cost confirm. A large repo is never one keystroke away from writing every page. Piped runs, `--yes`, and flagged runs stay non-interactive. **Cascade.** Regenerating a file page makes the pages that summarize it drift: its module, cycle and layer pages, plus the repo overview, architecture and onboarding pages. `--cascade none` marks them stale, `dependents` (the default) also regenerates the module, SCC and layer pages, and `full` leaves nothing stale. The cost estimate includes the cascade fallout, so it does not under-quote. ### `repowise reindex` Rebuild the vector search index from existing wiki pages. No LLM calls, only embedding API calls. Fast and cheap. Use when you switch embedders or suspect FTS/vector drift. ## Other commands URL: https://docs.repowise.dev/cli/other One-shot utilities: costs, coverage, dead-code, doctor, export, generate-claude-md, telemetry, login/logout/whoami, augment. ### `repowise costs` LLM cost history. Aggregates calls made during `init` and `update`. ### `repowise coverage` Ingest and inspect test-coverage reports. Coverage is auto-discovered and ingested during `init` / `update`; this group is the manual path, point it at a report (or let it auto-discover one) to populate per-file line/branch coverage, which clears `untested_hotspot` findings for tested files. ### `repowise dead-code` Detect unused code via the dependency graph. No LLM calls. The agent-facing equivalent is `get_dead_code`. ### `repowise doctor` Health check. Validates: git repo, `.repowise/` directory, database, `state.json`, provider config, stale pages, and store consistency (SQL/vector/FTS sync). **First port of call when something looks wrong.** `--repair` fixes the common mismatches automatically. ### CLI version check `doctor` also prints a best-effort `CLI version` row that compares your installed CLI against the latest release on PyPI. When an update is available it shows the right upgrade command for your install method (`uv tool upgrade repowise`, `pipx upgrade repowise`, or `python -m pip install -U repowise`). It surfaces both the `repowise` resolved on your `PATH` and the command that launched the current process, since these can differ, which is useful when an MCP client is running a stale executable. This row is **advisory only**: it never updates anything automatically, never fails `doctor` when PyPI is unreachable, and an unparsable latest version is reported as "unknown" rather than a false "up to date". After upgrading, **restart Claude/Codex/Cursor or any MCP client** so it picks up the new executable. ### `repowise whats-new` Show release notes for repowise versions you haven't seen yet. By default it lists releases newer than the last one you viewed, then records the current version as seen. Works **offline** from the changelog bundled with the install. `repowise update` shows a short "what's new" panel automatically after you upgrade to a newer version, and both `update` and `serve` print a one-line, non-blocking notice when a newer release is available. See Upgrading for the full upgrade flow. ### `repowise export` Export wiki pages to files. ### `repowise generate-claude-md` Regenerate `CLAUDE.md` from the index. Two-section file: a custom section above the markers (never modified) and the repowise-managed section (auto-updated). ### `repowise telemetry` Inspect and control anonymous, opt-out usage telemetry. ### `repowise login` Sign in to your hosted repowise.dev account. Unrelated to LLM provider keys (`--provider`/`--model` elsewhere). This adds the hosted layer: indexed repos on repowise.dev, reindex from local tools, and account status in `doctor`. Every local feature works without signing in. Sign-in is browser-based OAuth with PKCE by default: the command opens the hosted consent page and stores tokens at `~/.repowise/credentials.json`. ### `repowise logout` Sign out of your Repowise account on this machine (best-effort server-side revocation, local credentials always removed). ### `repowise whoami` Show the Repowise account this machine is signed in to. ### `repowise augment` Internal hook command. Runs as a Claude Code `PreToolUse` / `PostToolUse` hook to enrich `Grep` and `Glob` calls with related files, top symbols, importers, and dependencies. Detects git commits and notifies when the wiki is stale. Don't invoke `augment` directly. `repowise init` wires it into `~/.claude/settings.json` automatically. ## CLI overview URL: https://docs.repowise.dev/cli/overview All `repowise` commands at a glance. Command Purpose `init` Full wiki generation for a repository `update` Incremental wiki regeneration from new commits `reindex` Rebuild vector search index from existing pages `serve` Start API server + web UI `mcp` Start MCP server for editor integration `search` Semantic search over the wiki `status` Show wiki sync state + statistics `costs` Estimate LLM costs for generation `distill` Run a command, print a compact errors-first rendering (guide) `expand` Restore output behind a `[repowise#]` omission marker `saved` Tokens & dollars saved by distillation (`--missed` for foregone savings) `corrections` Recurring fail→fixed command fumbles mined from agent transcripts `workspace` Manage multi-repo workspaces `decision` Manage architectural decision records `hook` Manage post-commit git hooks + the distill rewrite hook `watch` Auto-sync wiki on file changes `augment` Enrich Claude Code tool calls with graph context `export` Export wiki as markdown / json `generate-claude-md` Generate `CLAUDE.md` from the wiki `dead-code` List unused code `doctor` Health checks on wiki setup `health` Score every file across defect risk, maintainability, and performance (guide) `risk` Score the defect risk of a commit or diff range (guide) `coverage` Ingest and inspect test-coverage reports `impacted-tests` List the tests a diff actually exercises `restyle` Switch wiki style and regenerate every page in the new voice `wiki-styles` List available wiki styles `whats-new` Show release notes since you last looked `telemetry` Inspect/control anonymous opt-out usage telemetry `login` / `logout` / `whoami` Hosted repowise.dev account sign-in and status `delete` Delete a repo's stored index (not source files) Each command is documented in full on the pages in this section. ## Query: search, status URL: https://docs.repowise.dev/cli/query Ask questions and check sync state from the terminal without involving an editor. ### `repowise search` Search the wiki by keyword, meaning, or symbol name. Modes: **fulltext**: keyword match (SQLite FTS). **semantic**: meaning-based (LanceDB vector search, falls back to FTS). **symbol**: symbol name match. There is no `repowise query` command. For question answering and synthesized explanations (not keyword lookup), use the MCP `get_answer` tool from your editor, or the **Chat** tab in the web UI (`repowise serve`). ### `repowise status` Show the wiki's sync state and page statistics: last sync commit, total pages, provider/model, token usage, and a per-type page breakdown. In workspace mode, the table includes a **Docs** column with each repo's page count and a per-repo docs-status block listing skip reasons and the exact remediation command. ## Server & watch: serve, watch, mcp URL: https://docs.repowise.dev/cli/server Run the repowise API and dashboard, auto-update on file save, or expose the MCP server directly to an editor. ### `repowise serve` Start the API server **and** the local web dashboard. The Next.js UI is downloaded and cached on first run (\~50 MB). Use `--no-ui` for API-only mode. The web UI needs Node >= 20; without it, `serve` falls back to API-only. The dashboard exposes the chat, graph view, hotspots, ownership, dead code, generated wiki, decision records, and cost tracking. It also shows the running version in the sidebar footer, a dismissible "update available" banner, and a what's-new view. `serve` prints a one-line, non-blocking notice when a newer release is available. See Upgrading for the full upgrade flow. ### `repowise watch` Filesystem watcher that triggers `update` on file changes. Debounced: several rapid edits collapse into a single update cycle. For passive auto-sync, prefer the post-commit hook. `watch` is best when you're actively coding and want the wiki current between commits. ### `repowise mcp` Start the MCP server for editor integration. Exposes the nine flagship tools plus `list_repos` and `generate_refactoring_code` by default. Supports `stdio` (Claude Code, Cursor, Cline), `streamable-http` (HTTP clients), and `sse` (legacy). `repowise init` writes a working `.mcp.json` for you, so you usually don't run this command directly; your editor spawns it. ## Workspace: multi-repo commands URL: https://docs.repowise.dev/cli/workspace Manage repos in a repowise workspace: list, add, remove, scan, and pick the default. A **workspace** is a parent directory containing several git repos. Indexing them together unlocks cross-repo co-changes, API contract matching, and federated MCP queries. See Workspace setup for the concept. ### `repowise workspace list` Show all repos in the workspace with their indexing status. ### `repowise workspace add` Add a repo to the workspace. PATH can be relative or absolute. ### `repowise workspace remove` Remove a repo from the workspace config. The repo's `.repowise/` directory is preserved on disk; only the workspace entry is dropped. ### `repowise workspace scan` Scan the workspace root for new git repos not yet in the config. ### `repowise workspace set-default` Change the default (primary) repo. The default is what tools target when you omit `repo=` in MCP calls or don't pass `--repo` to the CLI. ### `repowise workspace diagnostics` Explain the cross-repo contract link count: per-repo provider and consumer counts, unmatched consumers grouped by reason, and orphan providers. See Extraction diagnostics. ### `repowise workspace check` Architecture lint: check the declared `conformance:` rules against the system graph and detect dependency cycles. Exits non-zero on any finding, so it gates CI. See Architecture conformance. ### `repowise workspace metrics` Architecture-complexity metrics: propagation cost, the cyclic core, per-service roles, and a deterministic 1-10 architecture score. See Architecture metrics. Most workspace-aware operations live on other commands: `repowise update --workspace`, `repowise watch -w`, `repowise hook install --workspace`, `repowise generate-claude-md -w`. ## Set up with your agent URL: https://docs.repowise.dev/getting-started/for-agents Hand this page to Claude Code, Cursor, Codex, or any coding agent and it can install repowise, index the repo, and wire up MCP on its own. Includes copy-pasteable prompts, the Claude Code plugin, slash commands, skills, and machine-readable docs endpoints. You do not have to set repowise up by hand. Your coding agent can do it, and the whole flow is designed so it can: no API key is required, nothing blocks on an interactive prompt, and every step exits 0 or tells you exactly what to run next. ### Give this to your agent Paste this into Claude Code, Cursor, Codex, or whatever you use. It is written for an agent to follow start to finish. **The one command that matters is `repowise init --yes`.** It never requires a key, never prompts when stdin is not a terminal, and produces a full wiki either way. If you want a hard guarantee that the run spends nothing even when a key happens to be in the environment, use `repowise init --yes --docs deterministic`. ### Shorter version If the agent already has repowise installed and you just want the repo indexed: ### If you want the model-written wiki That order matters: the free index answers "is this useful on my codebase" before anything is spent. See Deterministic wiki. ### Install the plugin The fullest setup is the plugin. One install wires the MCP server, six auto-activating skills, ten slash commands, and the context hooks together: There is a Codex plugin too. Both are covered in Agent plugins, including what each skill activates on and what the hooks do. If you only want the MCP server and none of the rest: Or commit a project `.mcp.json` so your whole team picks it up: ### Other agents Or wire the project up properly, which also writes `.codex/hooks.json` and a managed `AGENTS.md`: See Agent plugins → Codex. Point the client at `repowise mcp`, run from the repo directory, over stdio. Drop this into `~/.cursor/mcp.json`, Cline's MCP settings, or the equivalent file for your client: The Repowise extension registers the MCP server for you and adds editor-native health signals, refactoring CodeLens, and branch risk on top. Search **Repowise** in the Marketplace, publisher `repowise-dev`. ### What agents should know about the CLI The behaviors that most often trip up an unattended run, all of them deliberate: Behavior Why it matters to an agent `init` never requires an API key A missing key is not an error condition. Without a provider it renders the wiki from structure and exits 0. No prompt when stdin is not a TTY The cost gate auto-declines rather than aborting, so it keeps the index it already built. Nothing hangs waiting for input. Unanswerable prompts degrade If the first interactive prompt reads EOF, `init` prints a notice and continues with defaults instead of ending the run. `REPOWISE_PROVIDER=""` means unset An empty value in a CI matrix resolves to normal auto-detection, not a provider named `""`. `--docs llm` plus `--index-only` exits 2 That is a usage error, not a runtime failure. Pass one or the other. `--mode fast` is the only wiki-less mode Everything else produces a full wiki. Do not reach for it unless the repo is very large. Repowise also writes a `CLAUDE.md` (and `AGENTS.md` for Codex) into the repo during `init`, so agents that read those files get the tool guidance without any MCP call at all. ### Machine-readable docs This documentation site serves itself in agent-friendly form. Point a fetch tool at either endpoint: Endpoint What you get `docs.repowise.dev/llms.txt` The index: every docs page, titled and linked, in one small file. `docs.repowise.dev/llms-full.txt` The full text of every docs page in one document. `repowise.dev/llms.txt` The site-wide index: features, comparisons, guides, and blog. Start with `llms.txt` to find the right page, then fetch that page or fall back to `llms-full.txt` when you want everything at once. ### What to do next Skim the ten MCP tools so you know what your agent can ask for. Set up auto-sync so the index stays current on every commit without anyone thinking about it. If the free index proved useful, upgrade the wiki to model-written prose with `repowise generate`. ## How it works URL: https://docs.repowise.dev/getting-started/how-it-works The five intelligence layers Repowise computes and how they fit together. Repowise's index is a single artifact built from five passes over your repo. Each pass produces something the next one consumes; the final shape is what the MCP tools query. ### 1\. Dependency graph Language-aware resolvers under `packages/core/src/repowise/core/ingestion/resolvers/` parse each file, extract symbols, and emit import edges. Symbols are nodes, imports are edges, and PageRank + community detection run once at the end to surface the architectural skeleton. → Dependency graph ### 2\. Git history A second pass walks the git log and records, per file: commit count, last-touched date, primary owner, co-change pairs (files that move together), and churn percentile. This is what powers hotspots, bus-factor, and the "who can review this PR" queries. → Git history & co-changes ### 3\. Generated wiki For each non-trivial file and every module, repowise produces a short Markdown page that names the symbol's purpose, cites callers, and flags anything weird. The wiki is the substrate `get_answer` and `get_context` retrieve from: the LLM is reasoning over Repowise's prose, not raw source. The pass runs one of two ways. With a provider configured, an LLM writes each page. Without one, repowise renders the same page set from the graph and git signals the earlier passes produced, with no model in the loop, which is why `repowise init` works and exits 0 on a machine with no API key. → Auto-generated wiki · Deterministic wiki ### 4\. Architectural decisions Decisions are first-class. You write them by hand (`repowise decision add`) or let repowise capture them from significant commits and inline markers. They link to the files they constrain, so `get_why` can answer "why is this code structured this way" with citations. → Architectural decisions ### 5\. Code health A final deterministic pass scores every file 1 to 10 from markers across three signals (defect risk, maintainability, performance), reusing the graph (centrality) and git signals (ownership, churn, co-change) the earlier passes produced, plus structural complexity, duplication, and static performance risk. No LLM calls. The defect-risk weights are calibrated against a real defect corpus, so the score predicts where bugs will land, and `get_health` exposes it to your agent. → Code health The five layers are computed once, then refreshed incrementally on every push (or every git commit, if you install the post-commit hook). See Auto-sync for the five sync mechanisms. ## Agent plugins URL: https://docs.repowise.dev/getting-started/plugins The Claude Code and Codex plugins bundle the MCP server, lifecycle hooks, skills, and slash commands into one install. What each plugin ships, how to install it, and what activates when. Repowise ships two agent plugins. Both bundle the MCP server, lifecycle hooks, and a set of skills into a single install, so you do not wire up each piece by hand. Claude Code Codex MCP server Yes Yes Lifecycle hooks Yes Yes, opt-in in current Codex releases Skills 6 6 Slash commands 10 None, Codex has no equivalent Install source Public marketplace Local marketplace from a repo clone Both are AGPL-3.0 and live in the OSS repo under `plugins/`. A plugin is the convenience, not the requirement. Everything it wires up works standalone: `repowise init` already registers the MCP server and writes `.mcp.json` for you. See Set up with your agent if you just want the shortest path. ### Claude Code plugin That is the whole install. It brings the MCP server, ten slash commands, six skills, and two hooks. ### Slash commands Explicit, you type them. Each maps to a CLI command and formats the result for reading rather than parsing. Command What it does `/repowise:init` Set up repowise here. Installs the CLI if needed, asks about preferences, runs the indexing. `/repowise:status` Index health: sync state, page counts, provider, token usage. `/repowise:update` Incremental update so the docs match recent commits. `/repowise:search` Search the wiki by natural language, full text, or symbol. `/repowise:health` Code health: KPIs, lowest-scoring files, refactoring targets, trends, per-file markers. `/repowise:risk` Defect risk for a commit or a `base..head` range, as a 0 to 10 score with drivers. `/repowise:decision` Architectural decisions: list, inspect health, add, or confirm auto-proposed ones. `/repowise:dead-code` Unreachable files, unused exports, and zombie packages, tiered by confidence. `/repowise:reindex` Rebuild the vector store by re-embedding wiki pages. No LLM calls, embeddings only. `/repowise:doctor` Diagnose the setup (install, keys, index drift) and optionally repair it. ### Skills Implicit, they activate on their own when the work matches. Each checks for a `.repowise/` directory first and stays out of the way if the repo is not indexed, so installing the plugin globally does no harm in unindexed repos. Skill Activates when `codebase-exploration` Understanding or explaining a codebase: how does X work, where is Y implemented, what does this module do. `pre-modification-check` Before editing, refactoring, or deleting files, especially shared utilities and core modules the user did not name. `change-review` Reviewing a PR, a branch diff, or working-tree changes before they merge. Blast radius, missing co-changes, test gaps. `architectural-decisions` Questions about why code is built a certain way, or before diverging from an established pattern. `code-health` Quality, complexity, technical debt, what to refactor next, untested hotspots, coverage gaps. `dead-code-cleanup` Cleanup, removing unused code, reducing bundle size, repository hygiene. ### Hooks Two, both calling the `repowise-augment` entry point: Hook Fires on Why `SessionStart` `startup`, `resume`, `clear` The session opens with repo context already loaded, so the first question does not cost a round-trip. `PostToolUse` `Bash`, `PowerShell`, `Grep`, `Glob`, `Read`, `Edit`, `Write`, and repowise MCP calls Nudges the agent toward the index after file and search operations, and flags when a git operation has made the wiki stale. Claude Code also gets search-result enrichment on `Grep` and `Glob`, which the Codex setup does not attempt. Full detail in Agent hooks. ### Codex plugin Repowise supports Codex three separate ways, and they are worth keeping apart: **Project setup** for Codex MCP and lifecycle hooks, via `repowise init --codex`. **The `codex_cli` provider**, which generates wiki pages through your authenticated Codex CLI subscription instead of an API key. **The plugin**, which bundles MCP, hooks, and skills. ### Prerequisites Repowise checks `codex --version` and `codex login status`. When both succeed, interactive `repowise init` offers Codex project setup. Non-interactive runs need `--codex` explicitly; `--no-codex` skips the prompt. ### Project setup This writes **project-local** files, not your global `~/.codex/config.toml`. It merges into `.codex/config.toml`: The server runs `repowise mcp` with no path argument. In no-path mode it walks upward from the current directory to the nearest initialized `.repowise` repo. Smoke check with `codex mcp list`. ### Installing the plugin The Codex plugin installs from a local marketplace rather than a public one, so you need a clone of the repo: It bundles the MCP server, lifecycle hooks, and the same six skills in Codex-neutral form. It adds no slash commands, because Codex has no equivalent surface. **Plugin-bundled hooks are opt-in in current Codex releases.** Set `[features] plugin_hooks = true` if you want hooks loaded from an installed plugin. Hooks written by `repowise init --codex` land in `.codex/hooks.json` and are not subject to that flag. ### Codex hooks Written to `.codex/hooks.json`, not inline `[hooks]` tables: Hook Fires on Why `SessionStart` `startup`, `resume`, `clear` Adds repowise MCP workflow guidance. `UserPromptSubmit` Every prompt Reminds Codex that repowise context is available. `PostToolUse` `Bash` Detects git operations that make the wiki stale. `PostToolUse` `apply_patch`, `Edit`, `Write` Reminds Codex after edits. ### The `codex_cli` provider Worth knowing about even if you skip the plugin. It routes page generation through your Codex subscription instead of a metered API key: Repowise treats `codex_cli/*` cost as $0.00, because subscription billing happens outside its API pricing. `--reasoning minimal` maps to Codex `model_reasoning_effort="low"`; `low`, `medium`, `high` and `xhigh` pass through when the selected model advertises them. `off` and `none` are not supported by this provider. ### AGENTS.md `repowise init --codex` generates a managed `AGENTS.md` by default, the Codex counterpart to the generated `CLAUDE.md`. `repowise update` refreshes it when `editor_files.agents_md` is enabled or `--agents` is passed. The repowise section sits between managed markers and your own content outside those markers is preserved. ### Which to install Install the plugin. The slash commands and skills are the difference between having the tools available and actually having them used at the right moment, and it is a two-line install. Run `repowise init --codex` first, since that is the part that wires MCP and hooks into the project and needs no clone. Add the plugin on top if you want the skills as well. There is no plugin, but nothing is lost: point your client at `repowise mcp` over stdio and you get the same tools. See Set up with your agent. ## Quickstart URL: https://docs.repowise.dev/getting-started/quickstart Install repowise, index your repo, and connect Claude Code in under a minute. Two paths, self-hosted (pip) or hosted (repowise.dev). Two ways to start. **Self-hosted** runs entirely on your machine and your code never leaves. **Hosted** uses managed infrastructure and a hosted MCP endpoint. ### Install Python 3.11+ required. Verify with `repowise --version`. ### Index the repo **No API key needed.** Repowise parses every file to an AST, builds the dependency graph, reads your git history, scores every file for code health, and finds dead code. It then renders a complete wiki from that structure: file, module, layer and cycle pages, the architecture diagram, the repo overview, API and infra pages, and the onboarding collection. No LLM calls, no key, no network. This is the step worth doing first, because it costs nothing and answers the question "is this useful on my codebase". If you want to be explicit that this run must not spend anything, spell it out: Those pages are honest about where they came from. Each ends with a footer saying it was derived from structure, and the repo overview covers composition, entry points, clusters and dependencies rather than what the project does end to end. More in Deterministic wiki. ### (Optional) Add a key for model-written docs The upgrade over the structure-rendered wiki is prose that explains *why*, plus semantic search. Bring your own key: With a provider resolvable, `init` writes the wiki with a model and shows you a cost estimate before spending anything. See Environment variables for the full provider list. Already indexed without a key? You do not need to start over. Upgrade pages in place, a slice at a time with `repowise generate --coverage 20` or wholesale with `repowise update --full`. ### Connect Claude Code `repowise init` already wrote `.mcp.json` at the project root and registered the server in `~/.claude/settings.json`. **Restart Claude Code** and you're done. To wire up another editor, the MCP server config is: Drop it in `~/.cursor/mcp.json`, Claude Desktop's `claude_desktop_config.json`, or any other MCP-aware client. **On VS Code?** The Repowise extension registers the MCP server for you and adds editor-native health signals, refactoring CodeLens, and branch risk on top. ### Verify it works In Claude Code, ask: > Give me a tour of this codebase. The agent should call `get_overview` and reply with the architecture summary. If it falls back to `Grep` and `Read` instead, the MCP server isn't connected. See Troubleshooting. ### (Optional) Browse the wiki locally Starts the MCP server and API on `http://localhost:7337`, plus a local dashboard at `http://localhost:3000`: interactive graph, hotspots, ownership, dead code, the generated wiki, decision records, and cost tracking. The dashboard needs Node.js 20+ (auto-downloaded and cached on first run); without it, `repowise serve` falls back to API-only mode. ### (Optional) Auto-sync on commit Installs a post-commit git hook that runs `repowise update` automatically. The wiki stays current without you thinking about it. Other sync methods (file watcher, GitHub webhook, polling) live in Auto-sync. ### Sign in Open repowise.dev and sign in with GitHub. ### Index a repo Click **+ Index a new repo** and paste a GitHub URL. Public repos are free; private repos need the Repowise GitHub App installed (one click from the same dialog). Indexing runs on managed infrastructure. You'll get an email when it's done, typically 10 to 30 minutes for the first index, seconds for each subsequent push (auto-synced via webhook). ### Connect your editor Open **Settings → Editor**, mint an API key, and copy the snippet for Claude Code, Cursor, Claude Desktop, VS Code, or Windsurf. Paste it into your MCP client config and restart. ### Verify it works Ask your agent: *"What does this codebase do?"* It should call `get_overview` against the hosted endpoint and answer in one round-trip. **Self-hosted vs hosted feature parity.** You get every CLI command, every MCP tool, the full dashboard. The hosted version adds managed indexing, push-sync via webhooks, federated cross-repo intelligence, and a security scanning layer. See Hosted vs self-hosted. If your product spans several repos, index them as a workspace and get cross-repo co-changes, API contract extraction, and federated MCP queries. ### Lay out the parent directory Each subdirectory must be its own git repo. ### Initialise Repowise scans for git repos, asks which to include, indexes each, then runs cross-repo analysis (co-change detection, API contract matching, package dependency mapping). ### Serve the workspace The dashboard shows aggregated stats, repo cards, contracts, and co-change pairs. The MCP server is federated, so pass `repo="backend"` or `repo="all"` to any of the ten tools. ### Connect Claude Code Same `.mcp.json` is written at the workspace root. Full guide: Workspaces. ### What to do next Skim the ten MCP tools so you know what your agent can ask for. Read How it works for the four intelligence layers behind those tools. Set up Auto-sync so the wiki stays current. Browse the CLI reference for all the commands. **Stuck?** Run `repowise doctor`. It checks API keys, store drift, hook installation, and MCP registration. `repowise doctor --repair` fixes most issues automatically. ## VS Code extension URL: https://docs.repowise.dev/getting-started/vscode The Repowise extension brings the local index into VS Code (editor-native health signals, refactoring CodeLens, branch risk, in-editor dashboards) and registers the Repowise MCP server so the same index serves both you and your AI agent. The Repowise extension brings the local index into your editor and registers the Repowise MCP server with VS Code, so the same index serves both you and your AI coding agent. It is a thin client over the local `repowise` CLI and server: everything is computed on your machine and nothing about your code leaves it through the extension. This extension drives the **local, self-hosted** server (the index under `.repowise/`). If you use the hosted platform and want your agent to reach the managed MCP endpoint instead, see Connecting your IDE; no local index required. ### Install the CLI Python 3.11+ required. Verify with `repowise --version`. ### Install the extension From the VS Code Marketplace (search **Repowise**, publisher `repowise-dev`), or from Open VSX for VS Code forks. ### Set up the repository Open a repository and run **Repowise: Set Up This Repository** to build the index, or follow the **Get Started with Repowise** walkthrough. The extension activates only in trusted workspaces and does no work at startup beyond registering its commands. It discovers a running server from the lockfile under `.repowise/`, or offers to start one when you first need data. ### Know before you push **Analyze Change Risk** (Source Control title bar, or the command palette) scores your uncommitted work against its base branch and opens a panel with the whole story of the change: A summary strip: how many files are affected downstream, how many usual companion files you haven't touched, and how many changed files have no associated test. Each chip jumps to its section. **Riskiest files in this change**: your changed files ranked by how risky history and structure say they are, so you review in the right order. Files that change unusually often are marked as hotspots. **Downstream of your changes**: the files that depend on what you edited. **Usually changes together**: companion files your history says belong to this change but are untouched. Advisory, not a rule. **Changed without a test**, and **suggested reviewers** with one-click copy for the PR description. While you edit, a quiet co-change hint can appear in the status bar when the files you're touching have a strong history of changing together with a file you haven't opened. Dismissible per change set, never a popup, and tunable or off in settings (`repowise.changeIntel.*`). ### Editor-native signals **Gutter heat**: a severity-tiered strip next to lines with findings in the visible editor. **File health in the status bar**: defect, maintainability, and performance scores for the active file. See Code health. **File explorer badges** on the worst-health files (threshold configurable). **Refactoring CodeLens** above symbols with a detected plan, including **Copy plan for agent**: the same payload the web Refactoring tab produces. **Hovers**: line 1 of a file shows its health scores, primary owner, and governing decisions. Hovering a symbol shows what kind of symbol it is, how many callers and callees it has, who owns the file, and the decisions that govern it, fetched only when you hover, then cached. **Diagnostics** (off by default): opt in to publish high-severity findings to the Problems panel (`repowise.diagnostics.enabled`). The quieter surfaces above carry the full detail either way. ### Tree views A single Repowise activity-bar container with a **Home** overview, a **Findings** tree (health, hotspots, ownership, dead code), and a **Refactoring** tree. All lazy: data is fetched on first expand and refreshed only when the index moves. ### Dashboards Editor-tab webviews rendered from the same shared visualization library the web app uses (no duplicated components): **health overview**, **architecture map**, **knowledge graph** (with node search, path finder, and community detail), **refactoring plans**, **decision timeline**, and a **docs browser**. ### MCP for your AI agent One install registers the Repowise MCP server with VS Code, so agent-mode assistants query the index through the ten task-shaped tools instead of guessing from open files. For editors that read a config file, run **Repowise: Configure MCP for this Workspace** to write `.vscode/mcp.json`. ### Settings Setting Default Purpose `repowise.server.autoStart` `ask` Start the local server automatically, ask first, or never `repowise.server.port` discover Override the server port instead of using lockfile discovery `repowise.cliPath` PATH Absolute path to the `repowise` executable `repowise.diagnostics.enabled` `false` Publish health findings to the Problems panel. Off by default; gutter, badges, and hovers still surface findings `repowise.diagnostics.minSeverity` `high` Lowest severity surfaced in the Problems panel `repowise.diagnostics.dimensions` all Health dimensions included in the Problems panel `repowise.gutterHeat.enabled` `true` Shade the gutter next to findings `repowise.fileDecorations.enabled` `true` Badge the worst-health files in the explorer `repowise.fileDecorations.maxScore` `4` Health score at or below which a file is badged `repowise.codeLens.enabled` `true` Show refactoring plan lenses `repowise.hover.enabled` `true` Show file health context on hover `repowise.hover.symbolDetail` `true` Enrich symbol hovers with callers, callees, ownership, and decisions `repowise.risk.baseBranch` default branch Base branch for branch risk scoring `repowise.changeIntel.cochangeNudge` `true` Show the quiet "usually change together" status-bar hint `repowise.changeIntel.cochangeMinScore` `4` Minimum historical co-change count before a related file is surfaced ### Privacy The extension talks only to the local Repowise CLI and server on your machine and reads the index under `.repowise/`. It sends no telemetry of its own. The CLI's own telemetry opt-out is respected because the extension itself sends nothing. ### Learn more Quickstart: install the CLI and build your first index. The ten MCP tools: what your agent can ask for. Connecting your IDE: the hosted MCP endpoint for other editors. ## What is repowise URL: https://docs.repowise.dev/getting-started/what-is-repowise Repowise indexes your codebase into five intelligence layers (graph, git, wiki, decisions, code health) and exposes them to AI agents through ten task-shaped MCP tools. The why your AI agent has been missing. Repowise is a codebase intelligence engine. Point it at a git repository and it produces a single artifact, a SQLite + vector store under `.repowise/`, that AI agents and humans can both query. The artifact captures five layers of context that no static analyzer or LLM-only tool gives you on its own. **You do not need an API key to try it.** `repowise init --yes` builds all five layers and renders a complete wiki from your code's structure, with no model, no key, and no network. Adding a provider later upgrades the wiki to model-written prose in place. See Deterministic wiki. ### 1\. Static structure Every file, symbol, and import edge, parsed by language-aware resolvers across 16 languages: Python, TypeScript, JavaScript, Java, Kotlin, Go, Rust, C++, C#, Scala, Ruby at the **Full** tier; C, Swift, PHP, Dart at **Good**; SQL via a dedicated sqlglot handler; plus config and data formats (OpenAPI, Protobuf, GraphQL, Dockerfile, Terraform, etc.). The dependency graph has two tiers (file nodes + symbol nodes) and uses a three-tier call resolver with confidence scoring to handle import aliases, barrel re-exports, namespace imports, and framework conventions (Django, FastAPI, Spring, Express, NestJS, Rails, Laravel, Axum, Actix). Plus heritage extraction (extends, implements, trait impls, derive macros, mixins, extension conformance) and Leiden community detection that finds logical modules even when your directory structure doesn't reflect them. ### 2\. Git history 500 commits of history (configurable up to 5,000) turned into behavioural signals static analysis can't produce: **Hotspot files.** High churn × high complexity, where bugs live. **Ownership.** `git blame` aggregated into per-engineer percentages. **Bus factor.** How many people could leave before a file becomes unowned. **Co-change pairs.** Files that change together without an import edge between them. Hidden coupling that AST analysis cannot detect. **Significant commits.** Meaningful messages (filtered of merges, dependency bumps, lint runs) that explain *why* code evolved. ### 3\. Auto-generated wiki A Markdown page for every module and every notable file. The pages cite source ranges, get a confidence score, are incrementally regenerated on every commit (typical update: 3 to 10 pages in under 30 seconds), and feed semantic search through a LanceDB vector store. Repowise builds this two ways. **Model-written** pages are the richer version: the prompt the LLM sees isn't only source, it includes parsed structure, top callers/callees, the most significant commit messages, ownership, and trend signals. That's the recipe for docs that explain *why*, not just *what*. **Deterministic** pages are rendered from the AST, the graph, and git with no model at all. That is what you get with no API key configured, and it covers the same page set: file, module, layer, cycle, overview, architecture, API, infra, and onboarding. It cannot tell you why retries were made idempotent, which is precisely what the model pass adds. See Deterministic wiki. ### 4\. Architectural decisions The layer nobody else has. Repowise treats decisions as first-class data: captured by hand (`repowise decision add`), mined from git history (auto-proposed), or extracted from inline markers in source: Decisions are linked to the graph nodes they govern, tracked for staleness as code evolves, and surfaced via `get_why` the moment your agent touches a governed file. ### 5\. Code health A 1 to 10 score for every file from **deterministic markers across three signals** (defect risk, maintainability, and performance) covering complexity, cohesion (LCOM4), duplication, untested hotspots, git-behavioural risk (ownership, churn, co-change scatter), and static performance risk (N+1 / I/O-in-loop shapes). Linters check patterns. This score predicts which files are likely to harbor the next bug: the defect-risk weights are **calibrated against a real defect corpus**, and the score is validated to out-rank the leading commercial code-health tool at predicting which files get bug-fixes. Zero LLM calls, under 30 seconds on a 3,000-file repo. See Code health. ### The agent surface Your editor's AI agent talks to all of this through ten MCP tools. They're **task-shaped**, not entity-shaped: pass multiple targets in one call, get complete context back in one round-trip. Tool What it answers `get_overview` Architecture, modules, entry points, git health `get_answer` One-call RAG: cited 2 to 5 sentence answers `get_context` Docs, ownership, callers/callees, metrics for any targets `get_symbol` Raw source bytes for one symbol with exact line bounds `search_codebase` Semantic search over the wiki `get_risk` Hotspot, dependents, co-changes, blast radius `get_change_risk` Pre-merge defect risk for a commit or diff range `get_why` Architectural decisions with archaeology fallback `get_dead_code` Tiered cleanup plan with confidence scoring `get_health` Three-signal health scores: KPIs + worst files, self-check before a PR Five calls usually replace what would otherwise take 30 reads and greps. Same answer, **27× fewer tokens, 36% cheaper, 49% fewer tool calls** on the repowise-bench SWE-QA suite. ### Why your agent needs this LLMs are good at reading the file in front of them and bad at reasoning across the rest of the codebase. They: Guess at module boundaries. Miss callers and dependents. Hallucinate function signatures from neighbouring repos. Have no idea why the previous engineer chose the design they did. Without context, the agent does what a junior engineer does on day one: reads files, asks lots of questions, and ships changes that break unrelated parts of the system. Repowise gives the agent the institutional knowledge a senior engineer would have. Hotspot warnings before edits. Co-change partners surfaced automatically. Architectural decisions linked to governed files. Ownership and bus-factor visible in every response. The agent stops guessing. ### Who it's for **AI-first engineering teams** who use Claude Code, Cursor, or Windsurf as their primary IDE. **Teams onboarding into unfamiliar codebases.** A new hire's first two weeks become two days when their agent already knows the hotspots, owners, and decisions. **Open-source maintainers** who want their contributors' agents to have full context without writing it all into `CONTRIBUTING.md`. **Anyone tired of watching their agent `cat` the same file four times.** ### Self-hosted or hosted Both modes ship the same intelligence: same parsers, same git analysis, same wiki generation, same MCP tools. Pick whichever fits. Self-hosted Hosted (repowise.dev) Install `pip install repowise` None, just sign in with GitHub Storage Local `.repowise/` (SQLite + LanceDB) Managed Postgres + R2 Auto-sync Hooks, watch, your own webhook server GitHub App push-sync (automatic) MCP server Local stdio process Hosted HTTP endpoint Multi-repo workspaces Yes Yes Cross-repo intelligence Yes (per workspace) Yes (federated across all your repos) Web UI `repowise serve` -> `localhost:3000` repowise.dev/dashboard Privacy Code never leaves your machine Encrypted; BYOK keeps LLM calls direct Cost Free, AGPL-3.0 Free tier + Pro See Hosted vs self-hosted for the full side-by-side. Or just jump to Quickstart and try one; switching later is painless because both speak the same MCP protocol. **Hybrid is fine.** Run self-hosted on a laptop for one private repo and hosted for everything else. Your agent talks to either through the same protocol; it doesn't care which server answers. ### What's next **Quickstart**: install + index connect Claude Code in under a minute. **How it works**: the end-to-end flow from `repowise init` to a connected agent. **MCP tools overview**: what your agent can actually ask for. ## Alerts & notifications URL: https://docs.repowise.dev/hosted/alerts HMAC-signed Slack-compatible webhooks, the in-product notification bell, and per-kind email preferences, for security events and engineering signals, designed to never spam. Repowise alerts on two families of events, through three channels. **Event families:** Family Events **Security** New CVEs (nightly refresh), live secret detected, scan failed, secret rotation overdue, audit-event stream (SIEM) **Engineering** Hotspot drift, bus-factor risk, health decline, decision staleness **Channels:** **Notification bell**: in-product, deduped to one unread per event kind per repo. A second nightly finding folds into the existing unread notification instead of stacking. **Email**: sent only when a new notification is actually raised (so it inherits the same dedupe), with a per-kind opt-out at **Settings → Email notifications**. **Webhooks** (Teams): HMAC-signed HTTPS deliveries, configured per repo or per team. ### Webhooks Configure under **your repo → Settings → Alerts**. Each endpoint picks its events and a payload format: **Slack format**: Block Kit messages that also work with Microsoft Teams and Mattermost inbound webhooks. **Signed JSON**: a stable envelope for your own receivers or SIEM. Every delivery is signed over the exact raw body: The signing secret is shown **once** at creation. Verify by recomputing the HMAC over the received body; the signed body embeds the same timestamp, so a replayed body with a fresh header is detectable. Delivery semantics: 3 retries with backoff on 5xx, no retry on 4xx, and an endpoint that fails 10 consecutive deliveries is auto-disabled with the reason surfaced in the UI. A webhook outage never blocks a scan or a cron. Team-scoped endpoints fire for every repo shared into the team. ### Anti-noise rules Alerting only earns its keep if you don't mute it. The rules, all deliberate: **Crossings, not levels**: engineering signals compare each nightly observation against the previous one and alert only when something crosses a threshold. The first observation of a repo stores a baseline and stays silent. **One unread per kind per repo**: repeat findings fold into the existing unread notification. **Email rides the notification**: no notification, no email. Every kind is individually opt-out, and the weekly digest is opt-in. **Rotation nudges fire once per secret**, not daily. ### Payload privacy Webhook and email payloads carry metadata only: file paths, owner names, deltas, counts, OSV ids, rule ids. Never code snippets, never secret values or previews. Security alerting is available on Teams. Engineering signals are detected nightly for Teams repos; see Teams & portfolio intelligence for what each signal watches. ## PR review bot URL: https://docs.repowise.dev/hosted/bot A deterministic GitHub App that posts one useful comment per pull request: a before-you-merge checklist, a change-map diagram, code-health deltas, hotspots, hidden coupling, dead code, change risk, and an optional merge gate. Zero LLM calls, free for OSS. The **Repowise PR bot** is a GitHub App that runs the same intelligence layers as the CLI and dashboard against every pull request, and posts **one deterministic comment**, only when there is something worth saying. No prompts, no hallucinations, no per-PR tokens. It is **free forever for public / OSS repos**; private repos need the Pro plan. Install it from the GitHub App page: **github.com/apps/repowise-bot**. Pick individual repos or a whole org. There is also a marketing overview and you can manage installs from the dashboard. ### Install **Install the GitHub App.** Open github.com/apps/repowise-bot, choose the repos (or the whole org), and approve. The bot indexes each default branch through the same pipeline the hosted dashboard uses, usually a few minutes. **Open a pull request.** On `opened` / `synchronize` / `reopened`, the bot re-parses the changed files, computes the health delta between base and head, and decides whether to comment. **Read the report.** Each comment links back to the live snapshot on `repowise.dev` for the full graph, hotspots, and marker drill-downs. **Permissions requested:** Contents: Read · Pull requests: Write · Metadata: Read · Issues: Write (GitHub treats PR comments as issue comments). The optional merge gate additionally needs Checks: Write; existing installs re-consent when you turn it on. ### The silence rule Most PR bots are noise. This one **stays silent unless there is a measurable signal** worth interrupting a reviewer for. A green PR with no findings gets no comment at all. When the bot does comment, improvements are shown alongside problems so cleanup gets credit. It posts when any of these fire: net repo health degrades, or any modified file's score drops; a hotspot file (high churn + many dependents) is touched; a top co-change partner of a modified file is missing from the PR; new dead code is introduced (or removed, which is a win); a modified file is on a declining-health trajectory; a changed file carries substantial recent bug-fix history; the diff's change-risk score lands in this repo's high band. The bot **edits its existing comment** when new commits land rather than posting a wall of duplicates; if the silence rule fires after an earlier comment, the stale comment is deleted. ### What's in the comment Each section is independent and only renders when it has something to say: Section What it shows **At a glance** A one-line factual summary of what the PR touches (files, hotspots, findings, scope), with a per-module drill-down when the PR spans several. **Before-you-merge checklist** Every signal restated as an action, as a tickable task list: the tests that depend on the changed files, co-change partners missing from the PR, and the docs that usually track this code. **Change map** A deterministic Mermaid diagram of the PR's structural impact: changed files on the left, the code that imports them on the right, with guarding tests and co-change gaps attached. Wide PRs collapse to a module-level flow so the map stays legible. **Health delta** Repo-level score change across the three signals (defect · maintainability · performance) plus a per-file table of which files dropped, with the concrete markers behind each drop. **Change risk** The just-in-time defect-risk score for the diff (the same signal as `repowise risk`), banded against this repo's own commit history. **Review priority** The changed files ranked by recent bug-fix history. Defects cluster, so these deserve the closest look. **Hotspot touches** When the PR modifies a high-churn, high-dependent file, surfaces its primary owner and suggests adding their review. **Hidden coupling** Files that historically co-change with a modified file but are absent from this PR, which catches partial refactors before they break the next deploy. **Declining-health alert** Files trending down across recent snapshots that also regressed in this PR. **Dead code** New unreachable code the PR introduces, plus cleanup celebrated when it removes existing dead code. **AI vs human** When the diff mixes AI- and human-authored hunks, the bot attributes the health delta by authorship: *"the AI-authored files account for the larger share of the regression."* Built on the agent-provenance layer, the one signal a generic linter cannot produce. Every finding is deterministic: health scoring is tree-sitter + git + the calibrated marker scorer, and refactoring suggestions are template strings keyed off the marker type. Nothing is generated by an LLM, so every comment is reproducible. ### The merge gate Beyond commenting, the bot can post a **GitHub Check Run** that a branch protection rule can require, turning code health into a merge gate. It is **off by default** and configured per repo (`health_gate.mode`): **`off`**: no check is created. **`advisory`**: always concludes `neutral`. The verdict is visible on the PR but never blocks. The safe default to start with. **`blocking`**: concludes `failure` when a rule trips, which a required check will block the merge on. The rules (evaluated only in `blocking` mode) let you adopt a clean-as-you-code policy without forking any constants: Rule Blocks when `repo_drop_block` The repo health score drops by more than this many points (default `0.3`). `min_new_file_score` A changed file scores below this floor. `block_on_introduced` The PR introduces any new marker in its added lines. `block_ai_regression` AI-authored files account for the larger share of the regression (the provenance wedge). Or start from a **named profile** and nudge single knobs: `health_gate.profile` accepts `warn-only`, `block-new-file-floor`, `block-any-decline`, or `block-on-ai-regression`. The profile seeds the rules; any explicit key set alongside it wins. Because the bot already re-scores the repo at both the base and head commits, the gate and the AI-vs-human attribution need no extra index; they read the same per-PR analysis the comment is built from. ### Configuration Two ways to configure, with the dashboard taking precedence: **1. In-repo `.repowise/bot.yaml`** (committed, versioned with the code): You can toggle any section (`show_summary`, `show_health`, `show_hotspots`, `show_ownership`, `show_coupling`, `show_dead_code`, `show_refactoring`, `show_declining_alert`, `show_change_risk`, `show_review_priority`, `show_checklist`, `show_change_map`), set the comment threshold, choose the verbosity, and ignore paths. **2. The hosted dashboard** (Settings → PR Bot). The dashboard config overlays the YAML: any field set there wins, fields it omits keep the YAML/default value, and `ignore_paths` is unioned (the dashboard can only add scope, never silently un-ignore a path the repo author chose to skip). A malformed value is skipped, never wedging the analyzer. ### Pricing Free forever for **public / OSS repos**: no LLM tokens, no PR cap. **Private repos** require the Pro plan (it matches the rest of Repowise hosted). Private installs still index on connect, so the snapshot is ready the moment you upgrade. See the pricing page. ### How it relates to the rest of Repowise Same engine, different surface. The bot reads the code-health, git-intelligence, and dependency-graph layers, and every comment links to the live dashboard snapshot, where the same data is queryable by humans (the web UI) and by AI agents (the MCP tools, including `get_health` for a pre-PR self-check). ## Connecting your IDE URL: https://docs.repowise.dev/hosted/connecting-ide Mint an API key on the hosted dashboard and paste a snippet. Claude Code, Cursor, Claude Desktop, VS Code, and Windsurf supported. The hosted MCP endpoint is a single HTTP URL. Every editor that supports MCP can talk to it once you've minted an API key. ### Mint an API key Sign in at repowise.dev. Open **Settings → Editor**. Click **Generate key** and name it after the editor you'll use it from. Copy the snippet for your editor below. Keys are scoped per repo or per workspace and revocable any time. ### Snippets Add to `~/.claude/settings.json` (or paste into Claude Code's MCP panel): Restart Claude Code. Then ask: *"Give me a tour of this codebase."* The agent should call `get_overview` against the hosted endpoint. Drop the same `mcpServers` block into `~/.cursor/mcp.json`. Restart Cursor. Add to `claude_desktop_config.json`: macOS: `~/Library/Application Support/Claude/` Windows: `%APPDATA%\Claude\` Use the same `mcpServers` block. Restart Claude Desktop. Install the MCP extension. In its settings, add a server: **Name**: `repowise` **Transport**: `http` **URL**: `https://mcp.repowise.dev` **Authorization header**: `Bearer YOUR_API_KEY` Settings → MCP servers → Add server. Use the same transport, URL, and authorization header. ### Targeting a specific repo or workspace The hosted server is workspace-aware. Pass `repo=""` to any tool to target a specific repo, or `repo="all"` to federate across your whole workspace. See Workspace MCP mode. ### Verify it works Ask your agent something the model can't possibly know without calling repowise: > What are the current hotspot files in this repo? The agent should call `get_overview` (or `get_risk`) and answer with specific file names, churn percentiles, and owners. If it falls back to greps and reads, the MCP connection isn't established. ### Rotate or revoke Settings → Editor shows every active key. Click **Revoke** to invalidate. Generate a new one, paste it in, restart your editor. **Self-hosted instead?** No API key needed. `repowise init` writes `.mcp.json` for you and the editor talks to a local stdio process. See Quickstart → Self-hosted. ## Dashboard tour URL: https://docs.repowise.dev/hosted/dashboard What lives behind sign-in at repowise.dev/dashboard: the hosted control plane for your indexed repos, workspaces, MCP keys, billing, and team. The hosted dashboard at repowise.dev/dashboard is the control plane for everything you can do with the hosted version of repowise. The same intelligence layers that `repowise serve` exposes locally are here, plus the bits that only make sense for a managed service: indexing status, MCP key minting, GitHub App management, billing, and team membership. ### What's on it The landing page at `repowise.dev/dashboard` lists your indexed repos with live indexing status, recent jobs, and a workspace summary card if you've grouped repos into a workspace. A `Cmd/Ctrl+K` command palette jumps straight to any repo or page from anywhere. Section What you do here **Dashboard (repo list)** Index a new repo, watch indexing progress live, jump into any repo **Workspace** Overview, System Map, Conformance, Contracts, and Co-Changes across every repo in the workspace **Settings → Editor** Mint API keys and copy the MCP snippet for your editor **Settings → Team** Members, invitations, shared repos, billing, and the portfolio intelligence pages (health, ownership, engineering signals) **Settings** Account, GitHub App, email notification preferences, billing ### Inside a repo Every indexed repo gets a full analysis surface under a grouped nav, not just a wiki: Group Pages *(top)* **Overview** (KPIs, activity, languages, health ring, recent significant commits) · **Docs** (the LLM-authored wiki with citations and freshness) · **Architecture** (tabs: Communities, Explore, Coupling, Dependencies, Symbols) · **Knowledge Graph** (node search, path finder, community detail) · **Code Health** (tabs: Overview, Findings, Hotspots, Coverage, Dead code, Impact, Security) · **Refactoring** (ranked plans, blast radius, copy-to-agent) · **Files** (every indexed file, ranked by importance, browsable by folder) **People & History** Commits (history with categories, per-change change risk) · Contributors (ownership, bus factor) · Decisions (linked to the files they govern, with staleness tracking) *(chat)* **Chat**: natural-language Q\&A over the repo, the same RAG that powers `get_answer` **Settings** Stats · Usage & savings (LLM spend and what Repowise saved your agents in tokens) · Settings (re-sync, visibility, alert webhooks, danger zone) Older flat links (`/graph`, `/c4`, `/hotspots`, `/risk`, `/ownership`, `/coverage`, `/blast-radius`, `/health`) still resolve: they redirect into the tab above that now owns that view. ### Indexing a repo From **Repos → + Index a new repo**: Pick a GitHub URL (or select from the list once the GitHub App is installed). Choose the LLM provider (Repowise-managed by default, using your account's pooled key, or BYOK). Submit. Indexing runs on managed infrastructure; you'll get an email when it's done. The repo card shows status (`indexing`, `ready`, `stale`, `error`) and a re-sync button. Pushes auto-sync via webhook; no manual update unless you want to force one. ### Connecting your editor **Settings → Editor** mints an API key and shows a ready-to-paste MCP snippet for Claude Code, Cursor, Claude Desktop, VS Code, and Windsurf. The snippet uses the HTTP transport and points at the hosted MCP endpoint. Keys are scoped per repo or per workspace and revocable any time. See Connecting your IDE for the full walkthrough. ### What's *not* on the dashboard The five intelligence layers themselves: they live in the wiki and the MCP tools, not as separate dashboard pages. The CLI: the dashboard wraps the same server as `repowise serve`, but you don't run shell commands here. Self-hosted? `repowise serve` gives you most of the same screens locally at `http://localhost:3000`. The bits that only exist on the hosted dashboard are the ones that wrap a managed service: billing, team management, the GitHub App installer. ## Jira & Confluence URL: https://docs.repowise.dev/hosted/integrations Connect an Atlassian site to link architectural decisions to the Jira tickets that motivated them, and publish your generated wiki to Confluence on a weekly schedule, updated in place and never duplicated. A team owner or admin connects an Atlassian Cloud site once, under **Settings → Team → Jira & Confluence**. The connection is OAuth-based (read-only Jira scopes plus Confluence page write), team-scoped, and covers every repo shared into the team. ### Connecting your site Go to **Settings → Team** and click **Connect Atlassian**. Approve the consent screen on Atlassian. If your account can access several sites, pick which one the team uses. The card shows the connected site and its status from then on. If Atlassian ever revokes the grant, the card flags **Needs re-auth** and a single reconnect heals every dependent feature. Tokens are encrypted at rest and never leave the Repowise API. Repowise stores no Atlassian account data, no account ids, names, or emails. ### Decisions ↔ Jira issues Repowise's decision records carry evidence commits, the commits a decision was extracted from. **Find Jira links** (on the decisions page) mines those commit messages for issue keys and links the matches: Keys only count when their project prefix exists on your connected site, so `SHA-256` or a made-up `FAKE-123` never produce a link. Each decision page gains a **Linked Jira issues** section showing the ticket, its title, and a live-ish status pill (refreshed on view, cached for an hour). Manual linking by key covers tickets that never appeared in a commit message; unlinking is one click. The `get_why` MCP tool carries the same links, so your editor's agent sees the originating ticket next to the decision rationale. ### Publishing the wiki to Confluence Per repo, under **repo → Settings → Confluence publication**: Pick a space (and optionally a parent page id) for the wiki to live under. Publish on demand with **Publish now**, or enable the weekly schedule. Publication is idempotent and in-place: Every page carries a banner stating exactly which commit it was generated from, with a link back to the hosted wiki, and an explicit **STALE** warning when the repository has new commits since the last index. Unchanged pages are skipped (content-hash diff), changed pages are updated in place at the next version, and pages that disappear from the wiki are moved to Confluence's trash (reversible), and re-publishing never duplicates a page tree. Markdown that has no clean Confluence equivalent (e.g. embedded raw HTML) is rendered as a visible code block rather than dropped. The last run's outcome (created / updated / unchanged / removed, plus any per-page failures) is shown on the card. The Jira & Confluence integration is available on the Teams plan. The connection is made by a team owner or admin; decision links and publication work for every member after that. ## Hosted platform URL: https://docs.repowise.dev/hosted/overview Everything the managed platform adds on top of the OSS engine: zero-ops indexing, push-sync, AI docs and chat, the security suite, team portfolio intelligence, and alerting, with a plan ladder from free to enterprise. repowise.dev runs the same intelligence engine as the OSS CLI (same parsers, same git analysis, same wiki generation, same MCP tools) as a managed service. You sign in with GitHub, click **+ Index a new repo**, and everything else (clones, indexing compute, webhooks, storage, re-syncs) is handled for you. What the platform adds on top of the engine: **Zero-ops indexing**: managed infrastructure, progress you can watch live, email when it's done, and push-triggered auto-sync that re-indexes within \~30 seconds of every push. **Private repos** via a one-click, read-only GitHub App install. **AI features with managed billing**: wiki generation, codebase chat, and semantic search on pooled credits, or bring your own LLM key and traffic goes straight from us to your provider. **A full security suite**: CVE-aware dependency scanning with usage and reachability triage, secret detection across full git history, SBOM/VEX export, nightly CVE refresh, compliance reports, and an audit trail. Details → **Team portfolio intelligence**: shared repos and credits, portfolio health, ownership and bus-factor rollups, and an engineering-leader dashboard fed by nightly drift detection. Details → **Alerting**: signed Slack-compatible webhooks, in-product notifications, and email for both security events and engineering signals. Details → **Jira & Confluence**: decisions linked to the tickets that motivated them, and scheduled wiki publication to a Confluence space with freshness banners. Details → **A hosted MCP endpoint**: one HTTPS URL for every editor, with federated queries across all your repos. Connect your IDE → ### Plans at a glance Full feature matrix and current prices: repowise.dev/pricing. Free Pro Teams Enterprise **Repos** 2 public 5, private included 25, pooled across the team Unlimited **Repo size** Up to 250 MB Up to 5 GB Up to 5 GB Unlimited **Git history** 500 commits Full Full Full **Auto-sync on push** No ✓ ✓ ✓ **AI docs, chat, semantic search** No ✓ (credits included, BYOK supported) ✓ (credits pooled per seat) ✓ **Security scanning** (CVEs, secrets, SBOM/VEX, nightly refresh) No ✓ ✓ ✓ **PR review bot** Free for OSS Your repos All team repos All SCMs **Teams features** (roles, shared workspaces, portfolio health, ownership) No No ✓ ✓ **Engineering signals + leader dashboard** No No ✓ ✓ **Alert webhooks** (Slack-compatible, signed) + compliance + audit trail No No ✓ ✓ **SSO / SCIM / on-prem / air-gapped** No No No ✓ The deterministic layers (dependency graph, hotspots, dead code, ownership, decisions, code health) are included on **every** plan, including Free. Paid plans add the AI features, the security suite, and the team surface; they never paywall the core analysis. ### How indexing works here **Index**: paste a GitHub URL (or pick from the App's repo list). A managed worker clones and runs the full pipeline; the dashboard shows phase-by-phase progress in real time. **Browse**: the snapshot is immediately explorable: wiki, graph, hotspots, health, security, decisions, commits. **Stay fresh**: pushes re-index automatically via webhook. A nightly CVE refresh re-matches your dependency inventory against new advisories with no re-index needed. **Query from your editor**: mint an API key and your agent gets the same ten MCP tools, served over HTTPS. ## Security suite URL: https://docs.repowise.dev/hosted/security CVE-aware dependency scanning with usage and reachability triage, secret detection across full git history, SBOM/VEX export, a nightly CVE refresh, compliance reports, and an insert-only audit trail. Every Pro+ repo gets a security scan with each index: the dependency inventory is matched against OSV.dev, secrets are hunted across the **entire git history** (not just HEAD), and the results land in the repo's **Security** hub (`Repos → your repo → Security`). What makes it different from a plain scanner is that findings are **graph-aware and usage-aware**: Repowise already knows what your code imports, what's dead, and which files are hotspots, so it can tell you which vulnerabilities actually matter in *your* codebase instead of handing you a flat CVE list. ### Vulnerabilities (Pro+) **Full inventory matching**: every dependency (including transitives via lockfiles) matched against OSV, with severity from CVSS, exploitation context from **CISA KEV** and **EPSS**, and a single priority score that ranks the queue for you. **Usage triage**: each finding is labelled by what your code actually does with the package: `used`, `imported but unreachable`, `not imported`, or `dev-only`. A critical CVE in a package you never import is not your first problem; the triage makes that explicit. **Function-level reachability**: advisories that name affected symbols are crossed with your imports; provably unreachable findings are discounted. Coverage is per-ecosystem and labelled honestly. **Nightly CVE refresh**: new advisories are matched against your *stored* inventory every night, no re-index needed. Anything new and critical/high/KEV raises an alert (bell, webhook, email). ### Secrets (Pro+) Leaked credentials across every commit ever made, with **live-at-HEAD** flagging: a key that's still in the working tree is a different emergency than one deleted two years ago. Provider-specific **revocation links** (GitHub PATs, AWS, Stripe, and many more) so the fix is one click away. **Rotation reminders**: a live secret that sits unrotated past 90 days nudges the owner once (never a daily nag). Only **redacted previews** are ever stored. Secret values never leave the scanner. ### SBOM + VEX export (Pro+) The dependency inventory exports as a standard **CycloneDX SBOM**, and your triage decisions export as a **VEX** document that downstream scanners and auditors consume. Snapshot-to-snapshot SBOM diffs show exactly what changed. ### Workspace security rollup (Teams) The workspace dashboard aggregates posture across every repo: open vulnerabilities by severity, KEV counts, live secrets, license risk (copyleft exposure), and a workspace-wide "fix first" list ranked by priority. ### Compliance reports (Teams) Control-coverage reports for **PCI-DSS** and **SOC 2**, derived from your live findings with evidence drill-ins and JSON/Markdown export. These are honest signals, not an audit. They map where an assessor will look and what your current findings say about each control. They don't certify anything. ### Audit trail (Teams) An insert-only log of who viewed, exported, or changed security data, including AI-agent reads over MCP, with actor, IP, and timestamp. Browse it in-product, export JSON/CSV, or stream it to your SIEM via the opt-in `security_audit_event` webhook. ### Alerting New critical CVEs, live secrets, failed scans, and rotation reminders fan out to the notification bell, email (per your preferences), and HMAC-signed webhooks. See Alerts & notifications. Privacy rules, all binding: OSV only ever sees package URLs (purls), never code. Webhook and email payloads carry metadata only: rule ids, paths, counts, OSV ids. Never code snippets or secret previews. ## Teams & portfolio intelligence URL: https://docs.repowise.dev/hosted/teams Seats with pooled repos and credits, shared workspaces, portfolio health and ownership rollups, and an engineering-leader dashboard fed by nightly drift detection. The Teams plan turns Repowise from a personal tool into the shared source of truth for an engineering org: index a repo once and every member reads the same snapshot, queries it from their own editor, and shows up in the same portfolio views. ### How a team works **Seats**: per-seat billing (3-seat minimum) with owner / admin / member roles. Members are invited by email. **Pooled repos**: the team's repo limit (25) is shared across the whole team, not per seat. No re-indexing the same codebase per person. **One GitHub App install**: an admin installs the App on the org once; every member's private-repo access comes from that install. **Pooled credits**: each seat contributes to one team credit balance for AI features, centrally billed and topped up by the admin. **Shared workspaces**: team-owned cross-repo workspaces with co-changes, contracts, and package-dependency views across member repos. **Team-wide PR review bot**: blast-radius and reviewer-suggestion comments on pull requests across all team repos. Team management lives at **Settings → Team**: members, invitations, shared repos, billing, and the portfolio intelligence pages below. ### Portfolio intelligence Three read-only rollups aggregate every team repo's latest snapshot, built for the person who pays for the plan and opens it weekly: ### Portfolio health Team-wide code-health KPIs (file-weighted average, critical/warning finding counts, worst repo) plus a per-repo card grid that deep-links into each repo's health pages. ### Ownership & bus factor Top owners merged across the portfolio (files owned, hotspots owned, recent commits, knowledge silos) and a cross-repo list of bus-factor-1 files: high-churn files one departure away from being orphaned. ### Engineering signals (the leader dashboard) A nightly job observes every team repo's latest snapshot and tracks four signals **between observations**, so it can alert on genuine drift rather than static levels: Signal What it watches **Hotspot drift** Files newly crossing the hotspot threshold (top churn quartile + activity floors) **Bus-factor risk** High-churn or hotspot files dropping to a single recent contributor **Health decline** Average / hotspot health falling 0.5+ points since the previous observation **Decision staleness** Recorded architectural decisions whose governed files churned past them The leader page (**Settings → Team → Engineering signals**) shows rollup KPIs, per-repo cards with health trend sparklines, and a recent-alerts stream that deep-links into each repo's hotspots, ownership, decisions, and health-trend pages. Threshold crossings also fan out as alerts: bell, email, and signed webhooks. See Alerts & notifications. **First observation = baseline, zero alerts.** Signals alert only when something *crosses* a threshold relative to the previous nightly observation. A repo that has always had 40 hotspots stays quiet; the day two new files enter the set, you hear about it. ### Weekly digest Team owners and admins can opt in (Settings → Email notifications → Weekly digest) to a Monday email summarising the same view: per-repo signal counts and the week's threshold crossings. Off by default. ### Enterprise Beyond Teams: unlimited repos and seats, SSO (SAML/OIDC) + SCIM, RBAC, private-cloud / on-prem / air-gapped deployment (with Ollama for local inference), Jira/Confluence integrations, custom language extensions, and an SLA. Talk to us. ## Hosted vs self-hosted URL: https://docs.repowise.dev/hosted/vs-self-hosted Both modes ship the same intelligence layers, the same ten MCP tools, and the same dashboard. The differences are about ops, billing, and team features, not about what the agent can do. The intelligence engine is one codebase. Self-hosted and hosted run the same Python: same parsers, same git analysis, same wiki generation, same MCP tools. Pick whichever fits your team. ### Side-by-side Self-hosted Hosted (repowise.dev) **Install** `pip install repowise` None: sign in with GitHub **Storage** Local SQLite + LanceDB under `.repowise/` Managed Postgres + R2 **MCP server** Local stdio process Hosted HTTP endpoint, one URL for any editor **Auto-sync** Hooks, watch, your own webhook server GitHub App push-sync (automatic) **Multi-repo workspaces** Yes Yes **Cross-repo intelligence** Yes (per workspace) Yes (federated across all your repos) **Dashboard** `repowise serve` on `localhost:3000` repowise.dev/dashboard **Auth** None (local) Supabase (GitHub OAuth, email magic link) **Team features** Not available Seats & roles, pooled repos/credits, shared workspaces, portfolio health & ownership, engineering-leader dashboard **Billing** Free, AGPL Free / Pro / Teams / Enterprise **GitHub App for private repos** Not available One-click installer **Security suite** Local pattern scan Full suite: CVE scanning + reachability triage, secrets across git history, SBOM/VEX, nightly refresh, compliance reports, audit trail **Alerting** Not available Bell + email + signed Slack-compatible webhooks for security events and engineering signals **PR review bot** Not available Blast-radius + reviewer suggestions on pull requests **Privacy** Code never leaves your machine Stored encrypted in our infrastructure; BYOK keeps LLM calls direct **Pro-only on hosted** Not available Semantic search, docs explorer, coverage page, federated workspace chat ### Same agent experience Whichever you pick, your AI agent gets: The same ten MCP tools. The same proactive `PreToolUse` / `PostToolUse` hooks (if you're using Claude Code). The same auto-generated `CLAUDE.md` (with `generate-claude-md` on self-hosted, automatic on hosted). The hosted MCP endpoint adds **federated workspace queries**: `repo="all"` against your entire org's repos in one call. ### Pick self-hosted if Your code can't leave your network. You're an individual or small team and don't want a billing relationship. You want full control over the LLM provider, model, and embedding pipeline. You're comfortable with a Python install and one of the auto-sync options. ### Pick hosted if You want zero ops: managed indexing, managed webhooks, push-sync. You want federated cross-repo intelligence across your whole org without coordinating workspace setup yourself. You want the security suite: CVE scanning with reachability triage, secret detection across git history, SBOM/VEX, nightly refresh, compliance reports, audit trail. You're running a team: seats and roles, pooled repos and credits, portfolio health and ownership rollups, and the engineering-leader dashboard with drift alerting into Slack. You want the Pro analysis pages (semantic search, docs explorer, coverage, federated chat) and the PR review bot. **Hybrid is fine.** Run self-hosted on a laptop for one private repo and hosted for everything else. Same MCP protocol, same tool names. Your agent doesn't care which server answers. ### Self-hosted under the hood The hosted frontend (Next.js + Supabase Auth) talks to a hosted FastAPI backend over a typed REST client; it imports presentational components from `@repowise-dev/ui` and types from `@repowise-dev/types`, the same packages the OSS web UI uses. There's no fork: both modes share the engine. ## Configuration: config.yaml & ignore files URL: https://docs.repowise.dev/installation/configuration The .repowise/ directory, the config.yaml file repowise generates on first init, and how to control which files get indexed with .gitignore, nested .gitignore, .repowiseIgnore, and --exclude. Everything repowise knows about a repository lives in a `.repowise/` directory at the repo root, created on the first `repowise init`. The main configuration file is `.repowise/config.yaml`. repowise writes it for you during `init`, and you can edit it by hand afterwards. ### The `.repowise/` directory repowise adds `.repowise/` to your `.gitignore` automatically. It's a local cache, not a source of truth, so don't commit it. ### `config.yaml` Generated after the first `init` and updated when you pass flags like `--commit-limit` or `--follow-renames`. You can also edit it directly; changes take effect on the next `init`, `update`, `serve`, or `mcp` run. `config.yaml` has no schema validation. It's loaded as a plain YAML dict, so an unknown or misspelled key is silently ignored; it won't error and won't take effect. The only part that's validated is the `distill:` block, and only when you run `repowise doctor`. If a setting doesn't seem to take effect, check spelling and indentation first. Provider keys and a few runtime knobs are set via environment variables, not `config.yaml`. See Environment variables. Code-health rules are configured separately in `.repowise/health-rules.json`. ### The `distill:` block Controls output distillation for this repo. Everything defaults sensibly when the block is absent; `repowise doctor` validates it. `families` keys are filter names (`test_output`, `build_output`, `lint_output`, `git_status`, `git_log`, `git_diff`, `search_results`, `file_listing`, `logs`) and accept `ask | allow | off | deny`. Declining the `repowise init` opt-in prompt writes `commands.enabled: false`, so a rewrite hook installed globally from another repo stays inert here. Under Codex, only families set to `allow` are rewritten; its hook protocol has no ask-with-mutation (see Distill). ### The `refactoring:` block Controls the refactoring-intelligence layer: the structured Extract Class / Extract Helper / Move Method / Break Cycle / Split File plans surfaced by `repowise health --refactoring-targets`, `get_health(include=["refactoring"])`, and the web Refactoring tab. The deterministic layer is zero-LLM and runs in the `init` / `update` health pass. Code generation is the only part that calls a provider. It's on by default but never runs during indexing, only on an explicit request (set `llm.enabled: false` to disable it). `enabled: false` skips the whole deterministic detector pass; `detectors.disabled` silences named detectors while the rest keep running. `skip_tests`, `skip_infra`, and `include_submodules` are CLI-flag-only (`--skip-tests`, `--skip-infra`, `--include-submodules`) and they don't persist to `config.yaml`, so pass them again on each `init`/`update` run if you want the same exclusions. ### Controlling what gets indexed repowise decides which files to document using, in order: **`.gitignore`**: respected automatically, using the same `gitwildmatch` format git uses. repowise reads the **repo-root `.gitignore` *and* nested `.gitignore` files** in subdirectories, just like git: a `.gitignore` in any directory applies to that directory's contents. **`.repowiseIgnore`**: same syntax as `.gitignore`, for repowise-only exclusions you don't want in git. Honoured at the repo root and in any subdirectory. **`exclude_patterns` / `--exclude`**: extra patterns from the CLI, persisted to `config.yaml` and reapplied on every `update`. **Built-in exclusions** (always applied): `.git/`, `.repowise/`, `node_modules/`, `.venv/`, `dist/`, `build/`, `__pycache__/`, binary files, lockfiles, and minified assets (`*.min.js`, `*.min.css`). **Monorepos & yarn/npm workspaces**: because nested `.gitignore` files are honoured, a workspace package that keeps its own `.gitignore` (excluding that package's build output, generated bundles, coverage, etc.) is respected without any extra configuration. You don't need to duplicate those patterns at the repo root. Add extra patterns on the command line; they're saved to `config.yaml` and reused by later `update` runs: Or drop a `.repowiseIgnore` file at the repo root or in any subdirectory for granular control without touching `.gitignore`: You can also skip categories of files with flags: `--skip-tests` excludes test files, and `--skip-infra` excludes Dockerfiles, Makefiles, and shell scripts. ### Submodules Git submodule directories are excluded by default (repowise reads `.gitmodules` to detect them). Include them with: ## Environment variables URL: https://docs.repowise.dev/installation/env-vars Provider API keys, embedder overrides, and runtime knobs that configure repowise's behavior at install and index time. Most things are configured via `.repowise/config.yaml` (see Configuration; `repowise init` generates one for you). The handful of settings that make sense as environment variables are below. ### LLM provider keys **All optional.** `repowise init` never requires one: with no provider resolvable it renders the wiki from your code's structure and exits 0. Set a key when you want model-written prose instead. See Deterministic wiki. Pick one. Anthropic is the default; pass `--provider ` on `init` / `update` / `mcp` to switch, or set `REPOWISE_PROVIDER` / `REPOWISE_MODEL` to override without touching `config.yaml`. Variable Used by `ANTHROPIC_API_KEY` Default provider `OPENAI_API_KEY` `--provider openai` `GEMINI_API_KEY` / `GOOGLE_API_KEY` `--provider gemini` `OPENROUTER_API_KEY` `--provider openrouter` `DEEPSEEK_API_KEY` `--provider deepseek` `LITELLM_API_KEY` / `LITELLM_API_BASE` `--provider litellm` `OLLAMA_BASE_URL` `--provider ollama` (default `http://localhost:11434`) Base URLs can also be overridden per provider: `ANTHROPIC_BASE_URL`, `OPENAI_BASE_URL` (used for vLLM/SGLang-compatible endpoints), `GEMINI_BASE_URL`, `DEEPSEEK_BASE_URL`, `LITELLM_BASE_URL`. Variable Purpose `REPOWISE_PROVIDER` Override provider, skips auto-detection. An empty value (`REPOWISE_PROVIDER=""`, common in CI matrices) is treated as unset rather than as a provider named `""` `REPOWISE_MODEL` Override model `REPOWISE_DOC_MODEL` Override the model used for `get_answer` synthesis specifically `REPOWISE_REASONING` Override `reasoning` (`auto`, `off`, `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`) Repowise also persists provider/model choice into `.repowise/state.json` during `init`, so the MCP server and `update` runs reuse the same provider without you re-specifying. ### Embedder overrides The embedder powers semantic search and the RAG behind `get_answer`. It's separate from the LLM provider, and defaults to `mock` (no semantic search) when no key is detected. Variable Notes `REPOWISE_EMBEDDER` Embedder: `gemini`, `openai`, `ollama`, `openrouter`, or `mock` `REPOWISE_EMBEDDING_MODEL` Embedding model, applies to whichever embedder is active `REPOWISE_EMBEDDING_DIMS` Embedding output dimensions (optional; inferred from the model otherwise) `REPOWISE_EMBEDDING_TIMEOUT` Embed request timeout in seconds `OLLAMA_EMBEDDING_MODEL` Ollama embedding model (also selects the `ollama` embedder) `OLLAMA_EMBEDDING_DIMS` Ollama embedding output dimensions (optional) `OLLAMA_EMBEDDING_TIMEOUT` Ollama embed request timeout in seconds (default: `30`). Raise it for long wiki pages on slow local models, otherwise those pages can silently drop out of the vector store. `repowise init` auto-detects which embedder to use based on which key is set. ### Server and database Variable Default Purpose `REPOWISE_DB_URL` SQLite Use PostgreSQL instead of SQLite (e.g. `postgresql+asyncpg://...`) `REPOWISE_DATABASE_URL` none Legacy alias for `REPOWISE_DB_URL`, still honored `REPOWISE_HOST` `127.0.0.1` API server host `REPOWISE_PORT` `7337` API server port `REPOWISE_MCP_PORT` `7338` MCP SSE server port `REPOWISE_API_URL` `http://localhost:7337` Frontend only; backend URL for the web UI `REPOWISE_API_KEY` none Bearer token required by clients calling the server API `REPOWISE_CONFIG_DIR` none Override where repowise looks for its config directory ### Telemetry Anonymous usage telemetry is **enabled by default** (opt-out). Variable Purpose `DO_NOT_TRACK` Any truthy value disables telemetry (respects the cross-tool convention) `REPOWISE_TELEMETRY_DISABLED` Disables telemetry, repowise-specific `REPOWISE_TELEMETRY_DEBUG` Prints the telemetry payload to stderr instead of sending it ### Misc Variable Purpose `REPOWISE_GIT_WINDOW_ANCHOR` Set to `head` to anchor git "now" to the latest commit instead of wall-clock time `REPOWISE_SKIP_EDITOR_SETUP` Skip the interactive editor/MCP setup step `REPOWISE_CHANGELOG` Override the changelog source used by the "what's new" check `PYTHONIOENCODING` On Windows PowerShell, set to `utf-8` if you see codec errors during indexing ### Hosted version If you're using repowise.dev, none of the above apply, because the platform manages keys for you. The only env var you'd set client-side is the API key your editor uses to talk to the hosted MCP endpoint, which the Settings → Editor page generates automatically. **BYOK on hosted.** Under Settings, you can attach your own Anthropic, OpenAI, or Gemini key. Repowise never sees your LLM calls; they go directly from our infrastructure to your provider. ## Install repowise URL: https://docs.repowise.dev/installation/install Install the repowise CLI on macOS, Linux, or Windows via pip or uv. Verify, upgrade, switch versions, or uninstall. Every step. The repowise CLI is a Python package. You can install it with `pip`, or (recommended) with `uv`, which puts the binary into an isolated environment without touching your system Python. Before installing, make sure you've got Python 3.11+ and Git 2.30+. ### Install `uv tool install` puts the binary in an isolated, uv-managed venv on `PATH`. No conflicts with system Python, no `requirements.txt` to maintain, fastest install path. If you don't have `uv` yet: Installs into your active Python environment. Fine for project-scoped installs (in a venv); not ideal for a global system install, since there's no isolation from your other Python tools. If you see a `Defaulting to user installation` message, the binary may land in `~/.local/bin` (Linux/macOS) or `%APPDATA%\Python\Scripts` (Windows). Add that to `PATH`. Like `uv tool install`, this isolates the binary in its own venv. Use it if you already standardise on `pipx` for CLI tools. ### Verify You should see something like `repowise 0.6.0`. If `command not found`, your `PATH` is missing the install location. See Troubleshooting → command not found. ### Optional extras **Every LLM provider works out of the box.** The Anthropic, OpenAI, Google, and LiteLLM SDKs are base dependencies, so there is nothing extra to install to use Claude, GPT, Gemini, Ollama, or any OpenAI-compatible endpoint. Just set the API key. See Environment variables. A provider is optional: `repowise init` runs and produces a full wiki without one. Two extras exist, and neither is needed for a normal install: Extra What it adds When you want it `postgres` `pgvector` + `asyncpg` Storing the index in PostgreSQL instead of the default SQLite. See Configuration. `graph-extra` `graspologic` Leiden community detection. Without it, repowise falls back to Louvain via networkx, which is already bundled. ### Upgrade Run `repowise --version` again to confirm, then run `repowise update` in your repo so the new build picks up your existing index. Upgrades keep that index working (no reindex in the normal case), and a full reindex is only ever *recommended*, never forced. See Upgrading for the full flow. Not sure if you're up to date? `repowise doctor` prints a `CLI version` row that compares your installed CLI against PyPI and suggests the right upgrade command for your install method. This is handy when an MCP client is silently running an older `repowise` from your `PATH`. ### Pin to a specific version The full release history is on PyPI. ### Uninstall The CLI is gone, but your `.repowise/` directories are untouched. Delete them by hand if you want to reclaim the disk space: ### Editable install (for contributors) Hacking on repowise itself? Clone the OSS repo and install with `uv` in editable mode: Or activate the venv `uv sync` created: See CONTRIBUTING.md in the OSS repo for the full developer setup, including how to add a language and how to add a new LLM provider. ### What's next **Index your first repo**: head to the Quickstart and run `repowise init --yes`. No API key needed. Repowise builds the graph, git, health and dead-code layers and renders a complete wiki from that structure. **(Optional) Set an API key**: a provider upgrades the wiki to model-written prose and, with an embedder, semantic search. Environment variables lists every key and provider option. You can add it after the fact and upgrade pages in place, no re-index needed. **Connect Claude Code**: `repowise init` already wrote `.mcp.json` and registered the server. Restart Claude Code and you're done. **Don't want to install Python at all?** The hosted version at repowise.dev runs the same engine on managed infrastructure. Sign in with GitHub, paste a repo URL, you're done. Same MCP tools, same dashboard, no install. ## Language support URL: https://docs.repowise.dev/installation/languages 16 languages with AST support and dedicated resolvers, 11 of them at the Full tier, plus per-language framework awareness for Django, FastAPI, Flask, Express, Spring Boot, Rails, Laravel, and more. Repowise ships language-aware resolvers under `packages/core/src/repowise/core/ingestion/resolvers/`. Each tier provides a different depth of analysis; lower tiers fall back to the generic resolver (file and symbol extraction, no import edges). ### Coverage matrix Tier Languages What works **Full** Python · TypeScript · JavaScript · Java · Kotlin · Go · Rust · C++ · C# · Scala · Ruby AST parsing, import resolution, named bindings, call resolution, heritage extraction, docstrings; multi-project workspace resolvers (`.csproj`/`.sln` for C#, `Cargo.toml [workspace]` for Rust, `go.mod` multi-module, `package.json` workspaces, Gradle/Maven for JVM); framework-aware edges (Django, FastAPI, Flask, ASP.NET, Spring, Express/NestJS, Next.js, Gin/Echo/Chi, Axum/Actix, Rails); per-language dynamic-hint extractors for runtime DI / reflection / plugins; **code-health markers** **Good** C · Swift · PHP · Dart AST parsing, import resolution, named bindings, call resolution, heritage (Swift extension conformance, PHP trait use, Dart mixins), docstrings; dedicated workspace-aware resolvers (SPM, composer PSR-4, pubspec.yaml); Laravel / TYPO3 / Flutter framework edges. Dart also gets **code-health markers** **SQL / dbt** `.sql` via a dedicated sqlglot handler Tables/views/functions/procedures as symbols with wiki pages; dbt projects get real `ref()`/`source()` lineage; app-to-database contracts in workspace mode **Shell** `.sh` · `.bash` · `.zsh` Function definitions as symbols, `source` / `.` import edges (including `$SCRIPT_DIR` and `$(dirname "$0")` idioms), and function-level complexity markers. No class metrics, heritage, bindings, or dead-code flagging **Config / data** OpenAPI · Protobuf · GraphQL · Dockerfile · Makefile · YAML · JSON · TOML · Terraform · Markdown Included in the file tree; special handlers extract endpoints/targets where applicable **Lightweight** Elixir · Clojure · Haskell · Lean 4 · Erlang · F# Regex-tier file-level import graph only, no symbols or calls **Partial** Luau / Roblox AST symbols + `require()` resolution (Rojo / `.luaurc` aware); no health markers yet **Structural** Objective-C · R · Zig · Julia · Elm · OCaml · Crystal · Nim · D Git history only (blame, hotspots, co-change); no AST parsing **16 languages parsed to AST, 11 of them at the Full tier** (plus Luau at partial tier). The eleven Full-tier languages plus Dart also get the code-health marker suite. Scala's import resolution is partial: it shares the JVM index with Java and Kotlin, with SBT/Mill build-file parsing as a fallback. ### Framework awareness Several languages get extra treatment: repowise recognises common framework conventions and emits edges for them, even when the underlying call goes through a decorator or a runtime registry. Language Frameworks **Python** Django (URL patterns, models, signals), FastAPI (route handlers, dependency injection), Flask (route decorators) **C#** ASP.NET (controllers, attributes), dependency injection containers **Java / Kotlin** Spring Boot (`@RestController`, `@Component`, `@Autowired`) **JavaScript / TypeScript** Express, NestJS (`@Controller`, `@Module`, `@Injectable`) **Go** Gin, Echo, Chi router patterns **Rust** Axum, Actix routes **Ruby** Rails (Zeitwerk autoloading, route DSL) **PHP** Laravel routes, TYPO3 conventions **Dart** Flutter route tables, `runApp()` edges ### Dead-code awareness Repowise's dead-code detector knows about dynamic dispatch patterns that look "unused" to a static analyzer but aren't: Naming patterns: `*Plugin`, `*Handler`, `*Adapter`, `*Middleware` Dynamic imports: `importlib.import_module()`, `__import__()`, dynamic `require()` Framework convention files (Flask blueprints, FastAPI routers, Django apps, Rails controllers, Laravel providers, TYPO3 extensions) These are excluded from `safe_to_delete` findings to keep the false-positive rate near zero. ### Code-health marker rollout Code-health markers, Extract Method (dataflow), and the performance signal each roll out per language independently, since they run off a separate complexity-walker map rather than the `.scm` grammar: Signal Coverage Complexity, class metrics, assertion smells All Full-tier languages, plus Dart Performance risk (`io_in_loop`, etc.) Python, TypeScript/JavaScript, Java, Go, C#, Rust, Dart; Kotlin and C++ pending Extract Method (dataflow) Python, Go, TypeScript/JavaScript, Java, Rust; Kotlin, C++, and C# pending ### Adding a language Adding new language support requires one tree-sitter `.scm` query file and one entry in the language registry. **No changes to the parser core.** See `CONTRIBUTING.md` in the OSS repo for the recipe. Working in a language we don't list? Repowise still indexes the file tree, ownership, and churn; you just won't get import edges or framework-aware analysis. Open a Discussion and we'll prioritise. ## Requirements URL: https://docs.repowise.dev/installation/requirements System and toolchain requirements for self-hosted repowise, covering Python, Git, disk, and an LLM provider key. ### System Requirement Notes **Python 3.11+** 3.12 recommended. Verify with `python --version`. **Git 2.30+** on `PATH` Repowise reads commit history; older Git is missing flags it relies on. **\~2 GB free disk** For the index of a medium repo (3,000 files). Larger repos scale roughly linearly. **An LLM provider key** Anthropic, OpenAI, Gemini, or local Ollama. See Environment variables. Officially tested on macOS, Linux, and Windows (PowerShell). WSL2 works the same as native Linux. ### Languages You don't need the language toolchain installed for the language you're indexing, because repowise parses source statically with tree-sitter. The one exception is **TypeScript monorepos**, where having `tsc` available improves resolver accuracy for path-mapped imports. See Language support for the full 15-language coverage matrix. ### LLM provider (optional) **Not a requirement.** `repowise init` never needs an API key. Without a provider it renders the whole wiki from your code's structure and exits 0. You get the graph, git signals, hotspots, ownership, code health, dead code, decision archaeology, and a complete set of wiki pages. See Deterministic wiki. A provider is what buys you model-written prose and, with an embedder, semantic search. When you want that, bring the key: **Anthropic**: default. `ANTHROPIC_API_KEY=sk-ant-...` **OpenAI**: `OPENAI_API_KEY=sk-...` plus `--provider openai` **Gemini**: `GEMINI_API_KEY=...` plus `--provider gemini` **Ollama**: fully offline. `--provider ollama`, no key needed. To guarantee a run spends nothing even when a key is present in the environment, pass `--docs deterministic` (or the older `--index-only`). ### Optional but useful **`uv`** for an isolated install (`uv tool install repowise`). **A second machine for hosted indexing**: if you'd rather not run Python at all, the hosted version manages all of this for you. ## Troubleshooting URL: https://docs.repowise.dev/installation/troubleshooting Diagnose a broken index with repowise doctor, plus the most common install and indexing problems with their fixes. ### First, run `repowise doctor` `doctor` validates the git repo, the `.repowise/` directory, the SQLite + vector + FTS stores, the persisted provider config, and checks for stale pages. `--repair` fixes most mismatches automatically. For most issues, this is the only command you need to run. ### "command not found: repowise" Your shell can't find the binary. If you used `pip install --user`: add `~/.local/bin` (Linux/macOS) or `%APPDATA%\Python\Scripts` (Windows) to `PATH`. If you used `uv tool install`: ensure `~/.local/bin` is on `PATH`. Verify with `which repowise` / `where repowise`. ### "ANTHROPIC_API_KEY is not set" `repowise init` does not need one. Without a resolvable provider it renders the wiki from your code's structure and exits 0, so a missing key is never what stopped an `init` run. `update` in docs mode, `generate`, `restyle`, and `health --generate-code` do need a provider. To set one: To index with no model in the loop at all: ### `REPOWISE_PROVIDER` is set but ignored An empty value is treated as unset, not as a provider named `""`. CI matrices routinely export `REPOWISE_PROVIDER: ""` for the keyless arm, and that resolves to normal auto-detection rather than an error. ### An `init` prompt aborted the run in CI It no longer does. If the first interactive prompt reads EOF, which is what happens when an agent or a CI job pipes stdin, `init` prints a notice and continues with defaults. The cost gate behaves the same way: it never prompts when stdin is not a terminal. It auto-declines, keeps the index it already built, and renders the wiki from structure. `repowise init --yes` is the command to reach for in a script. ### Indexing hangs or times out **Checked-in minified bundles** (webpack/rollup/storybook output and similar) pack thousands of near-identical tokens onto a few huge lines and used to stall the duplication/health pass. repowise now detects and skips minified/generated files automatically, but the cleanest fix is to keep them out of the index: they're already excluded if your `.gitignore` ignores them (repowise reads **nested `.gitignore` files**, so a per-package `.gitignore` in a monorepo works), or exclude explicitly with `repowise init -x '**//**'`. **Tree-sitter crash on a generated file**: exclude with `repowise init -x 'src/generated/**'`. **Submodules being scanned unexpectedly**: they're skipped by default; only included with `--include-submodules`. **Network flakiness on LLM calls**: re-run `repowise init`; it's idempotent and resumes from the last checkpoint with `--resume`. ### Claude Code can't see the MCP tools Confirm `.mcp.json` exists at the project root (`repowise init` writes it). Confirm `~/.claude/settings.json` registers the server. Restart Claude Code. Run `repowise doctor`. It cross-checks both files. If the agent uses `Grep` and `Read` instead of calling `get_overview`, the server didn't connect. ### Wiki feels stale after a big merge Or pass `--force` to `repowise init` to regenerate everything. ### Windows: codec errors during indexing Set UTF-8 encoding before `init`: ### Store drift (`SQL count` ≠ `vector count`) `reindex` rebuilds the vector store from the wiki. Embedding-only, no LLM cost. ### Hosted: indexing stuck on "queued" Refresh the dashboard. If the status doesn't move within \~5 minutes of submission, contact us and we'll check the queue manually. Still stuck? Capture `repowise doctor` output and the last 50 lines of `.repowise/logs/repowise.log` and open an issue on GitHub or hop into Discord. ## Auto-generated wiki URL: https://docs.repowise.dev/intelligence/auto-wiki How repowise writes a documentation page for every module and notable file: incrementally, with citations, with confidence scoring, and refreshed in under 30 seconds per commit. The wiki is repowise's documentation layer. An LLM writes a Markdown page for every module and every notable file at index time, then keeps them current incrementally on every commit. Pages cite the source ranges they're describing, get a confidence score, and are re-generated only when the underlying code changes meaningfully. ### What gets written Three page types: **File pages**: one per source file (skipping fixtures, tests if configured, and tiny files). Documents structure, key symbols, imports, and intent. **Module pages**: one per directory or logical cluster. Documents architecture, child files, and entry points. **Symbol spotlights**: for high-importance symbols (high PageRank, many callers). Documents purpose and usage. Pick a **wiki style** to change the voice without re-indexing: `comprehensive` (full narrative, the default), `reference` (signature-dense, minimal prose), `tutorial` (guided, beginner-facing), or `caveman` (token-condensed, AI-first fragments, \~70% smaller). ### Docs that follow your questions The page budget isn't spread evenly. repowise reads which modules you and your agent actually ask about, from `get_answer` citations and `search_codebase` hits, and tilts the file-page budget toward the modules in demand, so depth lands where you work instead of spreading flat. The total is conserved, every module keeps a floor, and a fresh repo with no session history generates byte-identically to before. It's one half of how repowise learns from how you use it; the other is session-mined decisions. ### What goes into the prompt The LLM doesn't just see source. It sees: The file's parsed structure (classes, functions, signatures). Its imports and what imports it. Its top callers and callees with confidence scores. The 10 most significant commit messages from its history (filtered of merges, dependency bumps, lint runs). Ownership and trend signals. Cross-references to existing wiki pages it should link to. That's the recipe for documentation that explains *why*, not just *what*. ### Citations Every page references the source ranges it's describing. The MCP `get_context` tool can pull the cited source back when the agent needs to verify. ### Confidence and freshness Each page carries a `confidence_score` and a `freshness_status`. The score reflects how well the underlying source maps to what the page claims. Pages drift over time as code changes; freshness is how recently the page was regenerated relative to the file's last meaningful change. Both surface through `get_context(include=["freshness"])`, and they're included by default for exactly this reason. ### Incremental regeneration `repowise update` finds the files changed since the last sync, walks the dependency graph to find affected wiki pages, and regenerates only those. A typical single-commit update touches 3 to 10 pages and finishes in under 30 seconds. There's a `cascade-budget` knob that caps how many pages a single update may regenerate (auto-scaled if unset), useful for very large refactor commits where you'd otherwise regenerate hundreds of pages. ### Search The wiki is indexed two ways and searched as hybrid RAG: **SQLite FTS**: exact keyword search. **LanceDB vector store**: semantic search via embeddings (Gemini, OpenAI, OpenRouter, or Ollama). Auto-detected from your environment; it falls back to `mock`, meaning no semantic search, when no embedding key is found. Results from both are merged via Reciprocal Rank Fusion, biased by PageRank, and expanded one hop along the dependency graph before ranking. Both feed `search_codebase` and `get_answer`. ### When no model is in the loop This page describes the model-written wiki. There is a second way to produce the same page set, and it is the default when no provider is configured: repowise renders every page from the parsed AST, the dependency graph, and git history instead of prompting a model. `repowise init` never requires an API key. Without one it renders the deterministic wiki and exits 0. You can also ask for it directly with `--docs deterministic` (or the older spelling `--index-only`), which is what free-tier, CI, and air-gapped runs want. What you give up is the prose, the paragraph that explains *why* a file is shaped the way it is, plus semantic search until an embedder is configured. Everything else, hotspots, ownership, dead code, the dependency graph, code health, and decision archaeology, is identical. Upgrading is in place and incremental: `repowise generate` writes any subset of pages with a model, `repowise update --full` does the whole wiki at once. Neither re-indexes from scratch. Full detail in Deterministic wiki. **No telemetry on what we generate.** Self-hosted, your code never leaves your machine. Hosted, the LLM provider sees the prompt (structure, signatures, commit messages) but Repowise does not log or train on it. ## Bug-fix history URL: https://docs.repowise.dev/intelligence/bug-history Which files and functions have actually been bug-fixed, how often, and how recently, computed from git alone with a fix-shape classifier validated at 98.3% on 240 hand-labelled commits. Churn tells you a file changes a lot, which is often just where the work is. Bug-fix history tells you a file *breaks* a lot, which is a different and more actionable thing. Repowise records which files and which functions have actually been fixed, how recently, and how often, then hands you a small set of honest numbers: a per-file fix count over a trailing 180-day window, a per-symbol breakdown, a decayed "bug magnet" flag, and the age of the most recent fix. **No LLM calls.** This is git history, a `-U0` diff pass, and arithmetic, run inside the existing git phase of `repowise init` and `repowise update`. On this repo the top bug magnets (`pipeline/persist.py`, `pipeline/incremental.py`, `dead_code/analyzer.py`, `update_cmd/command.py`) match the churn hotspot list, arrived at independently from bug fixes rather than from commit counts. ### What counts as a bug fix A commit whose subject matches the fix keywords is a candidate, not a fact. Plenty of `fix:` commits fix a README typo, tighten a test, or bump a version, and counting those inflates every downstream number. So each candidate's `-U0` diff is classified into one shape, and only one shape counts. Shape Counted Example `code_fix` yes production source lines changed `test_only` no only files under `tests/` or matching a test naming rule `doc_only` no only `.md` / `.mdx` / `.rst` / `.txt` / `.adoc` or `docs/` `config_other` no only lockfiles, CI YAML, `*.config.*`, dotfile rc `comment_only` no code files touched, but the changed lines are comments or docstrings `empty` no merge commits and no-op diffs The comment-only rule is line-level, not path-level: it strips trailing comments and compares the code part of each removed and added line, so a commit that rewords a docstring in a `.py` file does not count as a bug fix. The classifier was validated against **240 hand-labelled fix commits across four repos** (repowise, flask, django, zod) and agrees with the labels **98.3%** of the time (repowise, flask and django all 60/60; zod 56/60). The four residual disagreements are all the same shape, "a file with a code extension changed but no product code did", and were left as honest disagreements rather than closed with repo-specific ignore lists. The effect varies enormously by repo. On flask, **58.7%** of keyword-matched fix commits are noise, and filtering removes half the raw attributions. On repowise it is 7.0%. That is the point: a number that means the same thing in both repos is worth more than a bigger number in one. `GitMetadata` keeps both `prior_defect_count` (filtered) and `prior_defect_raw_count` (unfiltered), so the delta stays inspectable. Filtering deliberately did not change the health score. Re-running the defect-weight calibration on the 21-repo corpus showed it moves pooled OOF AUC by +0.0002, inside noise, so the `prior_defect` marker stays at weight 1.0. ### Per-symbol attribution Each counted fix produces one row per file it touched in a `fix_events` table, carrying the line ranges the fix replaced, numbered on the fix's own parent commit. Persisting the events, rather than only a count, is what makes per-symbol attribution possible later without re-walking git. Those replaced ranges are matched against the symbol spans in each file, producing a per-file map of which function or class absorbed each fix. Repo Events In-envelope rate django 2,179 97.4% flask 125 96.3% zod 337 81.8% repowise 1,145 96.8% "In-envelope" means the event's lines land somewhere between the file's first and last indexed symbol. Gaps *between* symbols still count as misses, so this stays a test of the join rather than a restatement of it. The misses were measured, not argued: django and flask are line drift (symbol spans are at HEAD, fix ranges are at each fix's parent, and 99.8% of django's events are 3+ years old), and zod is symbol density in test files the parser indexes with one or two named symbols. Symbol counts are **approximate**, and every surface says so. Symbol spans are current-tree, fix ranges are historical. Read them as "mostly here", not as an exact ledger. ### The bug magnet rollup Each file's counted fixes collapse into one decayed mass: The 90-day half-life came from a sweep of 60 / 90 / 180 days against the 21-repo calibration corpus. Decay was the only lever that moved the `prior_defect` coefficient at all (0.15 undecayed to 0.23 decayed); 90d and 180d tied inside noise, and 90d is the tighter of the two. Read the threshold with the decay in mind. Only a same-day fix is worth a full 1.0, so three real fixes spread over a couple of weeks land near 2.9 and do **not** flag. In practice the flag needs four recent fixes, or three very recent ones. That is deliberately the conservative end: the flag exists to interrupt someone mid-edit, so it should be rare enough to be worth reading. The rollup recomputes the whole repo on every index and update rather than patching only the files an update touched, because decay ages a rollup with nothing in the file changing. It costs about 0.25s on this repo (1,172 events, 739 files): two indexed queries and arithmetic. ### The recency contract One rule keeps the feature honest, and it is enforced in the type definitions rather than left to each surface: > `bug_magnet` is the decayed fix mass past its trigger, so it is a recency > claim. Any copy that shows it must show `last_fix_at` too. Two consequences: **A magnet claim never appears without its age.** If `last_fix_at` is null, the flag is dropped rather than shown unanchored. **The surface goes silent outside the window.** The pre-edit hook does not fire at all when the last fix is older than 180 days, no matter how large the historical count is. "This file was fixed nine times, in 2019" is not a warning, it is trivia. ### Pre-edit hook When an agent is about to edit a file with a real recent run of fixes, one line goes into its context: Three gates must all hold: at least 3 counted fixes, a last fix inside 180 days, and one claim per file per session (an atomic ledger, so two racing hook processes cannot double-fire). A file that also has a governing architectural decision emits two lines, never more. Both the Claude Code and Codex hook paths are wired up. ### `get_risk` Files with counted fixes gain a `defect_profile` block: `bug_magnet` appears only when true, `top_symbols` is the top three with the path prefix stripped, and the whole block is omitted on repos with no fix data. Measured at 46 tokens mean, 80 worst case, against a 150-token ceiling across 803 files. Shipping `defect_profile` also retired the old keyword `risk_type="bug-prone"` derivation, which used to scan commit subjects for `/fix|bug|patch/`, counted doc and test commits, had no recency, and disagreed with the count every other surface showed. It now reads `bug_magnet` or `prior_defect_count >= 3`. That does silently reclassify some files: a high-traffic file with 3 fixes in 200 commits now reads `bug-prone` where it read `churn-heavy`. ### `get_change_risk` A diff or commit range gains a `prior_fixes` block: per changed file, how many past fixes it carries and how many of the change's lines fall inside a past fix's replaced ranges. The per-file counts are exact (counted by `COUNT(DISTINCT fix_sha)`, so one commit fixing three files reports one fix, not three). The line overlap is labelled `approximate` in the payload, because past ranges are numbered on their own parent commit. Files rank by overlap then count, and the list carries a `truncated` flag rather than silently dropping the tail. ### Dashboard and editor **Health drawer**: a collapsed **Bug history** section with per-symbol counts, the last-fix age on the toggle, and an approximation footnote. **File signals panel**: the bug-fix tile gains a **Bug magnet** badge and folds the last-fix age into its caption. **Symbol detail**: a **Bug fixes** stat tile beside **Modifications**. How often something changes next to how often it breaks is the contrast that earns the cell. **Symbols list**: a **Bug-fixed** facet and a per-row fix chip. The filter is symbol-level, unlike the file-level filters beside it, because a bug-fixed file says very little about the one function you are reading. **VS Code**: one line on the file hover, off the same signals block. ### What was measured and deliberately not shipped The most useful thing this layer can tell you is what it refuses to tell you. ### SZZ inducing-commit attribution: built, measured, deleted The obvious next step from "this line was fixed" is "and here is the commit that introduced the bug". That is the SZZ algorithm, and it was fully built: a blame pass walking each fix's replaced lines back through history, refactor-aware, with overlap-based ranking of the candidates. Then it was measured against a hand-labelled set. Fifty-three judged rows, five reviewers. **File-level SZZ tops out at 74.5% top-candidate precision on that corpus. The gate was 80%.** 74.5% is not a bad algorithm; it is a *good* SZZ implementation. It is also not good enough to put a commit SHA and a person's name in a UI, because one time in four the UI would accuse the wrong commit and the reader has no way to tell which time. So the blame pass was deleted, `szz.py` is gone, and **no repowise surface names an inducing commit.** The planned inducing-commit tail on `get_change_risk` and the inducing-commit link on commit rows were both cut. The findings are kept because they are reusable by anyone attempting this again: **Refactor-aware blame is worth building.** Walking through behaviour-preserving moves to the parent lifted strict precision from 70.6% to 74.5%. All 14 of the initial false calls were refactors inheriting moved lines. **Overlap ranking beats earliest-commit ranking by 12 points** on judged rows. Earliest-commit's apparent 80% was an artefact of its wrong answers going unjudged: 7 of its 16 unknowns were this repo's initial commit, and all 7 came back "not plausible" once judged. **The two residual failure modes are properties of SZZ, not bugs.** An initial import has no earlier commit to name, and package splits that move lines wholesale while re-sorting imports defeat the carried-through test on exactly the lines that moved. Removing the pass also gave back 9.1s of index time on this repo and 5.9s on zod. Restoring the tracer is a `git revert` of one commit, not a re-derivation, so if someone finds a ranking that clears 80% on the frozen label set, the data layer is ready for it. ### "AI vs human introduced bugs": cut A repo-level card comparing defects introduced by AI-authored commits against human-authored ones, per KLOC, was planned and gated on a concentration check before build. The check failed. **The top 5 inducing commits held 30.3% of all traced mass against a 20% ceiling, with the initial import alone at 13.9%.** SZZ error does not average out: when blame concentrates on a handful of enormous commits, any aggregate built on inducing commits inherits that concentration, and it becomes mostly a statement about who authored the repo's five biggest commits. A stat like "AI introduces N% more bugs" is exactly the kind of number that gets screenshotted, which raises the bar rather than lowering it. So it was killed before it was built. ### What survived Counts and recency survived. Accusations did not. Everything shipped here answers "this code has been broken before, recently, and roughly here", and nothing answers "and it was your fault". The first question is answerable from git with measurable accuracy. The second is not, yet. ### Limitations **Symbol counts are approximate.** Current-tree spans against historical line ranges, stated on every surface that shows them. **Fix detection is keyword-matched.** A bug fixed in a commit whose subject does not say so is invisible. The shape filter improves precision, not recall. **The 180-day window is fixed.** A file fixed heavily two years ago and quiet since reads as clean, which is intentional but is a choice, not a truth. **Workspace lookup in the hook does not filter by `repository_id`,** matching the co-change query beside it. In a workspace whose members lack their own `.repowise` this degrades to silence rather than a wrong answer. **The hook's usefulness is unproven.** It shipped without the planned week of live-session dogfooding, so whether the notice changes behaviour or becomes ignorable noise is still open. If it is noise, the plan is to cut or reword the hook surface and keep every data layer beneath it. ### See also Code health, the `prior_defect` marker and the "does the score find the bugs?" self-check that reads the same counts. `get_risk`, where `defect_profile` lands. MCP overview for the rest of the tool surface. ## Code health URL: https://docs.repowise.dev/intelligence/code-health A 1 to 10 health score for every file from deterministic markers across three signals: defect risk, maintainability, and performance. Zero LLM calls, defect-calibrated weights, validated to out-rank the leading commercial code-health tool at predicting real bugs. Code health is repowise's deepest differentiator. Linters check patterns. The health score predicts which files are likely to harbor the next bug, ranked and validated forward in time against a real defect corpus, and benchmarked head-to-head against the leading commercial tool in the space. Repowise scores **every file from 1 to 10** from **deterministic markers** computed over tree-sitter ASTs and git history, surfaced as **three orthogonal signals**: defect risk, maintainability, and performance. No LLM calls, no cloud requirement, no new runtime dependencies, just pure Python that finishes in **under 30 seconds on a 3,000-file repo**. ### The markers Each file starts at 10.0; marker findings deduct from the score, with a cap per category so no single category can dominate. Category Markers **Structural complexity** `brain_method`, `nested_complexity`, `bumpy_road`, `complex_conditional`, `complex_method`, `large_method`, `primitive_obsession` **Cohesion & size** `low_cohesion` (LCOM4), `god_class` **Duplication** `dry_violation` (native Rabin-Karp clone detection) **Error handling** `error_handling` (empty catches, swallowed errors, bare panics) **Test coverage** `untested_hotspot`, `coverage_gap`, `coverage_gradient` **Test quality** `large_assertion_block`, `duplicated_assertion_block` **Organizational / git** `developer_congestion`, `knowledge_loss`, `hidden_coupling`, `function_hotspot`, `code_age_volatility`, `ownership_risk`, `churn_risk`, `change_entropy`, `co_change_scatter`, `prior_defect` **Performance** `io_in_loop` (N+1), `string_concat_in_loop`, `blocking_sync_in_async`, `resource_construction_in_loop`, `serial_await_in_loop`, and more (see the performance signal) The three repo-level KPIs (all for the defect-risk signal): **Hotspot Health.** NLOC-weighted average over the files the git layer classifies as hotspots (high churn percentile plus minimum-activity floors). **Average Health.** NLOC-weighted average over all files. **Worst Performer.** The single lowest-scoring file. ### Calibrated, not hand-tuned The marker **weights are learned offline from a real defect corpus**. Each file is scored at the commit immediately *before* a 6-month defect window (T0, so the measurement can't leak future information), and an L2-regularized logistic regression, with file size (NLOC) as an explicit control, fits each marker's defect lift *beyond* size. Only the learned constants ship; the runtime stays fully deterministic. The strongest calibrated predictors: `co_change_scatter`, `change_entropy`, `ownership_risk`, and `nested_complexity`. ### Three health signals: defect risk, maintainability, performance The score above is the **defect-risk** signal: calibrated against a defect corpus, with bands tuned to it (Alert files carry roughly 17× the defect rate of Healthy files). It is the overall number surfaced everywhere. But not every code smell predicts bugs, so repowise computes **two co-equal companion signals from the same marker stream**, never blended into the defect headline. **Maintainability.** A handful of markers fire widely and matter a lot for how hard code is to read and change, yet proved weak as defect predictors under leakage-free scoring, so the defect calibration *floors* them (`low_cohesion`, `brain_method`, `primitive_obsession`, `dry_violation`, `error_handling`). Floored inside a defect score they get no credit for the real problem they describe. The maintainability signal deducts them at **full weight** against its own expert-set caps, so the smell is scored where it actually lives. Structural smells that are *both* defect predictors and core maintainability concerns (`god_class`, `large_method`, `nested_complexity`) count toward both. **Performance.** Static performance *risk* (see below): high-precision, low-recall, always advisory, never folded into the defect number. The signals are computed by one shared scoring kernel against independent weight/category/cap tables and **never feed back into each other**. The overall surfaced score stays exactly the defect score (a golden test locks this byte-for-byte). Every finding carries a `dimension` (`defect` / `maintainability` / `performance`) naming the pillar it homes under, so findings can be filtered per signal, in the dashboard, the CLI, and the `get_health` MCP tool. ### Performance: static performance risk The third signal flags **shapes that waste work**, code whose structure does redundant I/O rather than measured runtime. It is deliberately **high-precision, low-recall**: a few real findings the rest of the toolchain can trust beat a wall of maybes. The headline detector is `io_in_loop` (the N+1): a database call, network request, filesystem read, or subprocess spawn that runs once per loop iteration. Two things make it more than a file-local lint: **Dependency classification.** The loop-nested call is resolved through a shared I/O-boundary classifier (`db` / `network` / `filesystem` / `subprocess` / `lock`) and only fires on a *classified* execution sink (an actual round-trip), not a query-builder chain or a same-named pure helper. **Call-graph reachability.** The loop and the I/O call need not be in the same function. A bounded-depth (≤3 hops) walk over the resolved call graph catches the interprocedural case no file-local linter can see; cross-function findings carry their resolved `caller -> ... -> sink` path. Alongside it: `string_concat_in_loop`, `blocking_sync_in_async`, `resource_construction_in_loop`, `lock_in_loop`, `serial_await_in_loop`, `membership_test_against_list_in_loop`, `nested_loop_with_io`, plus language-specific markers (Go `defer_in_loop` / `goroutine_in_unbounded_loop`, Python `pd_concat_in_loop`, JS/TS `array_spread_in_reduce`, and more). The signal fires on **Python, TypeScript/JavaScript, Java, Go, and C#**; a language without a dialect emits no perf findings (never a wrong one). `io_in_loop` is hand-label validated across an 11-repo OSS corpus (Go 96.7%, TypeScript 100%, Python 96.2% precision). On a 12k-file benchmark, the standard single-file linters (clippy, ruff PERF, ESLint, golangci-lint) found 0 of the cross-function I/O-in-loop cases that repowise surfaced 557 of. Following the call graph across files is the whole point: a file-local lint cannot see a loop in one function and its I/O sink in another. The clippy line of that comparison is catalogue-level, since a full end-to-end clippy run on the corpus was blocked by a Windows build wall rather than executed. Performance is a *static* signal, so it under-reports rather than over-reports: dynamic dispatch, ORM lazy-load N+1, and unmodelled libraries are out of scope by design. That is why we call it performance **risk**. ### Does the score predict real bugs? Yes, validated across **21 open-source repositories spanning all nine Full-tier languages** (Python, TypeScript, JavaScript, Java, Kotlin, Go, Rust, C++, C#): Result Value Cross-project mean ROC AUC (21 repos, 9 languages) **0.74** (mean 0.737) \[95% CI 0.68 to 0.79] (up to 0.90 on individual repos) Survives controlling for file size partial Spearman ρ = **−0.16** Beats recent-churn baseline **+0.10 AUC** (DeLong p \< 1e-9) Beats prior-defect baseline **+0.12 AUC** External, never-seen dataset (PROMISE/jEdit) AUC **0.76 to 0.78** ### Head-to-head vs the leading commercial tool This is a **different corpus** from the cross-project number above: **2,770 shared files across 9 languages**, scored at the same leakage-free commit against the same defect labels, with paired significance tests. The 0.731 ROC AUC below is on these 2,770 files; the 0.74 above is the cross-project mean over 21 repos. The two are measured on different file sets and are not the same number read twice. Axis repowise Leading commercial tool Recall @ 20%-of-lines budget **0.173** 0.074 Effort-aware ranking (Popt) **0.607** 0.462 Defect density, size-normalized (defects/KLOC) **2.18×** 0.56× Discrimination (ROC AUC) **0.731** 0.705 The decisive wins here are the effort-aware ones, all paired and significant: ranking by repowise health surfaces **2.3× the defects under a fixed review budget** (Popt Δ +0.144, recall Δ +0.098, density Δ, all at p = 0.003). The ROC AUC edge specifically is marginal (Δ +0.026, p = 0.054) and not significant, and precision\@20% between the two tools is a tie (p = 0.64). The commercial tool is also the more mature product, with 28+ languages, a published Code Red defect study, and behavioral-analysis features repowise does not match. ### Does the score find the bugs, on your repo? After every index, repowise checks its own claim against the repo's history: of the 20 least-healthy files, how many had a `fix:` commit in the trailing \~180 days, versus the repo-wide base rate. It prints a one-line callout (e.g. *"16/20 lowest-health files had a recent bug fix, 3.3× the 24% baseline"*) and surfaces the same precision\@K / lift stat on the web dashboards and over MCP (`get_health(include=["accuracy"])`). It stays silent on repos with too little history to be honest (fewer than 25 scored files or fewer than 5 recently-fixed files), and discloses that `prior_defect` is itself one down-weighted input, so this is an association on indexed history, not a leakage-free forward prediction. Full methodology, confidence intervals, and reproduction steps live in repowise-bench: the health-defect report and the head-to-head comparison. ### Using it Coverage lives behind its own command: `repowise coverage add ` ingests it once, and every later `repowise health` folds those test gaps into the scores automatically. When the report carries contexts (a coverage.py `.coverage`, or `coverage run --contexts=test`), `coverage add` also builds a per-test test-to-code map. **Three signals surfaced together.** Defect risk is the headline; maintainability and performance averages sit alongside it on the dashboard, in `repowise status`, and in the generated `CLAUDE.md`. **Coverage ingestion.** LCOV, Cobertura, Clover, or normalized JSON light up the test-coverage markers. **Trend tracking.** A rolling 50-row snapshot history powers `Declining Health` and `Predicted Decline` alerts. **Refactoring targets.** Deterministic, rule-based, ranked by impact / effort. A health score says a file is in trouble; refactoring intelligence names the specific fix: five detectors (Extract Class, Extract Helper, Move Method, Break Cycle, Split File) that emit one structured, graph-aware plan per opportunity. Code generation is on by default and can be turned off. **Per-repo policy.** `.repowise/health-rules.json` disables markers per glob and remaps severities (including a named `small-team` profile); the calibrated weights stay locked so the benchmark claims hold. Your agent reaches the same data through the `get_health` MCP tool, and a single-line summary shows up in `repowise status`. Full CLI reference: `repowise health`. ### How it connects to the other layers Code health isn't a silo; it reuses signals from every other layer: **Git** feeds the organizational markers (ownership, churn, co-change scatter, knowledge loss). **Graph** feeds centrality (a `brain_method` must be central, not just long), `hidden_coupling`, and the call-graph reachability behind the performance N+1 detector. **Decisions** surface as `ungoverned_hotspot` and `stale_governance` health findings. That's why a repowise health score carries more signal than a complexity linter's. A linter sees that a file is complex. The health score sees that the file is complex, central, churned by many hands, and untested, and weighs all four together. ## Dead code URL: https://docs.repowise.dev/intelligence/dead-code Files nothing imports, exports nothing uses, and packages nothing depends on, each with a confidence score and the evidence behind it. Repowise hands you a ranked list of code you can probably delete: the files nothing imports, the exported symbols nothing uses, and the packages nothing depends on. Every finding carries a confidence score and the evidence that produced it, so you can start at the top of the list and stop wherever you stop trusting it. It is pure graph traversal and SQL. No LLM calls, no network, and it finishes in under 10 seconds on any repo size. Findings populate during `repowise init` and refresh for changed files on `repowise update`. The layer surfaces candidates. You decide. Static reachability can prove that nothing *imports* a file. It can never prove nothing *loads* it. Everything below is built around that asymmetry. ### The four finding kinds Kind What it means Base confidence `unreachable_file` No file in the repo imports this one (file-node in-degree of 0 after entry points and the allowlist come out). Scored from git age, see below `unused_export` A public symbol nothing imports and no `calls` / `method_implements` / `reads` / `extends` / `implements` / `type_use` edge reaches. `1.00` when the containing file does have importers (the file is alive, only this symbol is not), `0.70` when it does not, `0.30` when the name ends in `_DEPRECATED` / `_LEGACY` / `_COMPAT` `unused_internal` A private or underscore-prefixed symbol nothing calls, and no cross-file importer pulls the name (which would mean a dispatch-table lookup). Off by default. `0.65` `zombie_package` A whole top-level package no other package imports. Never marked safe to delete. `0.50` `unused_internal` is opt-in (`--include-internals`); `zombie_package` is on by default and turns off with `--no-include-zombie-packages`. Passing `--kind` overrides both toggles, so `--kind unused_internal` enables internals on its own. `unused_internal` is disabled entirely for Rust, where the graph does not yet emit intra-file call edges, so a private Rust helper is never flagged. The `lines` count on file and package findings is an estimate: symbol count times ten, not a real line count. Read the "reclaimable lines" roll-up as an order of magnitude, not a figure. ### The git-age confidence ladder An orphaned file nobody has touched in a year is a much stronger signal than one added last week, so unreachable-file confidence starts from git activity. Condition Confidence No commits in 90 days, last touched over a year ago `1.00` No commits in 90 days, last touched over 180 days ago `0.90` No commits in 90 days, last touched over 90 days ago `0.80` No commits in 90 days, no other signal `0.70` No commits in 90 days, but the file is under 30 days old `0.55` (may be work in progress) Still being committed to `0.40` From there confidence only ever goes down. Two caps apply: **Dynamic imports nearby.** If any file in the same directory uses a runtime loader, confidence is capped at `0.40`. **Runtime-load risk factors.** If the path looks like config, environment, bootstrap, database, or script code (`config`, `settings`, `env`, `bootstrap`, `startup`, `entrypoint`, `database`, `db`, `schema`, `seed`, `migration`, or a `scripts/` / `bin/` / `tasks/` directory), confidence is capped at `0.40` and the finding carries an evidence line saying why. These are exactly the files wired up by a config key or a string path rather than an import, so "nothing imports it" is weak evidence. ### What `safe_to_delete` requires A finding is presented as safe to delete only when all three hold: Confidence is at or above `0.70`. The path carries no runtime-load risk factor. The name does not match a dynamic-dispatch pattern (`*Plugin`, `*Handler`, `*Adapter`, `*Middleware`, `*Mixin`, `*Command`, `register_*`, `on_*`, `*_view`, `*_endpoint`, `*_route`, `*_callback`, `*_signal`, `*_task`). Zombie packages are never safe to delete regardless of confidence. The safety re-derivation is monotonic: it only ever downgrades a stored flag, never upgrades it, so findings written by an older version stay honest. ### The CLI and MCP tiers differ on purpose Worth knowing before you compare numbers across the two surfaces. Surface High Medium Low Default floor CLI (`repowise dead-code`) `>= 0.7` `0.4` to `0.7` `< 0.4` `--min-confidence 0.4` MCP (`get_dead_code`) `>= 0.8` `0.5` to `0.8` `< 0.5` `min_confidence=0.5` The MCP surface is deliberately stricter: an agent acting on a finding is riskier than a human reading a table. The tool call itself is documented on the `get_dead_code` page, and the flags on other CLI commands. ### What is exempt by construction Before anything is scored, repowise removes what it knows is framework-loaded, generated, or convention-wired. Static reachability is the wrong tool for these, so they are never flagged rather than flagged and down-weighted. Group Examples Entry points Anything the graph marked `is_entry_point`, plus `__init__.py`, `__main__.py`, `conftest.py`, `manage.py`, `wsgi.py`, `asgi.py`, `setup.py`, `main.go`, `build.rs` Shell scripts `*.sh`, `*.bash`, `*.zsh`, invoked by name from CI configs and Makefiles Framework routes Next.js `page.tsx` / `layout.tsx` / `route.ts` / `middleware.ts`, SvelteKit `+page.svelte`, Nuxt `pages/*.vue`, Remix entry files, ASP.NET minimal-API `Apis/` / `Endpoints/`, Blazor and Razor code-behind Test files `*_test.go`, `*.test.ts`, `*.spec.ts`, `*_test.cc`, `*Test.java`, `**/tests/*.rs`, `src/test/java/`, MSTest and xUnit layouts, `__tests__/`, `__mocks__/` Generated code protoc `*.pb.go` / `*.pb.cs` / `*.pb.cc`, Qt MOC/UIC/RCC, Bison/Flex, SWIG, Cython, stringer, MapStruct `*MapperImpl.java`, Dagger, AutoValue, Roslyn `*.g.cs`, Dart `*.g.dart` / `*.freezed.dart`, `**/generated/**` Reflective loading Alembic `versions/*.py`, Django migrations, EF entity configurations, COM `*ClassFactory.cpp`, Win32 `*NativeMethods.cs`, ETW event classes Vendored trees `vendor/`, `third_party/`, `deps/`, `external/`, `extern/`, `contrib/`, `submodules/` Build artifacts `build/`, `cmake-build-*/`, `_deps/`, `*.min.js`, `*.bundle.js` Non-code languages Config and infra languages from the language registry, plus anything the parser could not identify Symbols decorated by a framework count as live too: pytest fixtures, Flask and FastAPI routes, Django `admin.register` and signal receivers, Celery tasks, Click and Typer commands, and the JVM stereotype and routing annotations (`@Component`, `@Service`, `@RestController`, `@Entity`, `@KafkaListener`, `@GetMapping`, `@Test`, JAX-RS `@Path` / `@GET`). Decorator *suffixes* match too, so `@my_local_group.command` and `@api.get` register even when the receiver has a project-local name. Two more targeted rescues: an `interface` in a file with no incoming `implements` edges is capped at `0.40` (implementor detection is heuristic, and missing evidence is not evidence of absence), and COM contract methods (`QueryInterface`, `AddRef`, `Release`) are capped the same way because they dispatch through native vtables. Zombie-package detection additionally ignores directories that are not packages at all: `.github`, `.vscode`, `.devcontainer`, `docs`, `scripts`, `assets`, `static`, `public`, `tests`, `benches`, `fuzz`, and their siblings. ### Dynamic-import awareness When a file uses a runtime loader, repowise assumes its neighbours may be reached through it and caps their confidence at `0.40`. Detected markers: **Python**: `importlib.import_module`, `__import__(`, `importlib.reload`, `pkgutil.iter_modules` **JS/TS**: dynamic `import(`, `require.context(`, `import.meta.glob(`, `React.lazy(`, `next/dynamic`, `jest.mock(` / `vi.mock(`, and the `'use server'` / `'use client'` boundary directives This is a text scan over source, grouped by file extension. Languages without markers in that table get no dynamic-import protection, which is one of the honest limits below. ### Cross-repo consumers in a workspace A file that is dead inside its own repo may still be the surface another repo depends on, so `get_dead_code` checks every finding against the cross-repo graph before returning it. If the file cross-changes with files in other repos, confidence is halved and the finding gains a `cross_repo_note` naming those repos (a behavioral signal from git co-change history, not an import edge, so read it as "something over there moves when this moves"). If another repo depends on this one as a package, the finding is an `unused_export`, and there was no co-change signal, confidence is cut to 30% of its value with a note saying the export may be consumed and should be verified. The adjustment runs after tiering, so it lowers displayed confidence without moving a finding between tiers. The CLI has no cross-repo pass yet: `repowise dead-code --repo ` analyzes that one repo in isolation. See workspace setup for how the cross-repo graph gets built. ### Known false-positive sources The layer is conservative, but it is still a static analysis over a static graph. These are where a finding is most likely wrong: **Reflection and string-keyed dispatch.** A class instantiated from a name in a config file, a handler looked up in a registry dict, a Java class loaded by `Class.forName`. The dynamic-pattern name list and the `.register` decorator suffix catch the common shapes. Nothing catches all of them. **Dynamic imports in unmodelled languages.** The marker table covers Python and JS/TS. Go, Ruby, PHP, Kotlin, Swift, and Scala runtime loading is not detected yet, so an orphan in those languages carries no dynamic-import cap. **Entry points the graph did not mark.** A binary target, a CLI script, or a serverless handler that neither the allowlist nor the entry-point pass recognized reads as unreachable every time. If a whole directory lights up, that is usually the cause. **Barrel re-exports.** `__init__.py` and index barrels are exempt from being flagged as unreachable *files*, but deliberately not exempt in the unused-export pass: a symbol defined in a barrel that nobody imports should still be reported. A symbol re-exported through a barrel to external callers can therefore surface as an unused export. **Python `__all__` is not read.** Declaring a public API there does not by itself rescue a symbol. The rescues that do apply are the `__init__.py` exemption, the dunder-name skip, and intra-module reference tracking. **Test-only usage reads as usage.** A test file's import produces a real graph edge, so a symbol only its tests touch is not flagged. That is deliberate, but it also means repowise will not tell you a symbol is *exclusively* exercised by tests. There is no "used only in tests" classification. **Recently added code.** A file under 30 days old with no importers is capped at `0.55` precisely because it is often unfinished, not dead. **Interfaces and abstract bases.** Reached only through implementors, which is heuristic detection. Capped, not suppressed. The evidence list on every finding tells you which of these applied. Read it before deleting anything. ### Where else it shows up The generated `CLAUDE.md` lists dead-code candidates alongside hotspots and decisions. Contributor profiles carry a dead-code burden per author. Module health folds dead-code percentage into its 0-100 composite. `repowise update` recomputes findings for changed files only. ### See also Code health: the scoring layer that shares the same graph and git data. Dependency graph: the graph this analysis walks. `get_dead_code`: the MCP tool, its parameters, and how findings come back tiered. Glossary: every dead-code term as it appears in the database and in tool responses. ## Architectural decisions URL: https://docs.repowise.dev/intelligence/decisions First-class decision records linked to the files they govern: captured by hand, mined from git history, or extracted from inline markers. Surfaced to AI agents via get_why so the why survives the team. Most documentation rots because the *why* lives in the original author's head. Repowise treats architectural decisions as first-class data: captured, linked to the files they govern, tracked for staleness, and surfaced to your AI agent via `get_why`. ### What's a decision A decision is a structured record with: **Title**: short summary. **Context**: what was the situation. **Decision**: what was chosen. **Rationale**: why. **Alternatives**: what was rejected. **Consequences**: what it implies going forward. **Affected files**: the graph nodes the decision governs. **Tags**: for cross-cutting concerns (security, performance, etc.). **Status**: `proposed`, `active`, `deprecated`, `superseded`. **Verification**: `verified`, `fuzzy`, or `unverified`, from an anti-hallucination gate that checks each claim against a literal source span rather than trusting the extraction. **Source**: one of the eight capture channels below (seven mined at index time, plus your session transcripts), plus manual `cli` capture. ### Seven sources, mined in parallel Beyond manual capture via the CLI, repowise mines decisions automatically from seven sources: ADR files, CHANGELOGs, PR bodies, inline markers, git archaeology, READMEs, and the LLM doc-generation pass itself. All seven run concurrently at index time; a failure in one source never blocks the others. ### The CLI Capture a decision interactively in \~90 seconds: See `decision` CLI commands for the full subcommand list. ### Inline markers in source Drop a marker comment in the file it governs: These get extracted at index time, linked to the file they live in, and treated as `active` decisions. ### Git archaeology Repowise mines significant commit messages and proposes decisions automatically. Run `repowise decision list --proposed` to review and either confirm them (`repowise decision confirm `) or dismiss them (`repowise decision dismiss `). ### The other four sources ADR files (Nygard/MADR format), CHANGELOG entries, PR and squash-commit bodies, and README/docs are all mined the same way: each candidate is checked against a literal source passage before it's kept, so a decision is only ever `verified` when the evidence actually says so. ### Verify, don't invent Every mined decision carries a **verification status**: `verified` (the claim traces to a literal quote in the source), `fuzzy` (related evidence exists but doesn't match exactly), or `unverified` (kept, but flagged rather than silently dropped or overwritten). Repowise never fabricates a rejection it can't justify. ### Linked to the graph, connected to each other Every decision is linked to the graph nodes it governs. When your agent edits a file, `get_why` automatically surfaces the decisions that touch it, without you having to remember to ask. Decisions also connect to each other by typed edges: `supersedes` (one decision replaces another), `refines` (narrows or extends without reversing it), `relates_to` (same topic, no ordering implied), and `conflicts_with` (two active decisions that contradict, with neither clearly winning, a governance smell surfaced in code health). This is how `get_why` answers a lineage question like "why is auth structured this way?" with a chain, not just the latest record. ### Mined from your sessions Beyond the index-time sources, repowise reads your own Claude Code transcripts for the corrections and conventions you actually enforce ("new endpoints go through the auth middleware", "use the shared HTTP client, not raw requests"), and turns the durable, repeated ones into tracked decisions. Deterministic gates decide what's worth keeping before a single batched LLM pass writes them up, so a one-off nudge never becomes a permanent rule. Repo-wide rules with no specific file (a project-wide convention) are kept too, and apply everywhere. ### Delivered where it matters Decisions reach the agent through the proactive hooks, no LLM and no round-trip: **At session start**, the decisions relevant to what this session is about to touch land in a compact block, scored against the working set. Relevance or silence: nothing is injected just for being high-confidence. **At edit time**, when the agent edits a file a decision governs, it gets a one-line "governed by" notice with the rationale. And it learns: every injected decision is recorded locally, and on the next `repowise update` the session miner checks whether the guidance was followed or contradicted by your corrections, relaxing or bumping the decision's staleness, so guidance that stops being true stops being injected. ### Staleness and health Decisions decay. If a file's `last_commit_at` moves forward but the decision's `last_update_at` doesn't, repowise flags it stale. Run: Or, agent-facing: You'll see stale decisions, proposed-awaiting-review, and ungoverned hotspots (high-churn files with no decisions on file). ### Workspace decisions In a workspace, decisions are per-repo by default. Pass `repo="all"` to `get_why` to search across the workspace. **The senior-engineer-leaving problem.** When the person who knew why it was built that way leaves, that knowledge usually leaves with them. Decision intelligence is the layer that keeps it in the codebase. ## Dependency graph URL: https://docs.repowise.dev/intelligence/dependency-graph How repowise builds the two-tier dependency graph (file nodes and symbol nodes) with import resolution, call resolution, heritage extraction, and community detection. The dependency graph is the foundation everything else sits on. Risk analysis, dead-code detection, blast radius, even the wiki itself: all of it walks the graph repowise builds at index time. ### Two tiers, one graph Tree-sitter parses every file in the repo into: **File nodes**: one per source file, with imports / imported-by edges. **Symbol nodes**: one per function, class, method, with caller / callee edges. Both tiers live in a single NetworkX graph. You can traverse from file to file, file to symbol, or symbol to symbol in a single query. ### Three-tier call resolution Naive call resolution is "the function name matched a definition somewhere, so link them." That approach is wrong about 30% of the time on real codebases (overloads, name collisions, dynamic dispatch). Repowise uses three tiers with confidence scoring: **Exact**: the import or namespace path uniquely identifies the target. Confidence `1.0`. **Heuristic**: name match plus contextual signals (file proximity, import direction, framework conventions). Confidence `0.7` to `0.95`. **Fallback**: name-only match, surfaced for review with low confidence (`< 0.7`). The MCP `get_context` tool filters callers/callees to confidence ≥ 0.7 by default: high-precision over recall. ### What the resolvers handle Import aliases (`import foo as bar`) Barrel re-exports (`export * from "./x"`) Namespace imports (`import * as Foo`) Path-mapped imports (TypeScript `tsconfig.json` `paths`, C# `.csproj`, Go `go.mod` replace directives, Rust `Cargo.toml` workspace members) Heritage: extends, implements, trait impls, derive macros, mixins, Swift extension conformance Framework-aware edges (Django routes, FastAPI dependency injection, Spring `@Component` graphs, Express routers, Rails Zeitwerk) Per-language detail: Language support. ### On top of the graph The graph alone isn't intelligence; it's data. Repowise computes: **PageRank**: global importance ranking. `get_context(include=["metrics"])` surfaces this per file. **Betweenness centrality**: files on many critical paths. **In/out degree**: direct dependents and dependencies. **Strongly connected components**: circular import groups. **Leiden community detection**: logical modules even when your directory structure doesn't reflect them. Each community gets a cohesion score and a label drawn from its most-common path segment. **Execution flow tracing**: from each natural entry point, follow the call graph and rank what's reached. All of these are exposed through `get_overview`, `get_context`, and `get_risk`. ### Refreshing `repowise update` rebuilds only the slice of the graph affected by changed files (incremental). A typical commit affects 3 to 10 nodes and takes under 30 seconds. ## Deterministic wiki URL: https://docs.repowise.dev/intelligence/deterministic-wiki The wiki repowise renders from your code's structure instead of writing it with a model. No API key, no spend, no network, and a full set of pages you can upgrade to model-written prose later. Repowise can produce its wiki two ways. The **model-written** wiki prompts an LLM per page. The **deterministic** wiki renders every page from the parsed AST, the dependency graph, and git history, with no model in the loop at all. Both produce a complete wiki. The deterministic one costs nothing and needs no API key, which makes it the right first run on a codebase you have not indexed before. `repowise init` never requires an API key. If it cannot resolve a provider it renders the deterministic wiki and exits 0. You do not have to pass a flag to get this behavior, though you can if you want it guaranteed. ### How to get it `--docs deterministic` and `--index-only` are the same switch. The first is named for what it produces, the second for what it skips. `--docs llm` asks for the model-written wiki and needs a key; passing `--docs llm` together with `--index-only` is a usage error and exits 2. You also land here without asking, in three cases: No provider is resolvable (no key set, no `--provider`, nothing in config). You answer No at the cost gate. The index you already built is kept and the deterministic wiki is rendered on top of it. The cost gate has no terminal to ask on. When stdin is not a TTY it never prompts, it auto-declines, which is what makes `repowise init --yes` safe to run from a script or an agent. ### What it renders Nearly the whole page set a model-written run produces: Page type Rendered deterministically File pages Yes Module pages Yes Layer and cycle (SCC) pages Yes Architecture diagram Yes Repo overview Yes API and infra pages Yes Onboarding collection Yes Symbol spotlight pages Skipped, the file pages already carry that content The pages are honest about where they came from. Each one ends with a footer saying it was derived from structure, and the repo overview describes composition, entry points, clusters, and dependencies rather than what the project does end to end, because no template can derive intent from an AST. ### What it costs Nothing. No API key, no tokens, no outbound network calls on the generation pass. It is the same local computation that produces the graph, git, health, and dead-code layers, applied to page rendering. ### What it lacks Two things, and they are worth being clear about: **Model-written prose.** A template can say that `PaymentProcessor` is called by six modules, sits in the checkout cluster, and has been bug-fixed four times this quarter. It cannot say why retries were made idempotent. That paragraph is what the model pass buys you. **Semantic search, until you configure an embedder.** Full-text and symbol search work on a deterministic index. Concept search and the RAG behind `get_answer` need embeddings, and the embedder defaults to `mock` when no key is detected. The embedder is separate from the LLM provider, so you can add semantic search without ever generating a page with a model. See Environment variables. Everything else, the dependency graph, git signals, hotspots, ownership, bus factor, code health, dead code, change risk, decision archaeology, and the MCP tools built on them, is identical either way. None of it was ever a model product. ### Upgrading later Both upgrades work in place on the index you already have. Neither re-indexes from scratch. **A slice at a time**, with `repowise generate`: **The whole wiki at once**, with `repowise update --full`: **Semantic search**, once an embedder is configured, with `repowise reindex`. That embeds the pages you have. No LLM calls, no page regeneration. In the dashboard, the Docs view on a deterministic repo offers the generation job directly rather than showing you an empty page. `--mode fast` is the one setting that produces no wiki at all. It is a graph plus essential-git index for very large repos, and it skips page rendering because rendering and embedding a page per file is exactly the cost it was chosen to avoid. `repowise update --full` is the way out of it. ### Related Auto-generated wiki, the model-written pass Quickstart, the keyless first run Indexing commands, `init`, `update`, `generate` ## Git history & co-changes URL: https://docs.repowise.dev/intelligence/git-history Hotspots, ownership, bus factor, and co-change pairs, the signals repowise mines from your last 500 commits that no AST analysis can produce. Static analysis tells you what the code *is*. Git history tells you how it *behaves over time*. Repowise mines your last 500 commits (configurable up to 5,000) for behavioural signals static tools can't produce. ### Hotspots Files that change often **and** are complex are where bugs live. Repowise computes a hotspot score from the joint distribution of churn percentile and complexity. Files in the top 25% on both axes get flagged in the dashboard, in `CLAUDE.md`, and surfaced by `get_risk` before your agent touches them. ### Ownership `git blame` aggregated into ownership percentages per engineer per file. Surfaces: **Primary owner**: who has historically touched this file most. **Recent owner**: the active maintainer (in case it's different). **Contributor count**: how many engineers have touched it. ### Bus factor For each file: how many people could leave the team before nobody owns it? `bus_factor: 1` means a single person owns >80% of the history. Surfaced as a knowledge-risk warning in the ownership view and in `CLAUDE.md`. ### Co-change pairs Files that change together in the same commit **without an import link** between them. This is hidden coupling, the kind AST analysis cannot detect. Often the most expensive coupling because no static tool will warn you about it. `get_context` surfaces co-change partners alongside direct dependencies; `get_risk` flags co-change warnings on PR blast-radius analysis when a changed file's historical partner is missing from the change set. ### Contributor profiles and reviewer suggestions Every author with commits gets a profile: modules they own, top files, co-authors, a commit-category mix (feat / fix / refactor / docs / test / chore / perf), silo modules they're solely on, and bus-factor risk files. Paste a PR's file list into Blast Radius and repowise ranks likely reviewers by direct authorship, co-change partnership, and recency. ### Significant commits The last 10 *meaningful* commit messages per file (filtered: no merges, no dependency bumps, no lint runs) are passed to the LLM during wiki generation. The model uses them to explain *why* the file is shaped the way it is, not just what it does. ### Trend signals Computed from the rolling commit-rate ratio: **Churn trend**: `increasing` / `decreasing` / `stable` based on the 30-day vs 60-day rate (cutoffs at 1.5× and 0.5×). **Change pattern**: `feature-active`, `fix-heavy`, `primarily refactored`, `dependency-churn`, or `mixed-activity`, derived from commit message classification. **Change magnitude**: lines added, lines deleted, average commit size in the last 90 days. ### Workspace mode In a workspace, all of the above is computed per repo *and* across repos. Cross-repo co-changes (files in different repos that move together) are first-class signals and surface in `get_context` responses. **Why 500 commits?** Empirically, signals stabilise around the 300 to 500 commit mark on most repos. Going higher gives diminishing returns and slower indexing. Tune with `--commit-limit` on `init` (cap is 5,000). ## Proactive agent hooks URL: https://docs.repowise.dev/intelligence/hooks Lightweight editor hooks that push graph, git, health, and decision context into Claude Code and Codex at the moment the agent needs it: no LLM, no network, fail-silent. This is also how repowise learns from how you actually use it. The MCP tools wait to be called. Hooks don't. They fire from editor lifecycle and tool-use events and push context to your agent with zero effort on its part, and keep your index fresh on every commit. Every agent hook shares the same guarantees: **no LLM calls, no network**, only local SQLite (`wiki.db`) and `git` reads. They are import-isolated (cold start under \~500ms) and any failure exits `0` silently, so a broken environment never crashes or blocks the agent. ### The hooks at a glance Hook Family Installed by Fires on What it does Post-commit auto-sync git `repowise hook install` every `git commit` Runs `repowise update` in the background SessionStart context Claude Code `repowise init` `startup` / `resume` / `clear` Live index freshness + the standing decisions relevant to this session PostToolUse enrichment Claude Code `repowise init` search / read / edit / shell / MCP calls Graph context on searches, git/edit freshness, read-intelligence, edit-time "governed by" notices Command-rewrite (distill) Claude Code `repowise hook rewrite install` (opt-in) shell commands Rewrites noisy commands to `repowise distill `, pending approval Codex context + staleness Codex `repowise init --codex` lifecycle / edit / shell Reminds Codex to use the MCP tools and flags stale context after edits The git hook is documented under the `hook` CLI command; the rest are covered below. ### SessionStart: live freshness and relevant decisions The generated `CLAUDE.md` is static between reindexes, so it can't say whether the index is current *right now*. This hook adds a short per-session block so the agent starts with calibrated trust instead of discovering staleness mid-task: **Index current** → one line saying so, plus the core-tool pointer. **Update running** → a positive "catching up" notice, never a stale scare. **Index behind** → indexed vs `HEAD` with a changed-file count, and the target-scoped trust rule (a stale warning fires only when a file a response actually served has changed). It also carries the **relevance-ranked standing decisions** for this session. repowise scores the repo's active decisions against the session's likely working set (dirty and staged files, files changed on the branch vs `main`, the previous session's edited files, and branch-name tokens) expanded one hop through import edges and co-change partners. The top few land under a hard token cap. Relevance or silence: nothing clears the floor, nothing is injected, and decisions are never shown just for being high-confidence. ### PostToolUse: enrichment on every tool call One hook covers several jobs, matched on the agent's search, read, edit, shell, and repowise MCP calls: **Grep/Glob enrichment.** When the agent runs a broad or zero-result search, repowise appends focused context pulled straight from `wiki.db`: the symbols defined in each related file, what imports it, what it depends on, and its git signals (hotspot, bus factor, owner). An agent that greps for `PageGenerator` immediately knows what depends on it and that it's a hotspot, without a separate MCP call: **Git/edit freshness.** After a successful `git commit`, `merge`, `rebase`, `cherry-pick`, or `pull`, repowise compares `HEAD` against the last indexed commit and, if the wiki is behind, reminds the agent to run `repowise update` so it never silently works from outdated docs. **Read-intelligence.** On a read of an indexed file, repowise can nudge the agent toward the cheaper `get_context(..., include=["skeleton"])` for structure-level questions, and emit a per-file stale-read notice when the file changed after indexing. **Edit-time "governed by" decisions.** When the agent edits a file governed by an architectural decision, it gets a one-line notice with the rationale, at most once per session per decision, so the decision reaches the agent right when it's about to honor or violate it. ### Command-rewrite (distill), opt-in The rewrite hook intercepts noisy shell commands and rewrites them to `repowise distill `, which compresses the output errors-first before the agent reads it, exit code preserved and every omission reversible. It defaults to **ask**, so you approve every rewritten command, and never touches pipes, compound commands, or watch modes. Install and manage it via `repowise hook rewrite`. ### Codex hooks `repowise init --codex` writes project-local Codex hooks: a SessionStart / UserPromptSubmit note reminding Codex to use the repowise MCP tools, and a PostToolUse staleness check after edits and git operations. See Connecting Codex for setup. ### Learns from how you actually use it The hooks aren't just delivery; they close a loop. Injected decision ids are recorded locally, and on the next `repowise update` the session miner checks whether each piece of guidance was followed or contradicted by your corrections, relaxing or bumping the decision's staleness so guidance that stops being true stops being injected. That feedback is one half of a flywheel that makes repowise adapt to your repo, all local and deterministic: **Decisions mined from your own sessions**: the corrections and conventions you actually enforce become tracked decisions, delivered back at session start and edit time. **Docs that follow your questions**: the wiki generation budget tilts toward the modules you and your agent ask about most, so depth lands where you actually work. Hooks and MCP tools are complementary. Hooks are passive, automatic, and free: they fire whether or not the agent is thinking about graph context. MCP tools are active and richer, for when the agent needs full documentation, a risk assessment, or dependency tracing. ## Refactoring intelligence URL: https://docs.repowise.dev/intelligence/refactoring A health score tells you a file is in trouble; refactoring intelligence names the specific fix. Five deterministic detectors (Extract Class, Extract Helper, Move Method, Break Cycle, Split File) emit one structured, graph-aware plan per opportunity, ranked by impact and effort. No LLM in the hot path; code generation runs only on demand, on by default and opt-out. A code health score tells you a file is in trouble. **Refactoring intelligence names the specific fix.** Every other tool stops at the score, or prints the same static sentence for every god class in every repo. repowise emits one structured plan per opportunity: *split `GraphBuilder` into these three cohesive groups*, *move `resolve_call` to the `resolvers` class where its calls actually land*, *break the `pipeline <-> update` import cycle by inverting this one edge*, *decompose this 900-line module into these four files and rewrite the imports in the six that depend on it*. Each is computed deterministically from the same graph, class model, and git data the score is built on. It runs **inside the health pass** (`init` / `update`), reusing data already computed: no re-parse, **no LLM, no network**, inside the same sub-30-second budget. The LLM layer (code generation) is a separate step that runs only on explicit request (below). ### The five detectors Each detector is a self-contained module registered into a registry (adding a refactoring type is a new file plus a registry entry, like the marker registry). A detector degrades to **"no suggestion" on any missing signal, never a wrong one**, and produces stable-sorted, deterministic output. Type What it names Detection (deterministic) **Extract Class** The cohesion groups an incohesive / god class should split into: the exact methods + fields per group. LCOM4 union-find components (each disconnected component is a candidate class), with the god-class shape confirmed via Lanza-Marinescu (WMC = Σ McCabe, TCC). **Extract Helper** A clone's exact occurrences and where the shared helper belongs. Rabin-Karp clone pairs (line ranges, token count, co-change). The extraction site is the community centroid of the involved files; transitive clones (`A<->B`, `B<->C`) are clustered into one suggestion, not pairwise nags. **Move Method** A feature-envy method and the class it actually belongs to. The method's entity set (fields / methods it touches, class-qualified) is built from the call graph; Jaccard distance to each class. Fires only when a foreign class is clearly nearer than its own. **Break Cycle** The minimal set of import edges to invert to break a dependency cycle. A strongly-connected component in the import graph, then a greedy minimum feedback arc set (MFAS) over the real edges picks the smallest cut. **Split File** The cohesive files an oversized module should decompose into: which top-level symbols move to each new file, plus the import edits in every dependent. Community detection (Leiden, Louvain fallback) over a weighted intra-file symbol graph (direct calls, shared local helpers, shared foreign modules); emits only when the partition's **modularity** clears a decomposability gate. The file-level analog of Extract Class. The algorithms are derived from public academic literature (Fokaefs-Tsantalis HAC for class splitting, Bavota feature-envy distance, MFAS for cycle breaking, Newman-Girvan modularity for module decomposition), not from any product. **Split File is the cross-file wedge made concrete.** It is language-agnostic: it reads only the already-built graph (`defines` / `calls` edges), so it works the same on every language with call resolution, and it covers the gap LCOM4 leaves for Go (top-level functions, not class methods). Splitting Go files in the same package is near-zero blast radius (no import edits); Python / TS get a back-compat re-export shim, surfaced as `shim_required` on the plan. ### Anatomy of a suggestion Every suggestion is **structured data, not a string**: the structure is the source of truth; human-readable text is rendered only at the edges (CLI / MCP / web). Field Meaning `refactoring_type` `extract_class` \| `extract_helper` \| `move_method` \| `break_cycle` \| `split_file` `file_path`, `target_symbol`, `line_start`, `line_end` What the refactoring acts on. `plan` The concrete, type-specific plan: the split `groups` (methods + fields), the move `{method, from_class, to_class}`, the clone `occurrences` + `suggested_site`, the cycle + `cut_edges`, or the file-split `groups` (`{name, symbols, suggested_file}`) + `residual` core + `shim_required`. `evidence` The signals that justify it: `lcom4`, `wmc`, clone token / line counts + `co_change_count`, Jaccard distances, cycle size, or the split's `modularity` + `symbol_count` + `group_count` + intra / cut edge counts. `impact_delta` The health score the refactoring would recover (the deduction of the marker it answers); `0` for the graph-native types that answer no marker. `effort_bucket` `S` \| `M` \| `L` \| `XL`, from the target's size. `blast_radius` What else must move: the callers, co-change partners, and importing files. `confidence` `low` \| `medium` \| `high`; drives the `min_confidence` surface gate. `source_biomarker` The finding this answers (e.g. `low_cohesion`, `god_class`, `dry_violation`). ### Ranking: graph-aware, not churn-only Each detector sorts its own output, but the surfaces show one mixed list, so the **global** order is what matters. A single unified rank blends three orthogonal signals as a product of `(1 + signal)` factors (so a zero in any one dimension shapes the order without annihilating the plan): A plan on a **central hub file outranks the same plan on a leaf**. Because the impact-free graph-native types (Move Method, Break Cycle, Split File) still rank via centrality and blast radius, they interleave fairly with the impact-bearing types rather than sinking below them. Ties break on type -> file -> target, so the order is fully deterministic. **The wedge.** The leading commercial code-health tool ranks refactoring targets by **churn alone**, generates code **within-function only**, and ignores its own coupling signal at generation time. repowise ranks by graph centrality, works **across files** (class splits, method moves, cycle breaks), and feeds the co-change + graph context straight into the plan. ### Surfaces The web **Refactoring** tab renders each plan as a card (the split groups as a small tree, the move arrow, the clone occurrences with line links, the file-split groups tree with its residual core and import-rewrite list) over an impact / effort quadrant, with per-type filter chips (URL-synced) and a distinct accent color per type carried consistently across the quadrant dots, card rails, and chips. Each card has a **copy-to-agent** button that exports the structured plan + source spans + blast radius as a prompt a coding agent can execute. ### Code generation The deterministic plan is the product. The LLM step is **on by default but opt-out** and **never in the indexing hot path**; it only runs when you ask for code for a specific plan, never during indexing. Configure it in `.repowise/config.yaml`: With `llm.enabled` left on (the default), the **Generate code** action on a plan card (or the endpoint below) gathers the plan's real source spans off the working tree, builds a behavior-preservation prompt carrying the structured plan **plus the graph / co-change context** a bare codegen tool throws away, and returns the refactored code and a unified diff. Where a self-check is cheap and meaningful it runs one: Extract Class re-walks the generated classes for an **LCOM4 before / after delta**, and Split File re-walks the generated files to assert each is **below the size floor** and the symbols are **partitioned with no duplication**. Results are cached on disk by a content hash (plan + source + model), so the same plan never pays twice. Code generation needs the working tree on disk (it reads the real source spans), so it is a local-`serve` capability: it returns `403` when disabled and `404` when the repo has no accessible checkout. **Apply is out of scope**: the wedge is the plan and the reviewable diff, not auto-applied edits. ### Configuration Per-path disables reuse the existing `.repowise/health-rules.json` glob mechanism, so a refactoring type can be silenced for generated or vendored paths the same way a marker is: ### See also Code health, the markers and the three health signals the suggestions are built on. `get_health`, the `get_health(include=["refactoring"])` response shape. `repowise health`, the full CLI reference. ## Test intelligence URL: https://docs.repowise.dev/intelligence/test-intelligence Ingest a coverage report and repowise answers two questions your CI cannot: which files are risky and untested, and which tests a given diff actually exercises. Ingest a coverage report and repowise can answer two questions your CI cannot: which files are risky *and* untested, and which tests a given diff actually exercises. That second one turns a 4,000-test suite into the 40 tests that guard the change you just made. Everything here is an index lookup: no LLM, no network. ### Two dimensions, one command `repowise coverage add` stores two different things, and the difference matters for everything below. Dimension What a row says Powers **Per-file aggregate** This file is 71% covered, merged across every test. `untested_hotspot`, `coverage_gap`, `coverage_gradient` in code health, the coverage dashboard **Per-test map** Test `tests/test_auth.py::test_login` covered lines 40-58 of `src/auth/service.py`. `repowise impacted-tests`, `get_change_risk`'s `impacted_tests`, `get_risk`'s `tests_to_run` The aggregate always gets stored. The map is only built when the report carries per-test contexts. A report without contexts still ingests fine, it just skips the map. Both are point-in-time: each ingest replaces the previous rows rather than appending history. Ingest at the same commit you intend to query, so line numbers line up. ### Supported formats Format Detected by Per-test map **LCOV** Leading `TN:` / `SF:`, or any `TN\|SF\|DA\|BRDA\|LF\|LH\|BRF\|BRH:` line Yes, when each record carries a non-blank `TN:` test name **Cobertura** XML `` takes explicit reports (repeatable). Note that `--coverage-report` is test coverage, while `--coverage` controls *documentation* breadth. Two different things, similarly named. ### CLI reference Command What it does `repowise coverage add [PATHS...]` Ingest reports. Auto-discovers when no path is given, merges multiple, builds the per-test map when contexts are present. Flags: `--path`, `--format`, `--verbose` `repowise coverage status` Coverage summary plus test-to-code map counts. Flag: `--path` `repowise impacted-tests [REVSPEC]` The tests a change exercises. Flags: `--path`, `--staged`, `--format` ### See also Code health, the coverage markers and how they deduct from the score. `get_risk`, where `tests_to_run` lives. `repowise health` and other commands. ## generate_refactoring_code URL: https://docs.repowise.dev/mcp/generate-refactoring-code Turns one structured refactoring plan from get_health(include=["refactoring"]) into generated code and a unified diff, grounded on the plan plus the real source it references. `get_health(include=["refactoring"])` returns ranked, structured refactoring plans, not template strings. `generate_refactoring_code` takes one plan's `id` and turns it into actual generated code: for Extract Class, the result includes an LCOM4 before/after self-check. ### Disabled by default Registered and on by default in the tool surface, but the tool itself returns `{"error": "disabled", ...}` unless the repo has opted in: When enabled, it uses the repo's configured LLM provider/model (bring your own key) and caches results by a content hash, so an unchanged plan never regenerates. ### When to call **After `get_health(include=["refactoring"])`** surfaces a plan you want turned into an applyable diff. **Only when your repo has opted into LLM-backed generation**: check for the `disabled` error first, or just read the config. ### Parameters ### Things worth knowing **Content-hash cached.** Re-running with the same plan against unchanged source returns the cached result instead of a fresh LLM call. **Grounded, not templated.** The generation is anchored on the plan's evidence plus the real source spans it references, not a generic rewrite prompt. **Extract Class gets a self-check.** The result includes an LCOM4 cohesion score before and after, so you can see whether the split actually improved cohesion. **BYO key.** Uses whichever LLM provider/model the repo already has configured for doc generation, so no separate credential. See `get_health` for how refactoring plans are ranked and what evidence each one carries, and Refactoring intelligence for the full plan shapes (Extract Class, Extract Helper, Move Method, Break Cycle). ## get_answer URL: https://docs.repowise.dev/mcp/get-answer One-call RAG synthesis over the wiki: it retrieves, gates on confidence, and returns a cited 2-5 sentence answer with fallback file targets. The first tool to call on any code question. Collapses **search → read → reason** into one round-trip. The tool retrieves the most relevant wiki pages, enriches the top hits with symbol docstrings and source excerpts, hands them to the LLM, and returns a synthesized answer with citations and a confidence label. If confidence is low, it returns ranked excerpts and fallback file paths instead, letting the agent decide whether to dig deeper. ### When to call **Always first** on any code question, before `search_codebase` or manual file exploration. If `confidence` is `"medium"` or `"low"`, follow up with `search_codebase` and `get_context` on the `fallback_targets`. Works best when the question names explicit identifiers (a class, function, or module name). ### Parameters ### Returns Field Description `answer` Synthesized 2-5 sentence answer (empty if synthesis was gated) `citations` File paths the answer references `confidence` `"high"`, `"medium"`, or `"low"` `fallback_targets` Top file paths from retrieval; agent should `get_context` on these for verification `retrieval` Top 5 wiki hits with `title`, `target_path`, `score`, `summary`, and (for top 2 file pages) symbols with docstrings and source excerpts `note` Context string explaining why synthesis was skipped or hedged `_meta` Timing, cache hit, answer hint ### Things worth knowing **Three confidence gates** keep the tool honest: **Dominance ratio**: if the top retrieval score isn't 1.2× the second, synthesis is skipped and excerpts returned instead. **Hedge-phrase detection**: if the LLM admits insufficiency in its own answer, `confidence` is downgraded `high` → `low`. **Identifier-citation gate**: if the question names symbols but none appear in the top retrieval hits, `confidence` is downgraded `high` → `medium`. **Question-aware symbol promotion**: symbols matching identifiers extracted from the question get longer docstrings (400 chars) and a 40-line source body excerpt, so "how does `X` work?" questions can be answered without hedging. **Intersection retrieval**: relational questions ("how does X talk to Y?") are split into two queries; hits appearing in both get a 2× boost. **Caching**: questions are normalized and hashed; repeat questions hit the answer cache instantly. Hedged cached answers are bypassed for re-synthesis when the symbol pipeline is updated. **No LLM provider configured?** Falls back to retrieval-only: ranked hits + snippets at `confidence="low"`. `get_answer` is the highest-leverage tool in the set. Most "what does this codebase do?" or "where is X handled?" questions are answered in a single call. ## get_change_risk URL: https://docs.repowise.dev/mcp/get-change-risk Pre-merge defect risk for a whole commit or diff range, scored from the shape of the live diff, plus the tests that actually cover the changed lines and whether those files have been bug-fixed before. Before merging, your agent should know whether this particular change is a routine one or an unusual one for this repo. `get_change_risk` scores a commit or a `base..head` range from the shape of its diff: how many lines, how many files, how scattered across directories, and how experienced the author is. It reads the live checkout, so it needs no index refresh and works on a branch you indexed an hour ago. It is deliberately different from `get_risk`, which scores indexed files by path and can report blast radius. `get_change_risk` scores the *change*. That means it catches risky small diffs that a file-level view misses. No LLM, no network. It is pure `git` plus learned constants, so the same diff always scores the same. ### When to call **Before merging** a commit or PR range, as a triage signal. **On a branch** you want to compare against the repo's own norm. **When the diff matters more than the files**, for example a three-line change spread across six subsystems. ### Parameters ### Returns Read the top three fields first. They are repo-relative and they are what you triage on. Field Meaning `review_priority` `Below typical`, `Typical`, or `Elevated`, from terciles of this repo's own commit-risk distribution `risk_percentile` "Riskier than N% of this repo's commits" `classification` Short label summarising the change shape `baseline_sample_size` How many filtered commits informed the percentile `score`, `probability`, `level` The corpus-calibrated fallback, secondary context only `features` The raw diff metrics behind the score `drivers` Signed per-feature contributions, so the result is auditable `exclude_patterns` The combined filters actually applied Lead with `risk_percentile` and `review_priority`, not `score`. The raw 0 to 10 is anchored to an offline calibration corpus, so on a repo whose typical commit is large, the diff-size term dominates and the absolute band skews high. Two-thirds of commits can read "high" while ranking perfectly normally for that repo. The ranking is sound, the absolute band is not portable. Note that `drivers` are reported relative to the *model's baseline commit* (the calibration-corpus mean), not to your repo. So a small change can legitimately read "more lines added than baseline" while still ranking `Below typical` for a repo of large commits. ### What it measures The model uses Kamei-style change metrics over the diff: Feature Meaning `la`, `ld` Lines added / deleted `nf` Files touched `nd`, `ns` Distinct directories / top-level subsystems touched `entropy` Shannon entropy of the per-file churn distribution (how diffuse the change is) `exp` Author's prior commit count. Unknown is scored neutrally The score is a plain L2-logistic over standardized, log-compressed features, so every feature's push on the result is exact rather than inferred. ### Impacted tests `impacted_tests` lists the tests that the per-test coverage map proves execute the change's changed *lines*. That is line-precise, so it is a narrower set than `get_risk`'s file-level `tests_to_run`. It is capped at ten, with `total` and `truncated` reporting overflow. `missing_tests` buckets the rest: `untested_changes` (covered file but uncovered change), `stale_test_candidates` (covered lines whose guarding test file is not in the diff), `covered`, and `no_coverage_data`. When no coverage map has been ingested, `status` is `no_map` and the change is reported as **unknown**, never as untested. Empty means "run the full suite", not "there are no tests". Build the map with `coverage run --contexts=test` followed by `repowise coverage add`. ### Prior fixes When the changed files carry counted bug fixes, the response includes `prior_fixes`: per file, how many past bug-fix commits touched it (`fix_count`), how many of the change's lines fall inside ranges one of those fixes replaced (`overlapping_lines`), and how long ago the most recent was (`last_fix_days_ago`). `total_fixes` counts distinct commits, not rows. The block is absent entirely on an index with no fix history. `overlapping_lines` is labelled `approximate` in the payload, and that label carries weight: a past fix's ranges are numbered against its own parent commit, so anything that moved lines in between shifts them. Read it as "this neighbourhood has been patched before", not "this exact line". The `fix_count` beside it has no such caveat. The block is aggregate and never names the commit that introduced a bug. File-level SZZ attribution measured 74.5% precision on this repo's frozen judgments, which is enough to count fixes and not enough to accuse a commit of causing them. ### Things worth knowing **Filters apply to both sides.** `extensions` and `exclude_patterns` filter the change *and* the recent commits sampled for its percentile, so the comparison stays like for like. **Project-wide rules** belong in a repository-root `.riskignore`. Those patterns apply automatically and combine with anything passed in the call. **An empty diff** produces a `warning` field, which usually means a bad revspec or over-tight extension and exclusion filters. **`baseline: 0`** disables percentile ranking, which leaves only the corpus-anchored score. Avoid it unless the repo is too young to have a distribution. **No cross-repo fields.** This tool is pure diff shape. Blast radius and co-change partners belong to `get_risk`. The same scoring is available from the shell as `repowise risk`. ## get_context URL: https://docs.repowise.dev/mcp/get-context The workhorse tool. Compact, batched context for any set of files, modules, or symbols: docs, ownership, freshness, and optional source/callers/callees/metrics/community in one call. If your agent only learns one tool, make it this one. `get_context` absorbs what would otherwise be five or six separate calls (file docs, symbol signatures, ownership, last-change history, source bodies, callers and callees, centrality metrics, community membership, and freshness) into a single call with a configurable `include` list. Pass multiple targets at once. ### When to call **After `get_answer`** to verify or expand on cited files. **Before editing** any file: check ownership, dependents, freshness, and governing decisions. **Architectural questions**: pair with `include=["metrics", "community"]` to see centrality and cluster membership. **Always batch**: one call with five targets is far cheaper than five calls with one target each. ### Parameters ### Returns The response is a `targets` map keyed by the target string. Each entry contains: Block What it gives you `docs` Wiki title, summary, and symbols list (name, kind, signature, line, docstring). Adds structure block and `imported_by` for files; child file pages for modules; `qualified_name`, `used_by`, candidate matches for symbols `full_doc` Same as `docs` but with the full page content\_md `ownership` `primary_owner`, `owner_pct`, `contributor_count`, `bus_factor`, plus `recent_owner` if the active maintainer differs from the historical primary `last_change` ISO date, author, days ago `source` Body, `start_line`, `end_line`, language, `truncated` flag (capped at 400 lines) `callers` / `callees` Up to 20 each, filtered to confidence ≥ 0.7. Each entry: `symbol_id`, `name`, `kind`, `file`, `confidence`, `edge_type` `metrics` `pagerank`, `pagerank_percentile`, `betweenness`, `betweenness_percentile`, `in_degree`, `out_degree`, `community_id` `community` `id`, `label`, `cohesion`, `top_members`, `neighbors` with cross-edge counts `freshness` `confidence_score`, `freshness_status`, `is_stale` `decisions` Governing architectural decision records (if any) `skeleton` *(file targets)* The file with bodies elided: every signature, the import preamble, and the bodies of only the most central symbols (ranked by symbol PageRank / hotspot / query match), token-budgeted. Typically \~15% of the full file's tokens. Elision markers carry 1-indexed line ranges so anything can be range-read back Top-level fields: `truncated`: `true` if output was capped at the token budget. `dropped_targets`, `dropped_symbols`: what got evicted when the budget was exceeded. `_meta.omitted`: when anything was dropped, the refs to get it back: `{ refs, tokens, restore }`. Resolve with `repowise expand ` from a shell or `get_symbol("repowise#")` from any MCP client; truncation is no longer silent. ### Things worth knowing **Token budget enforcement**: \~8000 tokens (\~32k chars) global cap. Truncation happens in stages: (1) strip heavy doc fields, (2) shrink symbol lists keeping query-matched symbols first, (3) drop whole targets. Largest targets are evicted first. **Symbol prioritisation**: within a target, symbols are ranked by exact name match → substring match → kind (class > function > method) → centrality. Navigationally important symbols survive truncation. **Target resolution order**: file\_page → module\_page → symbol (exact then fuzzy) → file by `target_path`. If none match, returns fuzzy path suggestions. **`freshness` is included by default**: critical for the agent to detect stale indices. `ownership` and `last_change` add 200 to 500 bytes each; omit them on multi-turn sessions to save the cache. **Cross-repo enrichment (workspace mode)**: appends co-change partners and contract links (HTTP routes, gRPC services, topics) from other repos for files in a multi-repo workspace. **Pattern that works well:** call `get_answer` first, then `get_context(targets=fallback_targets, include=["ownership", "last_change"])` on whatever the answer cited. Two calls, complete picture. ## get_dead_code URL: https://docs.repowise.dev/mcp/get-dead-code Tiered refactor plan for unused code. High/medium/low confidence findings with per-directory rollups, ownership hotspots, and safe-to-delete impact estimates. Pure graph + SQL, no LLM calls. Dead-code detection that's fast (under 10 seconds for any repo size, no LLM involvement) and conservative by design. Findings are classified into confidence tiers; `safe_to_delete` requires `confidence ≥ 0.70` and excludes dynamically-loaded patterns (`*Plugin`, `*Handler`, `*Adapter`, `*Middleware`). Framework-aware: Flask, FastAPI, Django, Rails, Laravel, and TYPO3 routes and convention files don't get flagged as unused. ### When to call **Before refactor sprints**: `min_confidence=0.7` to prioritize safe deletions. **Library API audits**: `kind="unused_export"` to find unused public symbols. **Monorepo cleanup**: `include_zombie_packages=True` to find packages no other package depends on. **Aggressive cleanup**: `include_internals=True` to also surface unused private symbols (higher false-positive rate). ### Parameters ### Returns Field Description `summary` `total_findings`, `filtered_findings`, `deletable_lines`, `safe_to_delete_count`, `by_kind` `tiers.{high,medium,low}` Each: `description`, `count`, `lines`, `safe_count`, `findings`, `truncated` `by_directory` *(if `group_by="directory"`)* per-dir rollup sorted by lines `by_owner` *(if `group_by="owner"`)* ownership hotspots sorted by lines `impact` `total_lines_reclaimable`, `safe_lines_reclaimable`, `recommendation` `limit_note` Present if the requested `limit` was clamped to 25 Each finding contains `kind`, `file_path`, `symbol_name`, `confidence`, `reason`, `safe_to_delete`, `lines`, `last_commit_at`, `primary_owner`, `age_days`, and `last_meaningful_change`. ### Things worth knowing **Confidence tiers**: **High** (≥ 0.8): zero references, safe to delete. **Medium** (0.5 to 0.8): likely unused, may have indirect references. **Low** (\< 0.5): possibly used via dynamic dispatch / reflection. **Safe-to-delete heuristic**: zero references **and** stable age (not modified in months). The threshold isn't just confidence. **Cross-repo adjustment (workspace mode)**: if a file has cross-repo consumers, confidence is reduced by 50%; if other repos depend on this repo's package, `unused_export` confidence drops to 30% with a verification note. **Zombie package detection**: monorepo packages flagged when no other package depends on them. **Last meaningful change**: derived from significant commits (feature/fix/refactor only, style/chore filtered out). **Limit clamping**: requests over 25 are clamped due to the MCP transport budget. `limit_note` will suggest tier/directory/owner filters to paginate. Repowise surfaces candidates. Engineers decide. Keep the team in the loop on big deletions. `group_by="owner"` makes it easy to route a cleanup PR to the right reviewer. ## get_health URL: https://docs.repowise.dev/mcp/get-health Code-health scores and marker findings per file across three signals (defect risk, maintainability, performance), exposed to your agent so it can self-check a change before opening a PR. `get_health` gives your agent the Code Health layer directly: a 1 to 10 score per file across **three signals** (defect risk, maintainability, performance), the marker findings behind it, repo-level KPIs, refactoring targets, and trend alerts. Zero LLM calls; it reads precomputed metrics. ### When to call **Self-check before a PR.** Read the same signals a code-health merge-gate judges the change on. Pass the files you touched and confirm you are not regressing the worst files. **Before a refactor.** Find the lowest-scoring files and the specific markers dragging them down. **Triage.** Dashboard mode returns the repo's worst files ranked, plus the "does the score find the bugs?" stat so the agent knows the score is trustworthy on this repo before acting on it. ### Parameters ### Returns **Dashboard mode** (no `targets`): Field Meaning `kpis.hotspot_health` NLOC-weighted average over the hotspot files `kpis.average_health` NLOC-weighted average over all files `kpis.maintainability_average` / `kpis.performance_average` The maintainability and performance pillar headlines (`null` until measured) `kpis.worst_performer` Single lowest-scoring file + score `lowest_scoring` Ranked worst files with score and top marker `module_rollup` Per-module NLOC-weighted health rollup **Targeted mode** (`targets` given): per-file `score`, the per-dimension `defect_score` / `maintainability_score` / `performance_score`, the marker `findings` (type, severity, line span, reason, and a `dimension`), and the score breakdown by category. ### Opt-in enrichments **`biomarkers`** returns the full (uncapped) findings set in dashboard mode. Pair with a dimension name, e.g. `include=["biomarkers", "performance"]`, to narrow to one pillar. **`accuracy`** adds a `defect_accuracy` block: of the K least-healthy files, how many were recently bug-fixed vs the repo-wide base rate (precision\@K + `lift`), with a per-K table and the flagged files. `null` on repos with too little history to be honest. **`signals`** adds a `signals` object on each targeted metric: prior-defect count, change scatter, 90-day churn, primary / recent owner, and graph in / out degree. Honest `null` per field when the underlying row is absent. **`churn_complexity`** adds `churn_complexity` points (one per recently-changed file: 90-day commits, max CCN, NLOC, score, churn percentile). **dimension filter** narrows findings to one pillar; pair with `"biomarkers"` for the full set, e.g. `include=["biomarkers", "performance"]`. ### Things worth knowing **Deterministic and offline.** The markers run off tree-sitter + git data with calibrated weights: no model calls, reproducible scores. **Three signals, never blended.** `score` is the defect-calibrated headline; maintainability and performance are co-equal companion views with their own per-file scores and `dimension`-tagged findings. **Coverage is opt-in.** The coverage markers (`untested_hotspot`, `coverage_gap`, `coverage_gradient`) only fire once you've ingested a report via `repowise coverage add`. **Module targets** (`module:foo`) expand to every file under the module, so one call covers a whole package. **Refactoring plans carry an id.** `include=["refactoring"]` returns each plan with a `suggestion_id`. Pass that id to `generate_refactoring_code` to get refactored code and a unified diff for that one plan. For the full marker reference, the three-signal model, the defect-prediction benchmark, and the head-to-head against the leading commercial tool, see the Code Health layer page. For the structured plans behind `include=["refactoring"]`, see Refactoring intelligence. ## get_overview URL: https://docs.repowise.dev/mcp/get-overview Architecture summary, module map, entry points, ownership, hotspots, and community structure for an entire repository: the first call your agent should make on any unfamiliar codebase. The opening move on any new codebase. One call returns a structured architecture summary, the top modules, the natural entry points, git health signals, ownership map, and the major architectural communities. ### When to call **First**, before the agent reads any source. **Workspace orientation**: pass `repo="all"` to get cross-repo topology and contract links. **Architecture review**: re-call before proposing structural changes to refresh hotspot and ownership context. ### Parameters ### Returns Field Description `title` Repo name `content_md` Full markdown overview (architecture summary, tech stack, data flow, areas to focus on first) `key_modules` Top module pages, each with `name`, `path`, `description` `entry_points` File paths for the natural entry points (test fixtures excluded) `git_health` `hotspot_count`, `avg_bus_factor`, `churn_trend`, `top_churn_modules` `knowledge_map` `top_owners` (with file ownership %), `knowledge_silos` (files >80% owned by one person, boilerplate excluded) `community_summary` Top 10 architectural communities by size, with cohesion scores `workspace` *(workspace mode only)* root, default repo hint, cross-repo topology, contract links ### Things worth knowing **Churn trend** is computed from a 30-day vs 60-day commit-rate ratio: above 1.5× is `"increasing"`, below 0.5× is `"decreasing"`, otherwise `"stable"`. **Knowledge silos** filter out boilerplate (migrations, `__init__.py`, `conftest.py`, lock files) so the list reflects real bus-factor risk. Module pages are capped at 20 and community summaries at 10 to keep the response within the MCP token budget. In workspace mode, `repo="all"` returns total repos, files, and symbols plus a per-repo dependency graph and contract links between services. If the agent calls `get_overview` and immediately follows up with `Grep` or `Read`, your MCP server probably isn't connected. Check `.mcp.json` and run `repowise doctor`. ## get_risk URL: https://docs.repowise.dev/mcp/get-risk Modification-risk assessment for files before editing, covering hotspot scores, dependents, co-change partners, blast radius, recommended reviewers, test gaps, and security signals. Before changing a file, your agent should know what it's walking into. `get_risk` rolls up churn, complexity, dependents, hidden coupling (co-changes), ownership, test coverage, and security signals into a single per-file profile, plus an optional PR-style blast-radius analysis when you pass a `changed_files` list. ### When to call **Before editing** any file the agent doesn't already understand. **PR review**: pass `changed_files` to get the transitive impact surface, missing co-change partners, and recommended reviewers. **Architectural planning**: surface bus-factor risks and coupling hotspots ahead of time. ### Parameters ### Returns `targets` is keyed by file path. Each entry contains: Field Meaning `hotspot_score` 0 to 1 churn percentile (higher = changed more often) `trend` `"increasing"`, `"decreasing"`, or `"stable"` (30d vs 60d rate) `risk_type` `"churn-heavy"`, `"bug-prone"`, `"high-coupling"`, `"bus-factor-risk"`, or `"stable"` `dependents_count` Number of files importing this one `co_change_partners` Top 5 co-changed files with date and import-link flag `primary_owner`, `owner_pct` Historical owner `recent_owner`, `recent_owner_pct` Active maintainer if different `bus_factor` How many people could disappear before the file becomes unowned `contributor_count` Total contributors `change_pattern` `"feature-active"`, `"fix-heavy"`, `"primarily refactored"`, `"dependency-churn"`, or `"mixed-activity"` `change_magnitude` `lines_added_90d`, `lines_deleted_90d`, `avg_commit_size` `impact_surface` Top 3 critical modules that depend on this file (PageRank-ranked) `test_gap` `true` if no test file matches the file's basename `security_signals` `kind`, `severity`, `snippet` from static analysis `risk_summary` One-line human summary Top-level extras: `global_hotspots`: top 5 hotspot files in the repo (excluding targets). `pr_blast_radius` *(only if `changed_files` provided)*: `direct_risks`, `transitive_affected`, `cochange_warnings`, `recommended_reviewers`, `test_gaps`, `overall_risk_score`. ### Things worth knowing **Risk type classification (priority order)**: `bug-prone` if ≥40% of commits are fix/patch; `churn-heavy` if percentile ≥ 70; `bus-factor-risk` if `bus_factor == 1` and >20 commits; `high-coupling` if ≥5 dependents. **Change pattern** is the dominant commit category at ≥50%, else `mixed-activity`. **Test gap detection** looks for `test_*.py`, `*_test.py`, or `*.spec.*` matching the file's basename. Test files themselves are never reported as having a test gap. **PR blast radius** walks the import graph up to depth 3. Recommended reviewers are the top-5 owners of affected files. `cochange_warnings` flag missing historical co-change partners not in the PR. **Cross-repo impact (workspace mode)**: co-change partners and contract links from other repos contribute to `dependents_count`. A high `hotspot_score` plus `bus_factor: 1` plus `test_gap: true` is the danger triangle. Don't ship a refactor of that file without pulling the primary owner into review. ## get_symbol URL: https://docs.repowise.dev/mcp/get-symbol Raw source bytes for one indexed symbol with exact line bounds, cheaper and safer than reading the whole file and counting offsets. The only MCP tool that returns actual source code. Every other tool returns *context about* code. `get_symbol` returns the **code itself**: the raw source bytes of a single indexed symbol with its exact start/end lines. It's the precise, bounded alternative to a full-file `Read` followed by offset arithmetic. It also resolves **omission refs** (`repowise#<12-hex>`) from truncated responses. ### When to call **You need one function or class body**, not the whole file. **After `get_context`**: pipe the `symbol_id` from its symbol list straight in. **To confirm a signature or implementation** before editing, without pulling 800 unrelated lines into the context window. **To restore truncated content**: when a response's `_meta.omitted` lists refs and you have no shell for `repowise expand` (e.g. Claude Desktop). ### Parameters ### Returns Field Meaning `symbol_id` The resolved canonical id `source` The symbol's source bytes (bounded at \~400 lines) `start_line`, `end_line` Exact 1-based line bounds in the file `kind` `function`, `class`, `method`, … `language` Detected language tag `truncated` `true` if the body exceeded the line bound and was cut On a miss, returns `{ error: "Symbol not found …" }` with the closest candidate ids so the agent can retry without another `get_context` call. For an omission ref, returns the stored content plus provenance (`source`, `created_at`, `original_tokens`) instead. ### Things worth knowing **Deterministic on overloads.** When a name resolves to more than one definition, resolution is stable: the same id always returns the same symbol. **Separator-agnostic.** `file.py::Name`, `file.py.Name`, and `file.py/Name` all resolve; use whatever `get_context` handed you. **Bounded by design.** The \~400-line cap keeps a single call from blowing the context window on a giant generated file; `truncated` tells you when that happened. Pair it with `get_context`: `get_context` returns the `symbol_id`s and signatures, `get_symbol` fetches the one body you actually need. Two calls, zero file reads. ## get_why URL: https://docs.repowise.dev/mcp/get-why Architectural-decision archaeology. Search decisions in natural language, anchor them to a file path, or pull the global decision-health dashboard. Falls back to git archaeology when no recorded decisions exist. The decision intelligence layer in one tool. `get_why` answers *"why is this code shaped this way?"*, pulling from the architectural decision records, the wiki, and (when nothing's recorded) the git history itself. Four modes: NL search, path-anchored, target-aware, and a no-arg health dashboard. ### When to call **Before architectural changes**: check whether existing decisions govern what you're about to touch. **During design reviews**: pull the health dashboard to find stale decisions and ungoverned hotspots. **On code with no recorded decisions**: the git-archaeology fallback reconstructs the origin story from significant commits. **Onboarding**: call with no args for a tour of the codebase's recorded reasoning. ### Parameters ### Returns The shape depends on which mode the call landed in. ### Mode 1: Search (`query` is a question) `mode: "search"`, `query` `decisions`: 8 merged hits (keyword + semantic, deduped) `related_documentation`: top 3 wiki pages mentioning the query `target_context`: *(if `targets` provided)* per-target governing decisions, origin story, and git archaeology fallback ### Mode 2: Path (`query` is a file path) `mode: "path"`, `path` `decisions`: every decision affecting this file `origin_story`: when and why the file was created, by whom, recent change patterns `alignment`: how well the file aligns with its governing decisions `git_archaeology`: significant commits, cross-references, git log results (used when no decisions exist) ### Mode 3: Health dashboard (no `query`) `mode: "health"` `summary`: human-readable counts `counts`: structured counts `stale_decisions`: decisions older than the files they govern `proposed_awaiting_review`: `status="proposed"` records `ungoverned_hotspots`: high-churn files with no decisions ### Mode 4: Workspace search (`repo="all"`) `mode: "search"`, `workspace: true` `decisions`: merged results across repos (capped at 15) ### Things worth knowing **Path detection**: if `query` contains `/` or ends with `.py`, the tool routes to path mode (Mode 2) instead of search (Mode 1). **Natural-language scoring** weights field matches: `title` 3.0×, `decision`/`rationale` 2.0×, `context` 1.5×, `consequences`/`tags`/`files` 1.0×. `targets` files contribute `+5.0` for an exact match, `+3.0` for a module-level match. **Git-archaeology fallback** runs when no decisions exist for a file: (1) significant commits from the file itself, (2) cross-file references in other files' commits, (3) live `git log --follow` and `git log --grep` (10-second timeout). **Staleness score** compares the file's `last_commit_at` to the decision's `last_update_at`; older files with unchanged decisions are flagged stale. **Workspace mode (`repo="all"`)** uses keyword search across all repos' decisions, capped at 15 merged results. Full per-repo semantic federation is path-mode only. Decisions are linked to graph nodes, so when the agent edits a file `get_why` will surface the decisions that govern it without you having to ask. This is what keeps the *why* in the codebase when the original author leaves. ## MCP tools: overview URL: https://docs.repowise.dev/mcp/overview The small, curated set of MCP tools repowise exposes to Claude Code and any MCP-compatible AI agent. Task-shaped, batched, and built to collapse long tool-call chains into one round-trip. Most MCP servers expose tools that mirror data entities: one file, one symbol, one diff. That forces the agent into long sequential chains. Repowise exposes a **small, curated set** of task-shaped tools instead. Pass multiple targets in one call. Get complete context (docs, ownership, metrics, history, decisions) back. Same answer, fewer round-trips, fewer tokens. ### The core tools These ten tools are the documented core surface, available in both single-repo and workspace modes: Tool What it answers When the agent calls it `get_overview` Architecture summary, module map, entry points, git health First call on any unfamiliar codebase `get_answer` One-call RAG: retrieves over the wiki, gates on confidence, synthesizes a cited answer First call on any code question `get_context` The workhorse: docs, symbols, ownership, freshness, optional callers/callees/metrics for any targets Before reading or modifying code `get_symbol` Raw source bytes for one indexed symbol with exact line bounds When you need one function/class body `search_codebase` Hybrid symbol / path / concept search, mode routes by query shape Finding a symbol or file, or discovering code by topic `get_risk` Hotspot scores, dependents, co-change partners, blast radius, reviewers, test gaps Before modifying files `get_change_risk` Pre-merge defect risk for a whole commit or diff range, plus impacted tests and prior fixes Before merging a commit or PR range `get_why` Architectural decision search: NL query, path lookup, or health dashboard Before architectural changes `get_dead_code` Unreachable code sorted by confidence tier with cleanup impact Cleanup tasks `get_health` Code-health scores across three signals (defect, maintainability, performance): KPIs and worst files, or per-file findings Self-check before a PR / before refactoring `get_risk` and `get_change_risk` are the pair people mix up. `get_risk` scores **indexed files by path** and can report blast radius. `get_change_risk` scores **the shape of a live diff**, so it catches risky small changes that a file-level view misses. One more tool is on by default and needs no page of its own: `list_repos` enumerates the repos the server can reach. It is mostly useful in workspace mode, where it lists every workspace repo and the default. That makes 11 tools advertised by default in single-repo mode, though only the ten above are worth an agent's attention. In workspace mode, every tool accepts a `repo` parameter. Pass a specific repo name, or `"all"` to federate across the workspace. ### Three more in workspace mode When the server runs over a workspace (several repos indexed together), three additional tools appear. They answer cross-repo questions that have no single-repo equivalent. Tool What it answers `get_blast_radius` If you change this service, what breaks across the other repos `get_conformance` Whether the live system graph obeys the declared dependency rules, plus dependency cycles `get_architecture` Whole-system coupling, the cyclic core, and a 1-10 architecture score They are documented in full on the Workspace MCP mode page. ### Two opt-in tools `get_dependency_path` (shortest dependency path between two files or modules) and `get_execution_flows` (entry points + call traces) are registered tools that ship with the server but are **off by default in every mode**. Turn them on per repo in `.repowise/config.yaml`: or per launch with `repowise mcp --tools "+get_execution_flows"`. See Configuring the tool surface for the full `+`/`-` delta syntax and the explicit-allowlist / `all` shapes. **Truncation is reversible.** Responses are token-budgeted, but dropped content is no longer silently lost: a `_meta.omitted` envelope lists refs (`repowise#<12-hex>`) that resolve via `get_symbol`, or `repowise expand ` from a shell, with no extra tool. See Distill for the full reversibility model. ### Connecting `repowise init` automatically writes `.mcp.json` at the project root and (for Claude Code) registers the server in `~/.claude/settings.json`. You don't need to do anything else. To wire up another editor manually: For the hosted version, use the HTTP transport with an API key from Settings → Editor. Drop the same `mcpServers` block into `~/.cursor/mcp.json`. Add the same `mcpServers` block to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`). Restart Claude Desktop after editing. Use the MCP extension and point it at `repowise mcp `. Add to Windsurf settings → MCP servers using the same command. ### A real five-call task *"Add rate limiting to all API endpoints."* Without repowise, an agent greps and reads files for \~30 calls. With repowise, five: That's the design point. Each call returns a *task-shaped* slice of the codebase, not a single file or symbol, so the agent reaches a decision in one or two passes instead of ten. ### Why a curated surface Repowise's internal modules expose more graph navigation primitives (callers/callees, dependency paths, graph metrics, execution flows, community detection). Most of that surfaces as `include` options on the core tools rather than separate calls; two of the primitives (`get_dependency_path`, `get_execution_flows`) are real MCP tools but ship off by default, because every extra tool in the schema is overhead on tasks that don't need it. The public tools are deliberately one level up. `get_context` absorbs callers, callees, metrics, and community into a single call via its `include` parameter. `get_risk` rolls up hotspot, dependents, co-changes, reviewers, and test gaps. `get_why` covers natural-language search, path lookup, and the global health dashboard. `get_health` rolls up the three-signal marker scores plus targeted findings. If you're building on top of repowise programmatically, the `packages/server` Python API exposes the lower-level primitives. The MCP surface is what AI agents see, and AI agents do better with fewer, richer tools. ## search_codebase URL: https://docs.repowise.dev/mcp/search-codebase Hybrid code search over repowise's indexes: symbols, file paths, or the wiki, depending on the shape of the query. One tool instead of a fallback to Grep for identifiers. A single tool that, depending on the shape of the query, searches the indexed **symbols**, **file paths**, or the **wiki**. An identifier routes to symbol hits, a path-shaped query to file hits, and prose to wiki-semantic search, so the agent doesn't need to pick a strategy up front. ### When to call **Locating a function/class/method by name**: symbol hits pipe directly into `get_symbol`. **Resolving a path-shaped query**: file hits pipe into `get_context`. **After `get_answer`** when confidence is medium or low: explore the alternatives, or discover pages by topic before drilling in. ### Parameters ### Modes **`auto`** (default) routes by query shape: an **identifier** (`GitIndexer`, `index_repo`) → searches indexed symbols; a **path** (`core/ingestion/indexer.py`) → searches file pages; **prose** ("how do we handle retries?") → wiki-semantic search; mixed prose + identifier → **hybrid** (symbol hits first, then concept pages). **`concept`** forces the original wiki-semantic behavior. **`symbol`** / **`path`** force the structural search. ### Returns **Symbol hits**: `{type: "symbol", symbol_id, name, kind, file, start_line, end_line, signature, next: "get_symbol"}`. Ranked by exact-name/qualified-name match, query-token coverage, then graph centrality (PageRank / betweenness / entry-point); non-test results rank before test unless `kind="test"`. **File hits**: `{type: "file", page_id, file, title, next: "get_context"}`. **Concept hits**: ranked wiki pages with `page_id`, `title`, `page_type`, `snippet`, `target_path`, `relevance_score` (raw, absolute), `confidence_score` (normalized to the top result), and `search_method` (`"embedding"` vs `"bm25"` fallback). Tombstoned and `exclude_patterns`-excluded results are filtered out. In workspace mode, structural and concept searches both federate across repos and merge. ### Things worth knowing **Vector + FTS fallback**: concept-mode semantic search runs first with an 8-second timeout. If the vector store is unavailable or slow, full-text search takes over transparently. **Fetch-and-filter**: concept mode fetches 3× the requested limit, then filters by `page_type` and a minimum relevance threshold, keeping results rank-stable when filters are applied. **Freshness boost**: concept results are re-ranked by git activity. Files with commits in the last 30 days get a 1.0× boost, 60 to 90 days get 0.5×, inactive get 0.0×. **Workspace-wide (`repo="all"`)**: uses Reciprocal Rank Fusion (k=60) to merge per-repo results; confidence scores are renormalized within the merged set. This is the one tool where `repo="all"` is fully supported (`get_context` and `get_overview` also accept it; `get_symbol`, `get_dependency_path`, and `get_execution_flows` do not). `get_answer` already runs a search internally before synthesizing. Reach for `search_codebase` when you want the list of candidates, not a synthesized answer, or when you know you're looking for a symbol or file by name. ## Architecture metrics URL: https://docs.repowise.dev/multi-repo/architecture-metrics The one evaluative read of the whole system, propagation cost, the cyclic core, per-service roles, and a deterministic 1-10 architecture score. Standard architecture-complexity metrics computed over the system graph, no LLM. Conformance and the cycle finder answer *per-relationship* questions (is this edge allowed, is this loop a cycle). Architecture metrics give the one *evaluative* read of the whole system: how coupled it is, where its architectural core is, and a single score you can track over time and compare across workspaces. These are the standard MacCormack / Baldwin / Sturtevant architecture-complexity metrics, computed deterministically over the system graph, no LLM. They use **structural edges only** (http, grpc, event, package, db); co-change is excluded. ### What it computes **Propagation cost**, the share of *other* services the average service can reach transitively through dependencies (0% = fully decoupled, 100% = everything reaches everything). The headline coupling number; lower is better. **Cyclic core**, the largest cyclic group of services (the largest strongly-connected component of the structural graph). Its size and ratio (core / services) describe how much of the system is tangled together. **Architecture type**, `core-periphery` when the core spans a meaningful fraction of the system, else `hierarchical`. **Per-service role**, each service classified from its visibility profile: **Core**, in the largest cyclic group (the architectural center). **Shared**, high visibility fan-in, low fan-out: many services depend on it, it depends on few (a widely-used utility or library). **Control**, high fan-out, low fan-in: it depends on many, few depend on it (an orchestrator or entry point). **Peripheral**, lightly coupled in both directions. **Architecture score**, a deterministic 1-10 roll-up (matching the Code Health 1-10 convention) from propagation cost, core ratio, dependency-cycle count, and declared-rule violation count. Lower coupling and a smaller core score higher. ### CLI `repowise workspace metrics` prints the score, propagation cost, cyclic core, dependency-cycle count, and the per-role service breakdown. CI-friendly plain output; `--json` emits the raw metrics. ### REST `GET /api/workspace/architecture` returns the workspace metrics plus the per-service roles. Computed at request time from the system graph (no separate artifact); the conformance violation count, if a report exists, is folded into the score. ### MCP `get_architecture` gives an agent the score, propagation cost, core members, and role breakdown in one call, the system-structure read to consult before a cross-service refactor. ### Web The **architecture score** appears as a stat on both the Conformance and System Map pages. The DSM header shows score, propagation cost, and core size, and tints each service's diagonal cell by its role, so the on-diagonal core block stands out. On the Live System Map, toggle **Core** to highlight the cyclic core, and the inspector shows any selected service's role and visibility profile. The score is deterministic and uses only structural edges, so it moves when the dependency topology changes, not when commit activity does. That makes it a stable number to track release over release. ## Cross-repo blast radius URL: https://docs.repowise.dev/multi-repo/blast-radius If you change this service, what downstream services and repos break? Blast radius walks the system graph against its edges and returns every reachable service ranked by impact. Blast radius answers a single question: **if I change this service, what downstream services and repos break?** It walks the system graph *against* its edge direction (a `consumer → provider` edge means changing the provider impacts the consumer) and returns every reachable service ranked by an impact score. ### Structural vs behavioral impact Two edge classes are weighted and labelled distinctly: **Structural** edges (http, grpc, event, package, db) assert a real dependency, a contract or an import. They propagate impact at full weight and surface as **will break**. **Behavioral** co-change edges only assert that two files historically *changed together*. That is correlation, not a call, so they propagate at half weight and surface as **may drift**. Each impacted service carries its `distance` (hops from the change) and `score` (0-1, with distance decay and the behavioral weighting baked in). Nearer, structural impact ranks highest. ### REST `target` is a node id (`repo` or `repo::service/path`) or a repo alias (which expands to all of its services). ### MCP The `get_blast_radius` tool (workspace mode) gives an agent the impacted set before it touches a high-fan-out provider. The `get_risk` PR-mode directive also gains `will_break_consumers` and `missing_cross_repo_cochanges`, so a diff in one repo flags its cross-repo fallout. ### System Map Pick a service in the **Blast radius** control above the Live System Map. The reachable set ripples (highlighted, the rest dimmed, with badges grading intensity), and a side panel lists the impacted services. Click any impacted service to walk the impact outward from there. Structural impact (`will break`) outweighs behavioral co-change (`may drift`). When both appear for the same change, fix the structural consumers before you ship, and treat the co-change set as a checklist to review. ## Breaking-change guard URL: https://docs.repowise.dev/multi-repo/breaking-changes Did a provider change in a way that actually breaks its consumers? On every workspace update, freshly-extracted contracts are diffed against the previous index and each incompatible change is reported with the exact consumer files it endangers. Where blast radius answers *what could be affected*, the breaking-change guard answers a sharper question: **did a provider change in a way that actually breaks its consumers?** On every `repowise update --workspace`, the freshly-extracted contracts are diffed against the previously-indexed set, and each incompatible provider change is reported with the exact consumer files that call it. ### Detected change kinds Kind Severity Fires when `removed_endpoint` breaking A provider route, gRPC method, or topic that existed before is gone `removed_field` breaking (response) / warning (request) A request or response field disappeared `field_type_changed` breaking A field's type changed (e.g. `string → int64`) `field_number_changed` breaking A proto field's wire number changed `field_required` breaking A field became required, or a new required field was added **Non-breaking changes never flag.** An added *optional* field, a widened set, or a brand-new endpoint produces no record. Field-level diffs need a contract *schema*: today gRPC carries one (proto message fields, recovered by the existing proto parser), and HTTP gains field-level checks when an OpenAPI spec is present. Route-level removal is detected for every transport from the contract id alone. Data/DB contracts don't get field-level diffing, only table-level removal. The consumer side is a heuristic SQL match, not a typed schema. Impacted consumers are resolved from the matched contract links, the same provider↔consumer evidence the system graph's edges are built from. Impact is therefore endpoint-precise (the consumer file that calls the changed contract) and direct (the first reachability hop, which is exactly what a contract break endangers; transitive ripple stays the job of blast radius). ### REST `GET /api/workspace/breaking-changes` returns the report from the most recent update, filterable by `repo` or `severity`. Each change carries its provider, detail, and impacted consumers with both code sides. ### MCP The `get_risk` PR-mode directive gains a `breaking_changes` block listing the provider contracts that changed incompatibly in the diff's repo and the consumers they endanger, across repos. ### System Map Toggle **Breaking changes** above the Live System Map: changed providers are badged with their breaking count, the consumers they endanger are badged *at risk*, and the seams between them are highlighted (an additive overlay, so the map stays whole). A side panel lists each change with both the provider and consumer files. The guard compares the current index against the previous one, so the first workspace index has nothing to diff against. Breaking changes appear from the second `repowise update --workspace` onward. ## Architecture conformance URL: https://docs.repowise.dev/multi-repo/conformance Declare which services may depend on which others, then continuously check the live system graph against those rules. Your team's architecture lint, plus automatic dependency-cycle detection. Workspaces let you declare, in `.repowise-workspace.yaml`, which services are *allowed* to depend on which others, then continuously check the live system graph against those rules. This is your team's **architecture lint**: the intended architecture, expressed as code, verified on every update. ### Declaring rules Conformance rules live in a `conformance:` block in the workspace config (no separate file). Each rule has a `source` matcher, a `target` matcher, and an `allow` flag: A **matcher** resolves against service nodes in the system graph: Matcher form Matches `*` every service `tag:` every service whose repo declares that tag (see `tags:` on each repo) anything else a glob over the node id, repo alias, and display name (`frontend`, `api::*`, `*-worker`) A rule with `allow: false` (the default) is a **deny** rule: a structural dependency from a matching source to a matching target is a violation. A rule with `allow: true` is an **exception** that whitelists an otherwise-denied edge. Only structural edges (HTTP, gRPC, event, package, db) are evaluated; behavioral co-change is never treated as a dependency. ### Dependency cycles Independently of any rules, conformance detects **circular dependencies** among services over structural edges (`A → B → … → A`). A cycle means the services cannot be built, deployed, or reasoned about independently. Cycle detection runs even with zero rules declared, so every workspace gets it for free. ### CLI `repowise workspace check` prints violations and cycles and exits non-zero when any are found, so it gates CI: It recomputes from the persisted system graph, so editing rules and re-running picks them up without a full re-index. ### REST `GET /api/workspace/conformance` returns the report from the most recent update, filterable by `repo`. ### MCP `get_conformance` exposes violations and cycles to an agent. The `get_risk` PR-mode directive gains `conformance_violations` and `dependency_cycles` blocks for the findings the diff's repo participates in. ### Conformance view The web UI's Conformance page renders a **dependency-structure matrix (DSM)**: services on both axes, each filled cell a dependency tinted by transport, with rule violations ringed red and cycle cells amber. Governance panels list the violations and cycles. Violations also badge the offending edges on the Live System Map (toggle **Conformance**), reusing the same additive overlay as the breaking-change guard. Because `repowise workspace check` exits non-zero on any finding, wiring it into CI turns your declared architecture into a gate: a pull request that introduces a forbidden dependency or a new cycle fails the build. ## Cross-repo intelligence URL: https://docs.repowise.dev/multi-repo/cross-repo What repowise learns from analyzing several repos together. Co-change pairs, API contracts (HTTP / gRPC / topics), and package dependency mapping. Hidden coupling that single-repo tools can't find. Workspaces give you three classes of insight that simply don't exist in single-repo mode. All three are pure analysis (no extra LLM calls) and they're refreshed on every workspace `update`. ### Co-change pairs When `backend/api/routes.py` and `frontend/src/api/client.ts` always change together, repowise records that as a high-strength co-change pair. There's no import edge between them, but the git history is unambiguous: they're coupled. Detection is a purely temporal, same-author signal: commits from the same author across repos within a 24-hour window count as a pair, with strength decaying over a 180-day time constant so recent co-changes count more than old ones. The result lives in `.repowise-workspace/cross_repo_edges.json` and surfaces in two places: **Workspace dashboard**: `/w//co-changes`, ranked by strength. **`get_context` and `get_risk` MCP tools**: when you query a file, its cross-repo co-change partners come back alongside its in-repo ones. ### API contract extraction Repowise scans every workspace repo for: **HTTP route handlers**: Express, FastAPI, Spring, Laravel, Go (gin/echo/chi), ASP.NET (attribute + minimal API), Rust (Axum). Consumers: fetch/axios (JS/TS), requests/httpx (Python), HttpClient/UnityWebRequest/Best.HTTP (C#), reqwest (Rust). **gRPC service definitions**: `.proto` files (services + RPCs), plus per-language dialects (Go, Java, Python, C#, TypeScript, NestJS). **Data / DB contracts**: table *providers* (DDL, ORM entities via SQLAlchemy/Django, JPA, EF Core, ActiveRecord, or Eloquent) paired with table *consumers* (SQL string literals in app code, matched heuristically). Renders as a `db` edge. **Message topics**: Kafka, RabbitMQ, NATS publishers and subscribers. It then matches **providers** with **consumers** across repos. If the backend exposes `POST /api/users` and the frontend calls `fetch('/api/users', { method: 'POST' })`, that's one contract link. Test files are excluded from extraction: directories named `tests/`, `__tests__/`, or `__mocks__/` are skipped by name, and files matching `test_*.py`, `*_test.py`, `*_test.go`, `*.test.*`, `*.spec.*`, `*.e2e.*`, or `conftest.py` are always excluded regardless of directory. Visible at `/w//contracts`, filterable by type and repo. Each contract type can be toggled off via the `contracts:` block in `.repowise-workspace.yaml`: ### Package dependency mapping Repowise reads each repo's manifest: `package.json` (npm / pnpm / yarn workspaces) `pyproject.toml` (Poetry, PEP 621) `go.mod` `pom.xml` (Maven) `Cargo.toml` When one repo depends on another as a published or workspace package, it shows up as an explicit dependency edge, and changes to the upstream package surface as risk signals on consumers. ### Why it matters The most expensive bugs come from **implicit coupling**: the kind where a refactor in one service silently breaks another because the connection lived in commit history rather than code. Repowise makes that connection explicit: Without workspaces With workspaces Refactor `backend/api/users.py` Refactor `backend/api/users.py` `get_risk` shows 4 in-repo dependents `get_risk` shows 4 in-repo dependents **+ 2 cross-repo consumers via the `POST /api/users` contract + 1 frontend co-change partner** Ship; frontend breaks in staging Realise the frontend client needs an update before merging The intelligence is automatic: no annotations, no manual contract declarations. If your code is consistent enough that humans can reason about it, repowise can extract the contracts. ### Where this goes next Co-changes, contracts, and package deps are each a flat list. Repowise folds all three into one normalized system graph, the structure every other cross-repo view reads: System graph & map renders services and their typed relationships, with extraction diagnostics that explain why a contract link did or didn't form. Cross-repo blast radius walks the graph to show what breaks downstream when you change a service. Breaking-change guard diffs provider contracts on every update and flags the consumers each incompatible change endangers. Architecture conformance checks the live graph against the dependency rules you declare, and detects cycles. Architecture metrics give propagation cost, the cyclic core, per-service roles, and a 1-10 score. ## System graph & map URL: https://docs.repowise.dev/multi-repo/system-map The service-granular system graph repowise folds every cross-repo signal into, the Live System Map that renders it, and the extraction diagnostics that explain why a contract link did or didn't form. The contracts, package dependencies, and co-changes repowise extracts are each a flat list. The workspace layer folds them into a single normalized **system graph**, the one structure every cross-repo view reads. It is rebuilt automatically on every `repowise update --workspace` and persisted to `.repowise-workspace/system_graph.json`. ### Nodes are services, not repos A monorepo with three detected service boundaries (a `package.json`, `go.mod`, or `Cargo.toml` sub-directory) shows three nodes. The repo is a grouping attribute on each node. A repo with no sub-boundary collapses to a single repo-root node. Each node carries its provider/consumer counts, the contract types it participates in, and flags for orphan or isolated services. ### Edges are typed and honest Every edge carries: a `kind`, one of `http`, `grpc`, `event`, `package`, `co_change`, or `db`; a `match_type`, one of `exact`, `candidate`, `manual`, or `inferred`; a `confidence` and a `weight` (how many underlying contracts, deps, or co-changes it aggregates); `contract_refs` back-pointers, so any view can drill from an edge to its evidence. Edge direction is uniform: **`source` depends on or calls `target`.** A consumer points to the provider it calls; a dependent repo points to the repo it imports. Structural edges (contracts, package deps) are flagged distinctly from behavioral co-change edges, so repowise never conflates "these change together" with "these call each other". Fetch the graph over REST with `GET /api/workspace/system-graph`, or explore it visually in the Live System Map. ### Live System Map The web UI renders the system graph as an always-current diagram at `/workspace/system-map`. It is the visual counterpart to the REST endpoint, the same nodes and edges laid out and explorable, never a hand-drawn picture. **Service nodes**, coloured by category (service, frontend, worker, library, external), with a health ring rolled up from the owning repo and small flags for orphan or isolated services. **Typed edges** distinguished by `kind` (colour and glyph) and by `match_type` (solid for exact/manual, dashed for candidate, dotted for inferred co-change). Behavioral co-change edges read differently from structural contract and dependency edges. **Filters** to toggle each edge kind on or off, and a service ↔ repo switch that collapses a monorepo's services into one node per repository. **Drill-down**: click a service to inspect its providers/consumers and connected services; click an edge to see its match type, confidence, weight, and the underlying contract evidence, with a jump to the Contracts view. A **legend** explaining the edge colours, dash patterns, and the health scale. The map appears once the workspace has at least two indexed repositories with detected relationships. It shows honest empty states otherwise. ### Extraction diagnostics When the cross-repo link count looks low, diagnostics explain why. Computed alongside contract matching, they report, per repo and contract type, how many providers and consumers were found, which consumers went unmatched (and why), and which providers have no consumer at all. The report covers: **Provider / consumer counts** per repo, broken down by contract type. **Unmatched consumers**, grouped by reason: `no_provider`, no provider anywhere declares a matching route/service/topic. `internal_only`, the only matching provider is in the same repo and service, so the call is intra-service and intentionally not surfaced as a cross-repo link. `unlinked`, a cross-service provider with a matching id exists, but no link formed (a candidate worth inspecting). **Orphan providers**, endpoints declared but never consumed by any repo. **Weak links**, matched links below the confidence threshold. The same data is available over REST at `GET /api/workspace/diagnostics` and is embedded in the system graph artifact's `diagnostics` block. Diagnostics is the first thing to run when a service you expect to be connected shows up isolated on the map. The `unlinked` bucket usually points at a route or topic id that almost matched but normalized differently on the two sides. ## Workspace MCP mode URL: https://docs.repowise.dev/multi-repo/workspace-mcp One MCP server, every repo. Pass repo="backend" to target a specific workspace repo, or repo="all" to federate a query across the entire workspace, plus three workspace-only tools for cross-repo blast radius, conformance, and architecture. In workspace mode, every one of the core MCP tools takes an extra `repo` parameter, and three workspace-only tools appear for questions that have no single-repo equivalent. The default repo (set by `repowise workspace set-default`) is targeted when `repo` is omitted, just like single-repo mode. ### Three ways to address a workspace `repo=` Behavior omitted Target the workspace's default repo. `"backend"` Target the repo with that alias. `"all"` Federate the query across every repo in the workspace. `repo="all"` is supported by `search_codebase`, `get_context`, and `get_overview`. It is not supported by `get_symbol`, which always resolves one symbol in one repo. ### How federated queries work Each tool implements `repo="all"` slightly differently: **`get_overview(repo="all")`**, returns workspace-level totals (repos, files, symbols), per-repo dependency graph, and cross-repo topology / contract links. **`search_codebase(repo="all")`**, runs the search in each repo and merges results with Reciprocal Rank Fusion (k=60). **`get_dead_code(repo="all")`**, aggregates findings via RRF and applies a cross-repo confidence adjustment when a "dead" symbol has external consumers. **`get_why(repo="all")`**, keyword search across every repo's decision records (capped at 15 merged results). **`get_context`** and **`get_risk`**, when the target lives in repo A but has cross-repo co-change partners or contract consumers in repos B and C, those signals are appended to the response. ### Cross-repo directives in `get_risk` When you pass `changed_files` in workspace mode, the `get_risk` `directive` block carries the changed repo's cross-repo fallout in addition to the in-repo blast radius: `will_break_consumers`, services in *other* repos that depend on this one (structural impact), each with `repo`, `service`, `distance`, `score`, and the edge kinds carrying the impact. `missing_cross_repo_cochanges`, services in other repos that historically co-change with this one but aren't in the diff. `breaking_changes`, provider contracts in this repo that changed *incompatibly* since the last index (a removed route or field, a type or field-number change, a newly-required field), each with the impacted consumers it endangers. See Breaking-change guard. `conformance_violations` and `dependency_cycles`, the declared dependency-rule breaches and circular dependencies the diff's repo participates in. See Architecture conformance. ### Workspace-only tools These three tools only exist when the server runs over a workspace. They read the system graph directly. ### `get_blast_radius` Cross-repo downstream impact: if you change this service, what breaks across the other repos? See Cross-repo blast radius. Parameter Type Required Description `targets` string\[] Yes Node ids (`repo` or `repo::service/path`) or repo aliases `max_depth` int No Reachability depth (1-8, default 3) `include_behavioral` bool No Include co-change (behavioral) edges (default true) **Returns:** the impacted services ranked by impact `score`, each with `distance` (hops), `structural` (a real dependency vs co-change only), and the edge kinds that carried the impact; plus `impacted_repos`, `structural_count` / `behavioral_count`, `total_impacted`, and any `unresolved_targets`. **When to use:** before changing a high-fan-out provider, to see who consumes it across repo boundaries. Structural impact (`will break`) outweighs behavioral co-change (`may drift`). ### `get_conformance` Architecture governance: does the live system graph obey the declared dependency rules, and are there circular service dependencies? See Architecture conformance. Parameter Type Required Description `repo` string No Limit findings to those involving this repo alias **Returns:** `violations` (each with the offending `source`/`target` services, the `rule_source`/`rule_target` matchers that fired, and the `edge_kind`), `cycles` (each with the participating `nodes` and `length`), and the `violation_count` / `cycle_count` / `rules_evaluated` rollups. **When to use:** before a refactor that changes service boundaries, or to audit whether the live architecture still matches the intended one. Rules are declared under `conformance:` in `.repowise-workspace.yaml`. ### `get_architecture` The one evaluative read of the whole system: how coupled is it, where is the architectural core, and a single 1-10 architecture score. Deterministic, structural edges only (co-change excluded). See Architecture metrics. **Parameters:** none. **Returns:** `score` (1-10), `architecture_type` (`core-periphery` or `hierarchical`), `propagation_cost_pct` (share of other services the average service reaches), `core_size` / `core_ratio` / `core_members` (the largest cyclic group), `cycle_count`, `conformance_violations`, a `role_breakdown` (count of Core / Shared / Control / Peripheral services), and a one-line `summary`. **When to use:** before a cross-service refactor, or to gauge and compare overall system structure over time. ### Setting the default The default determines what `repo`-less queries hit. Set it to whichever repo your team works in most often. ### Single endpoint, no extra setup `repowise init .` at the workspace root writes a single `.mcp.json` that points at the workspace MCP server. Your editor doesn't need to know which repo it's targeting, the tools handle routing. The server lazy-loads each repo's index on first query and evicts with an LRU policy once more than 5 repos are loaded at once, to bound memory in large workspaces. The default repo is never evicted. The MCP transport's per-call token budget still applies in workspace mode. `repo="all"` results are aggregated and capped; if you need deeper paging, narrow to a specific repo with `repo=""`. ## Workspace setup URL: https://docs.repowise.dev/multi-repo/workspace-setup Index multiple related git repos as a single repowise workspace. Get cross-repo co-changes, API contract matching, and federated MCP queries on top of per-repo intelligence. A **workspace** is a parent directory containing several git repos that repowise indexes and analyzes together. Each repo gets its own `.repowise/wiki.db` (the same as single-repo mode), plus a workspace layer adds cross-repo signals on top: co-changes, API contracts, and package dependency mapping. ### When to use a workspace Backend and frontend in separate repos. Microservices that talk over HTTP, gRPC, or topics. A monorepo split into sub-repos (Git submodules, sister projects). Anywhere you want to understand cross-repo dependencies and co-change patterns. ### Directory layout Each subdirectory must be its own git repo. ### Initialise Repowise scans for git repos under the cwd, asks which ones to include (or `--all` to include every match), then indexes each repo and runs cross-repo analysis. The `.repowise-workspace.yaml` config is generated automatically. To add a repo later: To remove a repo from the workspace (the repo's `.repowise/` directory is preserved on disk): See the `workspace` CLI page for the full subcommand list. ### What you get on top of single-repo **Cross-repo co-changes**: files that change together across repos without an import link. **API contract extraction**: HTTP routes, gRPC services, message topics, and app-to-database contracts matched provider-to-consumer. **Package dependency mapping**: when one repo declares another as a dependency in its manifest. **Federated MCP**: pass `repo="backend"` or `repo="all"` to any of the core MCP tools, plus three workspace-only tools for blast radius, conformance, and architecture metrics. **Workspace dashboard**: aggregate stats and contract / co-change views. **Workspace CLAUDE.md**: auto-generated context covering every repo and the relationships between them. Detail: Cross-repo intelligence, the system graph and map, blast radius, breaking-change guard, architecture conformance, architecture metrics, and Workspace MCP mode. **One MCP server, every repo.** The MCP server knows about the whole workspace. You don't need to spin up one server per repo: your editor talks to a single endpoint and the tools route by `repo`. ## Benchmarks URL: https://docs.repowise.dev/reference/benchmarks Every number repowise publishes, with the method behind it and the limits it carries, across three studies on public codebases. Three studies, all run on public codebases so you can re-run them: agent efficiency, distill compression, and whether the code-health score actually predicts defects. The harnesses, raw run logs, and full reports live in repowise-bench. Nothing here is measured on a private corpus. Two ground rules for how we report: **The limits ship with the wins.** Every study below has a "what this does not show" section, and it is the section we would want to read first if someone else published these numbers. **Token savings are not automatically dollar savings.** Agent-side prompt caching mutes the cost delta on repeated context even where token counts drop sharply. We report tokens, reads, and calls because those are what the measurements establish. ### 1\. Agent efficiency Most of a coding agent's spend goes to exploration: greping for symbols, reading candidate files, re-reading them as the context window fills. Repowise does that work once, offline, so the agent skips it on every query. Paired SWE-QA runs on real repositories, same model and same harness, with and without repowise's MCP tools: Measure Result Tokens to load context up to **−96%** File reads **−69% to −89%** Tool calls **−49% to −70%** Answer quality at parity with raw exploration The mechanism is context substitution, not a smaller model or a shorter answer. Loading one commit's context through `get_context` costs **2,391 tokens against 64,039** raw, roughly 27x fewer. On a long multi-step investigation the effect compounds: **−41% of the context re-read across the whole session**, because the agent is not re-reading files it already saw to recover a detail. Reports: flask48, flask v3, sklearn48. ### How to reproduce Clone repowise-bench and the target repository (`pallets/flask` or `scikit-learn`) at the pinned commit named in the report you want. Index the target with `repowise init `. Run the harness twice over the same SWE-QA question set with the same model: once with the repowise MCP server registered, once without. Each report names its own question set, model, and pinned commit. Compare the per-run token, file-read, and tool-call totals the harness emits. The answer-quality check is a graded comparison of the two answer sets, also described in the report. The `get_context` figure is the cheapest thing to check on your own repo: run `get_context` on a commit and compare the response size against the raw bytes of the files it covers. ### What this does not show **Not a SWE-bench-style task-completion result.** These runs measure the cost and shape of answering questions about a codebase, not the rate at which an agent lands a correct patch. **Answer quality is "at parity", not "better".** The claim is that the agent reaches the same quality of answer for far less exploration. If a benchmark showed a quality gain, we would report a quality gain. **The ranges are wide because the repos differ.** "up to −96%" is a ceiling observed on one context-loading comparison, not the average case. Read the per-repo reports for the distribution. **Prompt caching changes the economics.** With agent-side caching, a large repeated context can be cheap in dollars even when it is expensive in tokens. Token reduction still buys context-window headroom and fewer round trips. It no longer buys a proportional dollar saving. **Same model, same harness, one vendor's agent.** We have not shown the effect transfers unchanged to every agent framework. ### 2\. Distill: command-output compression `repowise distill ` compresses command output *before* the agent reads it: errors first, exit code preserved, and every omission recoverable through an inline `[repowise#]` marker (`repowise expand `). Paired runs on a public OSS repository (microdot), one run per command, tokens estimated at chars/4, the same estimator the savings ledger uses: Command Raw tokens Distilled Saved `pytest -q` (11 failures) 3,374 1,317 **61%**, all 11 `FAILED` lines preserved `git log -50` 3,064 331 **89%** `git diff` (30 commits of history) 62,833 8,635 **86%** `git log --oneline -30` 321 321 0%, already compact, passed through `git status` (clean tree) 83 83 0%, too small to distill, passed through The two 0% rows are the net-positive guard doing its job: distill never inflates small output. In an end-to-end spot-check on the same repo with a seeded 11-failure bug, the agent reached the identical root-cause line and fix from distilled output as from raw. Across the fixture suite, the core filters hold a median of at least 60% reduction on test, build, and lint output with zero error-line loss, asserted in CI. ### How to reproduce Clone microdot (or any repo with a test suite) and index it with `repowise init`. For each command, capture the raw output and the distilled output: Compare sizes with the chars/4 estimator. `repowise saved` reports the same accounting cumulatively across a session. To reproduce the failure-preservation claim, diff the `FAILED` lines in `raw.txt` against `distilled.txt`. They should match exactly. ### What this does not show **One run per command, one repository.** These are point measurements, not a distribution over many repos with confidence intervals. Your ratios will differ with your test suite's verbosity and your diff sizes. **Reduction is not comprehension.** The 61/89/86% figures measure bytes removed. The evidence that the removal is safe is narrower: preserved failure lines, the CI-asserted zero-error-line-loss fixtures, and a single end-to-end agent spot-check. One spot-check is an existence proof, not a rate. **`git diff` compresses hardest because diffs are the most redundant input.** Do not read 86% as the expected saving on arbitrary commands. **Token estimation is chars/4, not a tokenizer.** It is consistent across the raw and distilled sides, so the ratio is sound, but the absolute counts are approximations. **Dollar savings again depend on caching.** `repowise saved` prices tokens at your agent's model rate; a cached context reduces the real-world delta. ### 3\. Code health predicts defects The health score is worth something only if the files it flags are the files that actually break. Scores are collected at a historical commit (T0), bug-fixing commits are counted over the following six months, and the two are correlated with strictly no leakage: nothing after T0 feeds the score. ### Cross-project validation Across **21 open-source repositories spanning 9 languages** and 2,826 files: **Mean ROC AUC 0.74** (95% CI 0.68 to 0.79) at identifying the files that go on to receive bug fixes, reaching **0.90** on individual repos. ROC AUC is the probability the score ranks a known-buggy file worse than a clean one: 0.5 is a coin flip, 1.0 is perfect. **Survives controlling for file size**: partial Spearman rho = −0.16, so the signal is not simply "flag the big files". **Out-discriminates the obvious baselines**: +0.10 AUC over recent churn and +0.12 AUC over prior-defect history, DeLong p \< 1e-9. **Holds on an external dataset it never saw**: PROMISE/jEdit CK-metrics, AUC **0.76 to 0.78**, within about 0.03 of that dataset's own tuned model. This held-out result is the main evidence the markers are not overfit to the calibration corpus. Full report: health-defect/BENCHMARK\_REPORT.md. ### CodeScene head-to-head CodeScene is the closest commercial product on code health and the only vendor in the category with a published empirical defect study (the "Code Red" correlation study, Tornhill and Borg, TechDebt 2022). Both tools ran over the **same 2,770 files across 9 languages**, scored at the same leakage-free commit against the same defect labels: Axis (paired tests) repowise CodeScene Recall at a 20%-of-lines review budget **0.173** 0.074 Effort-aware ranking (Popt) **0.607** 0.462 Defect density, size-normalized (defects/KLOC, Alert:Healthy) **2.18x** 0.56x Ranking by repowise health surfaces about **2.3x the defects under a fixed review budget**. The deltas are Popt +0.144 and recall +0.098, both p = 0.003, paired and significant. This is not an unqualified "better than CodeScene". The ROC AUC edge is marginal (+0.026, p = 0.054) and precision\@20% is a tie. See the caveats below before quoting the comparison. Full methodology and confidence intervals: health-defect/COMPARISON\_REPORT.md. ### The per-repo self-check Separate from the cross-project study, every index prints a check against your own history: Agents read the same block over MCP with `get_health(include=["accuracy"])`, and `repowise health` prints it on the CLI. It stays silent on repos with too little history to be honest (fewer than 25 scored files, or fewer than 5 recently-fixed files). ### How to reproduce Clone repowise-bench and open `health-defect/`. The corpus list, the T0 commit per repo, and the bug-window definition are all pinned there. The harness checks out each repo at T0, runs the health pass, then labels files from `fix:` commits in the following six months and computes ROC AUC, Popt, recall\@20%, and the DeLong comparisons against the churn and prior-defect baselines. The PROMISE/jEdit arm needs no repowise index at all: it scores the published CK-metrics dataset with the same marker weights. The CodeScene arm requires a CodeScene account. The comparison is restricted to the 2,770 files both tools scored, so it can be re-derived from the two exported score sets plus the shared label file. For the per-repo self-check, run `repowise init` then `repowise health` on any repo with enough history. ### What this does not show **The per-repo callout is an association, not a forward prediction.** `prior_defect` is itself one (down-weighted) input to the score, so the "16/20 lowest-health files" line is measured on the indexed history. The cross-project study is the leakage-free one. **Within a size band the signal is weak.** Among files of similar size the AUC sits near 0.49, so part of the headline number is that larger files carry more risk. We report this because it is the most important caveat on the AUC. **A prior-defects baseline still wins on effort.** Under a fixed review budget that baseline finds bugs slightly more efficiently than the repowise score (Popt by 0.085), even though the score out-discriminates it on AUC. **The CodeScene comparison is scoped.** It covers 2,770 shared files at one leakage-free commit. The significant wins are Popt, recall\@20%, and defect density. The ROC AUC edge is marginal (+0.026, p = 0.054) and precision\@20% is a tie, not a win. The operating points also differ: CodeScene flags about 27 files where repowise flags 132, a more conservative threshold, which is why its precision reads higher. It says nothing about CodeScene's breadth (28+ languages, knowledge maps, off-boarding simulation). **"Bug fix" means a `fix:` commit touching the file.** That is a proxy for a defect, and it inherits every quirk of the corpus repos' commit hygiene. **Maintainability and performance are not validated this way.** Maintainability weights are expert-set and the performance signal is high-precision, low-recall and advisory. Only the defect pillar carries these numbers, which is exactly why repowise refuses to blend the three into one headline score. ### Related: static performance risk The performance pillar has its own separate benchmark. On a 12,000-file corpus, standard linters (clippy, ruff `PERF`, ESLint, golangci-lint) found **0** of the cross-function I/O-in-loop cases, while repowise surfaced 557 findings, about 90 of them spanning function boundaries, with 98% in categories ruff has no rule for. Findings are ordered by impact rather than raw count (NDCG 0.755 against 0.292 for severity only). Hand-labeled `io_in_loop` precision on an 11-repo OSS corpus: Go 96.7%, TypeScript 100%, Python 96.2%. One caveat travels with it: the Rust dialect was new when the benchmark ran and clippy could not be built end-to-end on the corpus under Windows, so the Rust comparison is catalogue-level, not a measured head-to-head. Data and method: perf-detection. ### See also Code health: the score, the markers, the bands, and the validation in full. Glossary: ROC AUC, Popt, and the rest of the vocabulary these studies use. repowise-bench: harnesses, raw logs, and every full report. ## Computed glossary URL: https://docs.repowise.dev/reference/glossary Every term repowise computes across traversal, graph, git, analysis, generation, workspace, persistence, and MCP. The vocabulary map for wiki pages, graph records, risk signals, contracts, and tool responses. This glossary describes the data Repowise computes while indexing, analyzing, generating, serving, and exporting a repository. It is based on the code paths in `packages/core`, `packages/server`, and `packages/cli`, not only on README files. Use this as the vocabulary map for wiki pages, graph records, risk signals, workspace overlays, MCP responses, and CLI output. ### Quick Map Area Main code paths What gets computed Traversal and parsing `packages/core/src/repowise/core/ingestion/traverser.py`, `packages/core/src/repowise/core/ingestion/parser.py`, `packages/core/src/repowise/core/ingestion/models.py` Files, languages, entry points, symbols, imports, exports, calls, inheritance, parse errors, content hashes Graph construction `packages/core/src/repowise/core/ingestion/graph.py`, `call_resolver.py`, `heritage_resolver.py`, `framework_edges.py`, `dynamic_hints/` File and symbol nodes, import/call/heritage/framework/dynamic/co-change edges, centrality, SCCs, communities, execution flows Git intelligence `packages/core/src/repowise/core/ingestion/git_indexer.py` Churn, ownership, hotspots, bus factor, co-change partners, significant commits, temporal scores, rename and merge signals Analysis `packages/core/src/repowise/core/analysis/` Dead-code findings, decision records, decision staleness, security findings, PR blast radius, execution flows, communities Generation `packages/core/src/repowise/core/generation/` Wiki page contexts, page types, source hashes, summaries, freshness, confidence decay, RAG context, job checkpoints, reports, costs Workspace intelligence `packages/core/src/repowise/core/workspace/` Workspace repo scan, cross-repo co-changes, package dependencies, API contracts, contract links, workspace CLAUDE.md data Persistence and search `packages/core/src/repowise/core/persistence/`, Alembic migrations ORM rows, FTS rows, vector records, answer cache, cost rows, graph rows API, MCP, CLI `packages/server/src/repowise/server/`, `packages/cli/src/repowise/cli/` Dashboard schemas, MCP tool payloads, status tables, doctor checks, exports, costs, augment hook context ### Traversal And Repository Structure Term Definition Computed by Example Includable source file A file that survives ignore rules, blocked patterns, size limit, binary detection, generated-file detection, and language detection. `FileTraverser._build_file_info()` `packages/core/src/repowise/core/ingestion/parser.py` `FileInfo` Per-file metadata used by the parser and graph builder. `FileTraverser.traverse()` `{path: "src/app.py", language: "python", is_test: false, is_entry_point: true}` Language tag Canonical language value from file extension, special filename, or shebang. `ingestion/models.py`, `traverser.py`, `languages/registry.py` `python`, `typescript`, `go`, `terraform`, `openapi`, `unknown` Test file flag Whether a file looks like a test/spec/fixture file. `FileTraverser._build_file_info()` and community/test-gap helpers `tests/test_auth.py -> is_test=true` Config file flag Whether a file is classified as configuration. `FileTraverser._build_file_info()` `pyproject.toml -> is_config=true` API contract flag Whether a file is an API contract format. `FileTraverser._build_file_info()` `openapi.yaml -> is_api_contract=true` Entry point flag Whether a filename or language-specific entry pattern marks a file as a starting point. `FileTraverser._build_file_info()` `main.py`, `server.ts`, `Dockerfile` depending on rules Traversal stats Counts of included files and skip reasons. `TraversalStats` in `traverser.py` `{included: 240, skipped_binary: 3, skipped_generated: 12}` Package info A package/workspace detected from manifests near the repo root. `FileTraverser._detect_monorepo()` `{name: "core", path: "packages/core", manifest_file: "pyproject.toml"}` Repo structure High-level structure summary used by overview generation. `FileTraverser.get_repo_structure()` `{is_monorepo: true, total_files: 820, entry_points: ["packages/cli/src/.../main.py"]}` Language distribution Fraction of included files by language. `get_repo_structure()` `{"python": 0.72, "typescript": 0.18, "markdown": 0.10}` Estimated LOC Fast line-count estimate from file sizes, not exact source line counting. `get_repo_structure()` `total_loc = sum(size_bytes // 40)` Content hash SHA-256 of raw file bytes. `compute_content_hash()` in `ingestion/models.py` `3f786850e387550fdab836ed7e6dc881de23001b...` ### Parsing, Symbols, Imports, Calls Term Definition Computed by Example `ParsedFile` Full parse result for one file: file metadata, symbols, imports, exports, calls, heritage, docstring, parse errors, content hash. `ASTParser.parse_file()` `ParsedFile(symbols=[...], imports=[...], calls=[...])` Symbol A function, class, method, interface, enum, constant, type alias, module, macro, variable, etc. `ASTParser._extract_symbols()` `src/app.py::create_app` Symbol ID Stable ID derived from path and name, including parent class for methods. `ASTParser._extract_symbols()` `src/models.py::User::save` Qualified name Dot-form symbol name derived from path and parent. `_build_qualified_name()` `src.models.User.save` Symbol kind Canonical symbol type. `LanguageConfig.symbol_node_types` plus refiners `function`, `class`, `method`, `interface`, `struct`, `trait` Signature Compact declaration text. `build_signature()` via parser extractors `def create_app(config: Config) -> FastAPI` Symbol docstring Human text attached to a symbol, when extractable. `extract_symbol_docstring()` `"Create and configure the API app."` Module docstring File-level docstring. `extract_module_docstring()` `"Command-line entry points."` Visibility Public/private/protected/internal classification. Language-specific visibility helpers `_helper -> private`, `UserService -> public` Async flag Whether a symbol is async. `_is_async_node()` `async def fetch() -> is_async=true` Complexity estimate Symbol complexity field, persisted to symbols. Parser/model pipeline; defaults to `1` unless language extraction enriches it `complexity_estimate: 3` Decorators Decorator/modifier strings captured with a symbol. `ASTParser._extract_symbols()` `["@router.get('/users')"]` Import Raw import statement plus normalized module path and imported names. `ASTParser._extract_imports()` `{raw_statement: "from .db import Session", module_path: ".db", imported_names: ["Session"]}` Named binding Alias-aware import binding. `extract_import_bindings()` `{local_name: "np", exported_name: null, is_module_alias: true}` Resolved import Import whose module path was matched to a repo file. `GraphBuilder.build()` through `resolve_import()` `from .models import User -> src/models.py` Export list Public top-level symbol names exported by a file. `ASTParser._derive_exports()` `["create_app", "Settings"]` Call site Raw function or method call extracted from the AST. `ASTParser._extract_calls()` `{target_name: "save", receiver_name: "user", line: 42, argument_count: 1}` Enclosing caller symbol The symbol that contains a call site. `_find_enclosing_symbol()` `src/app.py::main` Heritage relation Raw inheritance or implementation relationship. `extract_heritage()` `OrderController extends BaseController` Parse error Non-fatal syntax/tree-sitter error description. `_collect_error_nodes()` `Parse error at line 17` ### Graph Entities And Edges Term Definition Computed by Example Dependency graph Directed NetworkX graph containing file nodes, symbol nodes, and edge metadata. `GraphBuilder` `nx.DiGraph` with nodes `src/app.py`, `src/app.py::main` File node Graph node for a source file. `GraphBuilder.add_file()` `{node_type: "file", language: "python", symbol_count: 8}` Symbol node Graph node for an extracted symbol. `GraphBuilder.add_file()` `{node_type: "symbol", kind: "function", name: "main"}` External node Node for third-party or unresolvable dependencies. Import resolution paths `external:react` Synthetic module symbol Symbol node for top-level calls in a file. `GraphBuilder.add_file()` `src/app.py::__module__` `defines` edge File-to-symbol containment. `GraphBuilder.add_file()` `src/app.py -> src/app.py::main` `imports` edge File-to-file import relationship. `GraphBuilder.build()` `src/app.py -> src/settings.py` `imported_names` edge payload Names imported along an import edge. `GraphBuilder.build()` `["Settings", "load_config"]` `has_method` edge Class-to-method containment. `GraphBuilder.add_file()` `src/models.py::User -> src/models.py::User::save` `calls` edge Symbol-to-symbol call relationship. `CallResolver`, then `GraphBuilder._resolve_calls()` `src/app.py::main -> src/db.py::connect` Call confidence Confidence that a call edge points to the right callee. `CallResolver` `0.95` same-file, `0.90` import binding, `0.50` global unique `extends` edge Class/struct inheritance edge. `HeritageResolver` `UserView -> BaseView` `implements` edge Interface/trait implementation edge. `HeritageResolver` `UserRepository -> Repository` Heritage confidence Confidence that inheritance/implementation resolved correctly. `HeritageResolver` `0.95` same-file, `0.90` imported, `0.50` global unique `framework` edge Synthetic edge from framework conventions. `framework_edges.py` `urls.py -> views.py`, `app.py -> routers/users.py` Dynamic edge Edge inferred from runtime/dynamic patterns. `dynamic_hints/*` and `GraphBuilder.add_dynamic_edges()` `{edge_type: "dynamic_imports", hint_source: "django", weight: 1.0}` `co_changes` edge File-to-file historical coupling edge. `GraphBuilder.add_co_change_edges()` from git metadata `src/a.py -> src/b.py` with `weight: 4.2` Stem map Import-stem to candidate file path lookup used for import resolution. `GraphBuilder._build_stem_map()` `{"models": ["src/models.py", "tests/models.py"]}` File subgraph File-only graph used for PageRank and betweenness. `GraphBuilder.file_subgraph()` All file/external nodes, excluding `co_changes` edges PageRank File centrality in the import graph. `GraphBuilder.pagerank()` `0.01842` Betweenness How often a file sits on shortest paths. `GraphBuilder.betweenness_centrality()` `0.0067` SCC Strongly connected component, used to detect dependency cycles. `GraphBuilder.strongly_connected_components()` `{"src/a.py", "src/b.py"}` SCC page group Non-singleton SCC that gets a cycle page. `PageGenerator.generate_all()` `scc-3` Graph JSON Node-link serialization of the graph. `GraphBuilder.to_json()` `{"directed": true, "nodes": [...], "links": [...]}` ### Communities And Execution Flows Term Definition Computed by Example File community Cluster of related production files, with tests assigned to their most-related production community. `detect_file_communities()` `community_id: 2` Symbol community Cluster of symbol nodes based on call and heritage edges. `detect_symbol_communities()` `symbol_community_id: 5` Community algorithm Partition algorithm used. `communities._partition()` `leiden`, `louvain`, `none`, `failed` Oversized community split Second partition pass for communities larger than a graph fraction. `_split_oversized()` A 300-file cluster split into smaller clusters Community label Human label derived from non-generic path segments or filename keywords. `_heuristic_label()` `api/routes`, `auth`, `payments` Community cohesion Ratio of actual intra-community edges to possible edges. `_cohesion_score()` `0.2143` Dominant language Most common language among community members. `_dominant_language()` `python` Neighboring community Adjacent community from graph edges, surfaced by MCP/API. `tool_community.py`, graph routers `{community_id: 4, edge_count: 9}` Entry point score 0 to 1 score for a function/method as an execution start. `_score_entry_point()` `0.735` for `main()` Entry point score signals Weighted fan-out, low in-degree, visibility, name pattern, and file entry flag. `_score_entry_point()` public `main()` with many calls scores high Execution flow BFS trace following high-confidence call edges from an entry point. `trace_execution_flows()` `main -> load_config -> connect_db` Cross-community flow Execution flow that visits more than one community. `_bfs_trace()` `communities_visited: [0, 3]` Flow depth Number of call hops in a traced flow. `_bfs_trace()` `depth: 4` Flow deduplication Keeps the longest flow per shared first-three-node prefix. `_deduplicate_flows()` Two `main -> route -> handler` traces collapse to one ### Git Intelligence Term Definition Computed by Example Git metadata row Per-file history, ownership, churn, and coupling record. `GitIndexer.index_repo()` and `_index_file()` One `git_metadata` row for `src/app.py` Commit counts Total, 90-day, and 30-day commit volumes. `_index_file()` `{commit_count_total: 87, commit_count_90d: 12, commit_count_30d: 3}` Commit count capped Whether the history reached the configured commit limit. `_index_file()` `true` when `len(commits) >= 500` First/last commit timestamps Oldest and newest commit timestamps for a file. `_index_file()` `first_commit_at: 2024-05-03T10:00:00Z` File age days Days since first commit. `_index_file()` `age_days: 455` Primary owner Dominant owner by blame when available, otherwise by commit count. `_get_blame_ownership()` and `_index_file()` `{name: "Asha", email: "asha@example.com", pct: 0.64}` Top authors Top five authors by commit count. `_index_file()` `[{name: "Asha", commit_count: 20}]` Recent owner Dominant committer in the last 90 days. `_index_file()` `recent_owner_name: "Sam"` Contributor count Number of distinct authors. `_index_file()` `contributor_count: 6` Bus factor Number of contributors needed to account for 80 percent of commits. `_index_file()` `bus_factor: 2` Significant commits Filtered, non-noise commit messages useful for decisions and risk. `_is_significant_commit()` `[{sha: "a1b2c3d4", message: "migrate auth to JWT"}]` PR number PR/MR number extracted from significant commit messages. `_PR_NUMBER_RE` in `git_indexer.py` `pr_number: 128` Commit categories Message classification counts. `_COMMIT_CATEGORIES` in `git_indexer.py` `{"feature": 4, "fix": 11, "refactor": 2}` Lines added/deleted 90d Recent churn by numstat. `_index_file()` `{lines_added_90d: 340, lines_deleted_90d: 87}` Average commit size `(lines_added_90d + lines_deleted_90d) / commit_count_90d`. `_index_file()` `35.6` Merge commit count 90d Number of merge commits touching the file recently. `_index_file()` `merge_commit_count_90d: 2` Original path Earliest path found through rename-follow history. `_detect_original_path()` `legacy/auth/session.py` Temporal hotspot score Exponentially decayed churn score with 180-day half-life. `_index_file()` `2.43` Churn percentile Rank percentile among indexed files by temporal hotspot score, with 90-day commits as tiebreak. `_compute_percentiles()` `0.88` Hotspot flag Top churn file: percentile >= 0.75 and has recent commits. `_compute_percentiles()` `is_hotspot: true` Stable file flag File with more than 10 total commits and no recent 90-day commits. `_index_file()` `is_stable: true` Co-change partner File historically changed in the same commits, with temporal decay. `_compute_co_changes()` `{file_path: "src/schema.py", co_change_count: 3.72, last_co_change: "2026-04-14"}` Git index summary Repo-level indexing result. `GitIndexSummary` `{files_indexed: 420, hotspots: 38, stable_files: 71, duration_seconds: 12.4}` ### Generated Wiki Pages Term Definition Computed by Example Page type Kind of generated documentation page. `PageType` in `generation/models.py` `file_page`, `module_page`, `repo_overview` Generation level Ordered generation tier for page dependencies. `GENERATION_LEVELS` `api_contract: 0`, `file_page: 2`, `repo_overview: 6` Generated page Markdown wiki page plus metadata and token counts. `GeneratedPage` and `PageGenerator._build_generated_page()` `{page_id: "file_page:src/app.py", title: "File: src/app.py"}` Page ID Deterministic natural key. `compute_page_id()` `symbol_spotlight:src/app.py::create_app` Source hash SHA-256 of rendered prompt/source context for freshness comparisons. `compute_source_hash()` 64-character hex Page summary Deterministic first prose paragraph or overview excerpt. `PageGenerator._extract_summary()` `"This file wires the CLI command group and registers subcommands."` Freshness status Whether a page still matches current source and age thresholds. `compute_freshness()` `fresh`, `stale`, `expired` Confidence decay Linear decay from 1.0 to 0.0 over expiry days. `decay_confidence()` `0.77` after part of the expiry window Git-adjusted confidence decay Multiplier adjusted by hotspot/stable state and commit message intent. `compute_confidence_decay_with_git()` Direct refactor on hotspot decays faster Prompt cache key SHA-256 of model, language, page type, and prompt. `PageGenerator._compute_cache_key()` `9e107d9d372bb6826bd81d3542a419d6...` Cached tokens Tokens served from provider cache. Provider response, persisted on pages and report `cached_tokens: 12000` Hallucination warning LLM output mentions symbol-like backticks not found in parsed symbols. `_validate_symbol_references()` `Unknown symbol: "run_worker"` Generation report Run summary by page type, tokens, stale pages, dead-code count, decision count, warnings, elapsed time. `GenerationReport.from_pages()` `{pages_by_type: {"file_page": 45}, total_input_tokens: 980000}` Estimated generation cost Token estimate using USD per 1M-token rates. `GenerationReport.estimated_cost_usd()` and CLI `cost_estimator.py` `$2.3400` Generation job checkpoint JSON state for resumable generation. `JobSystem` `{status: "running", completed_pages: 12, current_level: 2}` Generation status Job lifecycle state. `JobSystem` and `GenerationJob` ORM `pending`, `running`, `completed`, `failed`, `paused` ### Page Contexts Term Definition Computed by Example File page context Template data for one important source file. `ContextAssembler.assemble_file_page()` `{file_path, symbols, imports, dependencies, pagerank_score}` Symbol spotlight context Template data for a top public symbol. `assemble_symbol_spotlight()` `create_app` with signature, source body, callers Module page context Aggregate context for top-level directory/module. `assemble_module_page()` `{module_path: "packages/core", total_symbols: 780}` SCC page context Context for a circular dependency cycle. `assemble_scc_page()` `cycle_description: "Circular dependency cycle: a.py -> b.py"` Repo overview context Whole-repo summary context. `assemble_repo_overview()` `language_distribution`, `top_files_by_pagerank`, `circular_dependency_count` Architecture diagram context Top PageRank nodes, selected edges, communities, SCC groups. `assemble_architecture_diagram()` Mermaid graph inputs for 50 nodes and 200 edges API contract context Raw API contract plus endpoint/schema hints. `assemble_api_contract()` `endpoints: ["GET /users"]`, `schemas: ["User"]` Infra page context Raw infra file plus target names. `assemble_infra_page()` `Dockerfile`, `Makefile`, `terraform` files Diff summary context Changed files, symbol diffs, affected pages, trigger commit/diff. `assemble_diff_summary()` `{added_files: ["src/new.py"], affected_page_ids: [...]}` Cross-package context Monorepo boundary summary between packages. `assemble_cross_package()` `{source_package: "cli", target_package: "core", coupling_strength: 5}` Dependency summaries Summaries of already-generated dependency pages. `assemble_file_page()` with `page_summaries` `{ "src/db.py": "Database access layer..." }` RAG context Snippets from vector search for related generated pages. `_generate_file_page_from_ctx()` `["[file_page:src/schema.py]\nDefines API schema..."]` Token estimate `len(text) // 4` heuristic. `ContextAssembler._estimate_tokens()` `3200` Structural summary mode Large-file outline instead of raw source snippet. `_build_structural_summary()` `[Large file - structural summary mode]` Significant file File selected for its own `file_page`. `_is_significant_file()` Entry point, top PageRank, bridge file, package `__init__.py`, or test with symbols Top symbol selection Public symbols selected by their file PageRank and percentile budget. `PageGenerator.generate_all()` Top 10 percent of public symbols, capped by page budget Page budget Hard cap `max(50, int(num_files * max_pages_pct))`. `PageGenerator.generate_all()` 800 files with 10 percent cap -> 80-page budget ### Dead Code Term Definition Computed by Example Dead-code finding A graph/git finding persisted to `dead_code_findings`. `DeadCodeAnalyzer` `{kind: "unused_export", file_path: "src/api.py", confidence: 0.7}` Unreachable file File with no incoming imports, not an entry point/test/config/contract/whitelisted file. `_detect_unreachable_files()` `src/legacy_adapter.py` Unused export Public symbol in an imported file that no importer names. `_detect_unused_exports()` `symbol_name: "OldClient"` Unused internal Private/internal symbol with no incoming `calls` edges. `_detect_unused_internals()` `_parse_legacy_token` Zombie package Monorepo top-level package with no external package importers. `_detect_zombie_packages()` `packages/old-sdk` Dead-code confidence Heuristic certainty based on age, recent commits, importers, dynamic imports, and deprecation hints. `DeadCodeAnalyzer` `1.0` for year-old unreachable file Safe-to-delete flag Whether confidence passes delete threshold and dynamic patterns do not block deletion. `_make_unreachable_finding()` and other passes `safe_to_delete: true` Dead-code evidence Human-readable reasons for the finding. `DeadCodeAnalyzer` `["in_degree=0 (no files import this)", "No commits in last 90 days"]` Estimated deletable lines Sum of line estimates for safe findings. `DeadCodeAnalyzer.analyze()` `deletable_lines: 420` Confidence summary Counts of high, medium, low confidence findings. `DeadCodeAnalyzer.analyze()` `{"high": 12, "medium": 8, "low": 0}` Finding status User triage status persisted in DB. `DeadCodeFinding.status` `open`, `acknowledged`, `resolved`, `false_positive` ### Decisions And Governance Term Definition Computed by Example Decision record ADR-like row from code comments, git, docs, or CLI/manual entry. `DecisionExtractor`, CRUD, CLI `{title: "Use Redis for sessions", status: "active"}` Inline marker decision Decision extracted from comments such as `WHY:`, `DECISION:`, `TRADEOFF:`, `ADR:`. `scan_inline_markers()` `# DECISION: cache auth sessions in Redis` Git archaeology decision LLM-structured decision inferred from significant commit messages with decision keywords. `mine_git_archaeology()` `migrate from REST client to generated OpenAPI client` README-mined decision Decision extracted from docs such as README, CLAUDE, ARCHITECTURE, DESIGN. `mine_readme_docs()` `"We use SQLite by default because setup should be local-first."` Decision source Provenance of a record. `DecisionRecord.source` `inline_marker`, `git_archaeology`, `readme_mining`, `cli` Decision confidence Source-specific extraction confidence. `DecisionExtractor` `0.95` inline LLM, `0.70` git signal, `0.60` README mining, `1.0` manual Affected files Files linked to a decision from graph neighbors, commit files, or manual input. `DecisionExtractor` `["src/auth.py", "src/session.py"]` Affected modules Top-level modules inferred from affected files or text. `_infer_modules()` `["src", "packages"]` Decision tags Topic labels inferred from keywords or LLM output. `_infer_tags()` and prompts `auth`, `database`, `api`, `security`, `testing` Decision status Lifecycle state. `DecisionRecord.status` `proposed`, `active`, `deprecated`, `superseded` Decision staleness score 0 to 1 score indicating code has moved since a decision. `DecisionExtractor.compute_staleness()` and `crud.recompute_decision_staleness()` `0.63` Conflict boost Staleness increase when newer commit messages contain contradiction signals and overlap decision text. `compute_staleness()` `+0.3` for "migrate away" touching the same concept Decision health summary Counts and lists for stale, proposed, and ungoverned hotspots. `get_decision_health_summary()` and server/CLI routes `{active: 10, stale: 2, proposed: 3}` Ungoverned hotspot Hot file without related architectural decision coverage. Decision health computation `src/payments/processor.py` ### Security Findings Term Definition Computed by Example Security finding Regex or symbol-name signal persisted to `security_findings`. `SecurityScanner.scan_file()` `{kind: "hardcoded_secret", severity: "high", line: 12}` High severity finding Dangerous execution, deserialization, shell, or hardcoded secret/password pattern. `_PATTERNS` in `security_scan.py` `eval_call`, `pickle_loads`, `hardcoded_password` Medium severity finding SQL construction or TLS verification issue. `_PATTERNS` `fstring_sql`, `concat_sql`, `tls_verify_false` Low severity finding Weak hash or security-sensitive symbol name. `_PATTERNS` and symbol scan `weak_hash`, `security_sensitive_symbol` Security snippet Trimmed source line or symbol name for context. `SecurityScanner.scan_file()` `password = "admin"` ### Risk And Blast Radius Term Definition Computed by Example File risk score Pagerank centrality multiplied by `1 + temporal_hotspot_score`. `PRBlastRadiusAnalyzer._score_file()` `0.018 * (1 + 2.4) = 0.0612` Overall PR risk score 0 to 10 composite using average direct risk, max direct risk, and transitive breadth. `_compute_overall_risk()` `7.25` Transitive affected file Importer reached by reverse BFS from changed files. `_transitive_affected()` `{path: "src/api.py", depth: 2}` Co-change warning Historical co-change partner missing from a PR/change set. `_cochange_warnings()` `{changed: "src/a.py", missing_partner: "src/b.py", score: 4.2}` Recommended reviewer Owner aggregate over changed and affected files. `_recommend_reviewers()` `{email: "asha@example.com", files: 7, ownership_pct: 0.63}` Test gap File lacking a matching test path by basename conventions. `_find_test_gaps()` and MCP `_check_test_gap()` `src/auth.py -> true` Risk trend Velocity from 30-day vs prior 60-day commit rates. `tool_risk._compute_trend()` `increasing`, `stable`, `decreasing` Risk type Human bucket for the kind of risk. `tool_risk._classify_risk_type()` `bug-prone`, `churn-heavy`, `bus-factor-risk`, `high-coupling`, `stable` Change pattern Human label from dominant commit category. `tool_risk._derive_change_pattern()` `feature-active`, `fix-heavy`, `dependency-churn`, `mixed-activity` Impact surface Top critical reverse dependencies within two hops. `tool_risk._compute_impact_surface()` `[{file_path: "src/api.py", pagerank: 0.05}]` Risk summary One-line synthesized risk sentence for MCP. `tool_risk._assess_one_target()` `src/auth.py - hotspot score 88% (increasing), 6 dependents...` Top hotspots Highest churn/hotspot files returned for context. `get_risk()` `[{file_path: "src/db.py", hotspot_score: 0.94}]` ### Code Health Metrics And Calibration Term Definition Computed by Example LCOM4 Lack of cohesion: the number of connected components of a class's methods, where two methods are linked when they share a field or call each other. A value of `>= 2` means the class has independent clusters and is a split candidate. `low_cohesion` marker and the Extract Class detector A class whose methods fall into 3 unconnected groups has `lcom4 = 3` ROC AUC Ranking quality of the health score: the probability that a file which gets bug-fixed later scores riskier than a clean one. `0.5` is random, `1.0` is perfect. Offline validation in repowise-bench against a forward defect window Cross-project mean `0.74` over 21 repos, 9 languages Popt Effort-aware ranking quality: the defects surfaced per line of code reviewed, normalized against the optimal and worst orderings. Offline validation in repowise-bench `0.607` on the 2,770-file head-to-head corpus ### Search, Answer Cache, And Retrieval Term Definition Computed by Example Search result Unified full-text or vector result. `SearchResult` in `persistence/search.py` `{page_id, title, page_type, target_path, score, snippet, search_type}` FTS5 query Stop-word-stripped OR prefix query for SQLite. `_build_fts5_query()` `"auth"* OR "session"*` FTS score Positive score from negated SQLite rank or Postgres `ts_rank`. `FullTextSearch` `0.734` Vector score Cosine similarity between query embedding and page embedding. `InMemoryVectorStore.search()` and other vector stores `0.812` Snippet First 200 chars of indexed content. `_snippet()` or vector metadata `"This module handles..."` Answer cache row Cached MCP answer payload. `tool_answer.py` and `AnswerCache` ORM `{question_hash, payload_json, provider_name, model_name}` Question hash SHA-256 of normalized question text. `tool_answer._hash_question()` Same hash for `"How auth works?"` with extra whitespace/case Answer payload Cached `get_answer` result. `get_answer()` `{answer, citations, confidence, fallback_targets, retrieval}` Retrieval hit Search hit hydrated with page metadata and summary. `tool_answer.py` retrieval pipeline `{target_path: "src/auth.py", score: 3.2, summary: "..."}` Retrieval dominance Gating logic comparing top and second search scores. `tool_answer.py` Top score high enough to answer from dominant hit Federated RRF score Reciprocal rank fusion score for workspace search across repos. `tool_search.py` `rrf_score: 0.0164` Confidence score Normalized workspace search confidence. `tool_search.py` `confidence_score: 0.87` ### Persistence Tables And Stored Entities Table or store Computed content Example `repositories` Repo identity plus current indexed `head_commit` and settings JSON. `{name: "repowise", default_branch: "main"}` `generation_jobs` Long-running generation progress. `{status: "running", total_pages: 120, completed_pages: 31}` `wiki_pages` Current generated markdown pages and freshness metadata. `file_page:src/app.py` `wiki_page_versions` Archived historical snapshots on regeneration. `version: 3` `graph_nodes` File and symbol nodes with graph metrics and community metadata. `{node_id: "src/app.py", pagerank: 0.02}` `graph_edges` Typed relationships with imported names and confidence. `{source: "src/app.py", target: "src/db.py", edge_type: "imports"}` `wiki_symbols` Parsed symbols projected into DB. `{symbol_id: "src/app.py::main", kind: "function"}` `git_metadata` Per-file history, churn, ownership, hotspots, co-changes. `{file_path: "src/app.py", is_hotspot: true}` `decision_records` Extracted/manual architectural decisions and staleness. `{title: "Use Postgres for production", status: "active"}` `dead_code_findings` Dead-code analyzer findings and triage status. `{kind: "unreachable_file", safe_to_delete: true}` `security_findings` Static security signals. `{kind: "eval_call", severity: "high"}` `llm_costs` Per-call token and USD cost rows. `{operation: "doc_generation", input_tokens: 2500, cost_usd: 0.012}` `answer_cache` Cached MCP answer payloads keyed by normalized question. `{question: "How does auth work?", question_hash: "..."}` `conversations` and `chat_messages` Chat state and structured message JSON. `{role: "assistant", content_json: {...}}` `webhook_events` Received external events and processing status. `{provider: "github", event_type: "push", processed: false}` SQLite `page_fts` FTS5 mirror of page title/content. Used by full-text search Postgres `wiki_pages.embedding` pgvector embedding column, conditionally added by migration. 1536-dim vector LanceDB `wiki_pages` table Local vector index with page metadata. `{page_id, vector, title, page_type, target_path}` ### LLM Cost And Provider Usage Term Definition Computed by Example Pricing table USD per million input/output tokens by model. `generation/cost_tracker.py` `claude-sonnet-4-6: {input: 3.0, output: 15.0}` Fallback pricing Default pricing for unknown models. `_get_pricing()` `{input: 3.0, output: 15.0}` Call cost `(input_tokens * input_rate + output_tokens * output_rate) / 1_000_000`. `CostTracker.record()` `1000 in, 500 out on Sonnet -> $0.0105` Session cost Cumulative USD for one tracker instance. `CostTracker.session_cost` `2.37` Session tokens Cumulative input plus output tokens. `CostTracker.session_tokens` `845000` Cost totals DB aggregate grouped by operation, model, or day. `CostTracker.totals()` `{group: "file_page", calls: 42, cost_usd: 1.12}` CLI cost estimate Pre-generation token/cost plan. `packages/cli/src/repowise/cli/cost_estimator.py` `{estimated_pages: 82, estimated_cost_usd: 4.60}` ### Workspace Intelligence Term Definition Computed by Example Discovered repo Candidate git repo found under a workspace root. `workspace/scanner.py` `{alias: "api", path: "services/api"}` Workspace config Parsed `.repowise-workspace.yaml`. `workspace/config.py` `{repos: [{alias: "web", path: "apps/web"}]}` Repo update result Per-repo update outcome for workspace update/watch. `workspace/update.py` `{alias: "core", updated: true, file_count: 420, symbol_count: 2100}` Cross-repo co-change File pair in different repos changed by same author within a time window, weighted by recency. `detect_cross_repo_co_changes()` `{source_repo: "api", source_file: "routes/users.py", target_repo: "web", target_file: "users.tsx", strength: 1.34}` Cross-repo package dependency Manifest path dependency from one repo to another. `detect_package_dependencies()` `{source_repo: "web", target_repo: "shared", kind: "npm_workspace"}` Cross-repo overlay JSON payload saved under workspace data dir. `run_cross_repo_analysis()` `{co_changes: [...], package_deps: [...], repo_summaries: {...}}` Cross-repo edge count Per-repo count of co-change and package-dependency edges. `_build_repo_summaries()` `{cross_repo_edge_count: 12}` Workspace CLAUDE.md data Per-repo summaries plus cross-repo overlays and contract links. `generation/editor_files/data.py`, `claude_md.py` `{repos: [...], co_changes: [...], contract_links: [...]}` ### API Contracts Term Definition Computed by Example Contract Provider or consumer API endpoint/topic/service extracted from source. `workspace/contracts.py` and extractors `{contract_id: "http::GET::/api/users/{param}", role: "provider"}` Contract type API surface kind. Contract extractors `http`, `grpc`, `topic` Contract role Whether source provides or consumes the contract. Extractors `provider`, `consumer` Contract confidence Extraction strategy confidence. Extractors and contract matching `0.8` Service boundary Monorepo service path assigned to contracts. `workspace/extractors/service_boundary.py` `services/billing` Normalized contract ID Lowercase/canonical ID used for matching. `normalize_contract_id()` `http::GET::/Api/Users/ -> http::GET::/api/users` Contract link Matched provider-consumer pair across repos/services. `match_contracts()` `{provider_repo: "api", consumer_repo: "web", match_type: "exact"}` Manual contract link Workspace-configured provider/consumer link. `_build_manual_links()` `{match_type: "manual", confidence: 1.0}` Contract store JSON payload saved as `contracts.json`. `run_contract_extraction()` `{contracts: [...], contract_links: [...]}` ### Knowledge Map Term Definition Computed by Example Top owner Owner ranked by number of files primarily owned. `server/services/knowledge_map.py` `{email: "asha@example.com", files_owned: 42, percentage: 18.6}` Knowledge silo File where one owner has more than 80 percent ownership. `compute_knowledge_map()` `{file_path: "src/auth.py", owner_pct: 0.91}` Onboarding target High-PageRank file with few or no documentation words. `compute_knowledge_map()` `{path: "src/core.py", pagerank: 0.04, doc_words: 0}` Documentation word count Word count of the generated file page content. `compute_knowledge_map()` `doc_words: 640` ### CLI-Visible Computed Outputs Command Computed output Example `repowise status` Sync state, current HEAD, indexed commit, DB page counts, graph node counts, pages by type, token totals. `file_page: 52`, `Status: 3 new commit(s)` `repowise status --workspace` Per-repo file/symbol counts, indexed age, HEAD short SHA, stale/up-to-date state. `api 420 files 2,100 symbols 2h ago a1b2c3d stale` `repowise doctor` Health checks for DB, pages, vector store, FTS, graph, stale pages, store drift, coordinator state. `SQL <-> Vector Store: 3 missing` `repowise search` Full-text/vector/wiki or symbol hits. `score 0.83, file_page, src/auth.py` `repowise dead-code` Dead-code table or JSON report. `unused_export src/api.py OldClient 0.70` `repowise decision` Decision list, detail view, health summary, stale records, proposed records, ungoverned hotspots. `Stale decisions: 2` `repowise costs` Grouped LLM cost totals. `group=file_page, calls=45, cost=$1.37` `repowise export` Markdown/HTML/JSON export entries, optionally decisions/dead-code/hotspots. `wiki_pages.json` with page metadata `repowise update` File diffs, adaptive cascade budget, affected page plan, regenerated/decayed page counts, dead-code/decision refresh results. `Adaptive cascade budget: 30` `repowise reindex` Embedding/indexing progress and page counts. `Indexed 430 items -> .repowise/lancedb` `repowise watch` Debounced changed-path batches and forwarded update output. `Detected 3 changed file(s), updating...` `repowise workspace` Workspace repo discovery, config entries, update status, cross-repo hook output. `Found 2 new repo(s)` `repowise generate-claude-md` Editor-file data and rendered `.claude/CLAUDE.md`. `hotspots`, `key_modules`, `decisions` in markdown `repowise augment` Hook-time graph/search enrichment for AI tool calls. Related files, symbols, importers, dependencies `repowise mcp` FastMCP server exposing the computed graph/wiki/risk tools below. stdio or SSE transport ### MCP And API-Visible Computed Payloads Tool or endpoint concept Definition Example `get_answer` RAG answer with citations, confidence, fallback targets, retrieval metadata, and answer-cache support. `{answer: "...", confidence: "medium", citations: [...]}` `search_codebase` Wiki search using vector/FTS and federated workspace RRF when requested. `{results: [{title, relevance_score, confidence_score}]}` `get_context` Compact page, symbol, freshness, dependency, git, and cross-repo context for targets. With `include`, also folds in callers/callees, graph metrics (centrality percentiles, entry-point score), and community membership. `{targets: {"src/app.py": {docs, graph, freshness}}}` `get_overview` Repo or workspace overview, module map, entry points, git health, communities, and workspace footer. `{summary, modules, git_health, community_summary}` `get_why` Decision/governance lookup, file origin story, alignment, and decision health modes. `{decisions: [...], target_context: {...}}` `get_risk` Per-file risk, trend, risk type, owners, co-change partners, test gaps, security signals, top hotspots, optional PR blast radius. `{results: [{risk_summary, hotspot_score}], top_hotspots: [...]}` `get_dead_code` Tiered, grouped, and summarized dead-code findings. `{summary: {total_findings: 12}, tiers: {...}}` `get_dependency_path` Dependency-path or bridge context between files/symbols. `{path: ["src/a.py", "src/b.py"]}` `get_symbol` Exact symbol metadata and source slice. `{name: "create_app", signature: "def create_app(...)"}` `get_execution_flows` Entry-point traces through call edges. `{flows: [{entry_point, trace, crosses_community}]}` Blast radius API Direct risks, transitive affected files, co-change warnings, reviewers, test gaps, overall score. `{overall_risk_score: 7.25}` Knowledge map API Top owners, knowledge silos, onboarding targets. `{top_owners: [...], knowledge_silos: [...]}` Cost summary API Grouped costs and totals. `{groups: [...], total_cost_usd: 3.21}` Provider API Available provider/model configuration. `{providers: [...], active_provider: "gemini"}` ### Statuses And Enumerations Domain Values Page freshness `fresh`, `stale`, `expired`, `unknown` in type definitions Job status `pending`, `running`, `completed`, `failed`, `paused` Decision status `proposed`, `active`, `deprecated`, `superseded` Decision source `git_archaeology`, `inline_marker`, `readme_mining`, `cli` Dead-code kind `unreachable_file`, `unused_export`, `unused_internal`, `zombie_package` Dead-code status `open`, `acknowledged`, `resolved`, `false_positive` Security severity `high`, `med`, `low` Security kind `eval_call`, `exec_call`, `pickle_loads`, `subprocess_shell_true`, `os_system`, `hardcoded_password`, `hardcoded_secret`, `fstring_sql`, `concat_sql`, `tls_verify_false`, `weak_hash`, `security_sensitive_symbol` Edge type `imports`, `defines`, `calls`, `has_method`, `has_property`, `extends`, `implements`, `method_overrides`, `method_implements`, `co_changes`, `framework`, `dynamic`, plus dynamic subtypes such as `dynamic_uses`, `dynamic_imports`, `dynamic_url_route` Node type `file`, `symbol`, `external` Search type `vector`, `fulltext` Contract type `http`, `grpc`, `topic` Contract role `provider`, `consumer` Contract link match type `exact`, `manual` Risk trend `increasing`, `stable`, `decreasing`, `unknown` Risk type `bug-prone`, `churn-heavy`, `bus-factor-risk`, `high-coupling`, `stable`, `unknown` Change pattern `feature-active`, `primarily refactored`, `fix-heavy`, `dependency-churn`, `mixed-activity`, `uncategorized` Chat role `user`, `assistant` Coordinator health `ok`, `warning`, `critical` ### Example End-To-End Computation For a file `src/auth/session.py`, a typical Repowise index can compute: `FileInfo`: `language="python"`, `is_test=false`, `is_entry_point=false`. `ParsedFile`: symbols such as `src/auth/session.py::SessionStore`, imports such as `from .redis import client`, calls such as `client.get()`. Graph records: a file node, symbol nodes, `defines`, `imports`, `calls`, and maybe `framework` or `dynamic_*` edges. Graph metrics: `pagerank=0.013`, `betweenness=0.004`, `community_id=2`, `community_label="auth"`, `cohesion=0.18`. Git metadata: `commit_count_90d=11`, `primary_owner_name="Asha"`, `temporal_hotspot_score=2.1`, `churn_percentile=0.88`, `is_hotspot=true`. Analysis rows: maybe a security finding `hardcoded_secret`, or a decision record from `# DECISION: store sessions in Redis`. Generated docs: `file_page:src/auth/session.py`, source hash, token counts, summary, freshness, and vector/FTS entries. Risk output: `hotspot_score=0.88`, trend `increasing`, risk type `churn-heavy`, co-change partners, test-gap flag, and an impact surface.