Architecture

How repowise works, end to end.

A complete guide to how repowise works: ingestion, generation, persistence, graph algorithms, and MCP tools. For the product view of the C4 diagrams this pipeline produces, see the architecture feature; for what it costs to run, see pricing.

The Big Picture

repowise takes a codebase and produces living documentation: AI-generated documentation that stays current as the code changes. Each layer has a single responsibility and a clear boundary.

Single responsibility per layer

Ingestion, generation, and persistence are fully decoupled.

Swap the LLM provider without touching core

The LLM abstraction is isolated behind a provider interface.

Change the database without touching generation

Persistence is accessed through a repository pattern.

Replace the frontend without touching persistence

The API is the only contract between UI and data.

Ingestion Pipeline

The ingestion pipeline turns raw source code into structured data. Five components run in sequence.

FileTraverser

Walks the directory tree and applies three filter layers to find only documentable files.

ASTParser

Extracts functions, classes, imports, and exports from 28 languages using tree-sitter queries with unified capture names.

@symbol.def      : full definition node (provides line numbers)
@symbol.name     : the name identifier
@symbol.params   : parameter list
@symbol.modifiers : decorators, visibility keywords
@import.statement : full import node
@import.module   : the module path being imported

Adding a new language requires only one .scm query file and one entry in LANGUAGE_CONFIGS.

GitIndexer

Extracts ownership, churn, co-change relationships, and significant commits from git history using a single git log pass, O(1) processes instead of O(N).

CategoryMetricWhat it tells you
Timelinecommit_count_90d, age_daysHow active the file is
Ownershipprimary_owner, bus_factorWho knows this code, single points of failure
Churnchurn_percentile, is_hotspotHow volatile, risky to change
Co-changeco_change_pairsWhat files change together (invisible coupling)
Bus factor = minimum contributors needed to account for 80% of commits. Bus factor of 1 means a single point of failure: if that person leaves, institutional knowledge is lost.

ChangeDetector

After the initial indexing, ChangeDetector determines what to regenerate on each update run.

Generation Pipeline

The generation pipeline takes ingested data and produces documentation pages using LLMs.

Page Types & Levels

repowise generates 10 page types in 8 ordered levels. Later levels depend on earlier ones: a module page references the file pages inside it.

LevelPage TypeDescription
0api_contractAPI definitions (OpenAPI, Proto, GraphQL)
1symbol_spotlightIndividual important symbols
2file_pageIndividual code files (most common)
3scc_pageCircular dependency documentation
4module_pageDirectory-level summaries
5cross_packageInter-package boundaries (monorepos)
6repo_overviewRepo-wide summary
6architecture_diagramMermaid dependency diagram
7infra_pageDockerfiles, Makefiles, Terraform
7diff_summaryChange summaries

ContextAssembler

Each page type has a ContextAssembler method that builds everything the LLM needs to know. Context is rendered into Jinja2 templates and token-budgeted to fit the LLM window.

FilePageContext
├── file_path, language
├── symbols (public first, then private)
│   └── name, kind, signature, docstring, visibility
├── imports, exports
├── dependencies + dependents
├── file_source_snippet (trimmed to token budget)
├── pagerank_score, betweenness_score, community_id
├── git_metadata (ownership, churn, significant commits)
├── co_change_pages
├── dead_code_findings
├── depth: "minimal" | "standard" | "thorough"
└── rag_context (related pages from vector search)

Job System

The job system checkpoints every page, so a long run on a large repository resumes exactly where it stopped.

{
  "status": "running",
  "total_pages": 300,
  "completed_pages": 150,
  "completed_page_ids": ["file_page:src/auth.py", "..."],
  "current_level": 2
}

Persistence Layer

repowise writes to three independent stores: SQL, vector store, and graph, each tuned for its own query pattern.

The repowise doctor --repair command checks SQL↔Vector↔FTS consistency and auto-repairs orphaned entries: re-embedding missing vectors, re-indexing missing FTS entries.

Graph Algorithms

Every graph metric is computed from the import dependency graph: a directed graph where each node is a file and each edge is an import.

PageRank

Answers “How important is this file?” A file is important if many other important files depend on it.

score(B) = (1 - α) / N  +  α × Σ [ score(A) / out_degree(A) ]
                                        for each A that imports B

α = 0.85 (damping factor: probability of following an edge vs. teleporting)
  • Doc priority: highest PageRank files get documentation pages generated first
  • Generation depth: low PageRank + low churn → “minimal” docs (saves LLM tokens)
  • CLAUDE.md: files sorted by PageRank descending, most important appears first for AI assistants

Betweenness Centrality

Answers “Is this file a bridge between subsystems?” High betweenness files sit on shortest paths connecting many file pairs: they are the joints that hold subsystems together.

PageRank says “I'm important.” Betweenness says “I'm a bottleneck.” A bridge file with low PageRank still gets a Level 2 documentation page because it's a coupling point: changes to it ripple across subsystem boundaries.

Community Detection

Louvain algorithm on the undirected graph finds natural clusters: files that are more connected to each other than to the rest. These clusters become subsystem labels in the documentation and color groups in the dependency graph visualization.

Dead Code Detection

Files with in-degree = 0 (nothing imports them) are dead code candidates. repowise filters out entry points, test files, config files, and framework-loaded files before flagging, then scores confidence using git activity.

ConfidenceCondition
1.0No imports + no commits in 90d + file age > 180d
0.7No imports + no commits in 90d
0.4No imports but has recent commits (dynamic loading?)

MCP Tools

Ten MCP tools expose all of repowise's intelligence to AI coding assistants: Claude Code, Cursor, Cline, and any MCP-compatible editor.

get_answer(question)

One-call cited Q&A over the documentation, with a calibrated confidence score.

when to use: First call on any code question.

get_context(targets=[...])

A triage card for files, modules, or symbols: summary, signatures, hotspot bit, governing decisions.

when to use: Before reading or modifying specific code.

get_symbol(symbol_id)

Raw source bytes for one indexed symbol with exact, verified line bounds.

when to use: When you need the body of one function or class.

search_codebase(query="...")

Hybrid full-text and semantic search over the documentation, routed by query shape.

when to use: When you don't know where something lives.

get_why(query="...")

Architectural decision archaeology: why the code is shaped this way, with lineage.

when to use: Before architectural changes: understand existing intent.

get_risk(targets=[...])

Hotspot score, dependents, co-change partners, and PR-mode break/test directives.

when to use: Before modifying files: assess blast radius.

get_change_risk(revspec)

Pre-merge defect-risk score for a commit or diff range, computed from its shape alone.

when to use: Before merging: score a commit or diff range.

get_health(targets=[...])

Per-file code-health scores across three pillars, plus ranked refactoring targets.

when to use: Before refactoring: find the riskiest files first.

get_dead_code()

Unreachable files, unused exports, and zombie packages, tiered by confidence.

when to use: Before cleanup or refactoring.

get_overview()

Architecture map, module list, entry points, and tool recipes. First call on any repo.

when to use: First call when exploring an unfamiliar codebase.

Safeguards

Every layer checks its own output, so the docs, the graph and the three stores stay accurate as the code moves.

  • Graph-first architecture captures structural dependencies that keyword search misses.
  • Git history and co-change add a time dimension that static analysis alone cannot see.
  • A bounded cascade with PageRank-sorted budgets keeps the most important pages fresh.
  • Decision mining reads architectural intent from commits, comments and documentation.
  • MCP puts all of it inside the AI coding workflow, with no copy and paste.
  1. doctor --repairChecks the SQL, vector and full-text stores against each other and repairs any orphaned entry.
  2. Symbol cross-checkValidates generated pages against the symbols the parser actually found.
  3. Framework edgesAdds the edges pytest, Django, FastAPI and Flask create at runtime, so dynamic loading stays in the graph.
  4. Adaptive cascade budgetScales regeneration from 10 to 50 pages with the size of the change.
  5. Generation reportSummarises cost and quality after every update run.

Now run it on your own repo.

Index a repository free and every stage above runs on your code. Or explore a live repo first.