How code-review-graph Generates Wiki Documentation From Community Structure
The code-review-graph project transforms its code-knowledge graph communities into browsable markdown pages by detecting clusters, generating per-community documentation, and emitting an index file.
The code-review-graph open-source tool analyzes codebases as knowledge graphs and automatically produces wiki documentation. This article explains how it converts abstract community structure into practical markdown documentation based on the implementation in code_review_graph/wiki.py.
Detecting Communities From the Graph
The wiki generation process begins by identifying cohesive code communities. The generate_wiki function calls get_communities(store) from code_review_graph/communities.py to obtain community data:
def generate_wiki(store: GraphStore, output_dir: Path, force: bool = False) -> Dict[str, int]:
communities = get_communities(store) # Returns list of community dicts
# ... each containing: name, size, members, cohesion, language, etc.
Each community dictionary contains metadata including name, size, members, cohesion score, and dominant programming language. These values drive the content of the resulting wiki pages.
Creating Safe Filenames With _slugify
Community names must become filesystem-safe paths. The _slugify function in code_review_graph/wiki.py handles this normalization:
- Normalizes Unicode to ASCII
- Drops non-ASCII characters entirely
- Replaces non-alphanumeric characters with hyphens
- Truncates to 80 characters maximum
- Falls back to
"unnamed"if the result is empty
def _slugify(name: str) -> str:
# Normalization and truncation logic (lines 24-30)
# Returns filesystem-safe string for markdown filenames
Building Per-Community Markdown Pages
The _generate_community_page function assembles comprehensive documentation for each community. This core generator creates structured markdown with multiple sections.
Page Structure
| Section | Content Source |
|---|---|
| Header | Community name as H1 |
| Overview | Size, cohesion, language, optional description |
| Members table | Up to 50 nodes via store.get_node |
| Execution Flows | Top 10 flows via get_flows and store.get_flow_qualified_names |
| Dependencies | Cross-community edges via store.get_outgoing_targets / store.get_incoming_sources |
The members table displays node name, kind (function, class, etc.), file path, and line range. Execution flows show how code travels through community members. Dependency counts reveal coupling between communities.
Writing Pages and Handling Collisions
The main generate_wiki loop manages file output with several safeguards:
- Unique slugs – Appends
"‑2","‑3", etc. when community names collide - Change detection – Skips writing if content matches existing file (unless
force=True) - Statistics tracking – Returns counts of generated, updated, and unchanged pages
stats = generate_wiki(store, Path("./wiki"), force=False)
# Returns: {'pages_generated': 12, 'pages_updated': 3, 'pages_unchanged': 5}
These mechanics ensure incremental updates rather than full regeneration, preserving modification timestamps and reducing I/O.
Generating the Index Page
After all community pages are emitted, generate_wiki constructs an index.md listing every community with:
- Community name (linked to its page)
- Member count
- Quick navigation to subsections
The index follows the same change-detection logic—only rewritten when content differs from the previous version.
Retrieving Pages Programmatically
The get_wiki_page function enables runtime access to generated documentation. It supports flexible lookup:
- Slugified name match (primary)
- Exact filename match with path-traversal protection
- Partial substring search within the wiki directory
from code_review_graph.wiki import get_wiki_page
# Find by natural name, exact file, or partial match
markdown = get_wiki_page("./wiki", "Data Processing")
This three-tier resolution makes the wiki navigable by both humans and automated tools.
Practical Usage Example
from pathlib import Path
from code_review_graph.graph import GraphStore
from code_review_graph.wiki import generate_wiki, get_wiki_page
# Load your analyzed codebase graph
store = GraphStore.load("/tmp/graph.db")
# Generate complete wiki documentation
stats = generate_wiki(store, Path("./wiki"))
print(f"Created {stats['pages_generated']} new pages, "
f"updated {stats['pages_updated']}, "
f"skipped {stats['pages_unchanged']} unchanged")
# Later: retrieve specific community documentation
content = get_wiki_page("./wiki", "Authentication Handlers")
Running this produces a directory structure like:
wiki/
├── index.md
├── authentication-handlers.md
├── data-processing.md
├── http-routing.md
└── ...
Key Implementation Files
| File | Responsibility |
|---|---|
code_review_graph/wiki.py |
Core generation: _slugify, _generate_community_page, generate_wiki, get_wiki_page |
code_review_graph/communities.py |
Cluster detection via get_communities |
code_review_graph/flows.py |
Execution flow analysis via get_flows |
code_review_graph/graph.py |
Storage layer with GraphStore, get_node, get_outgoing_targets, get_incoming_sources |
Summary
generate_wikiorchestrates the full pipeline: community detection → page generation → index creation_slugifyensures safe, portable filenames from arbitrary community names_generate_community_pageproduces rich markdown with members, flows, and dependencies- Incremental updates avoid unnecessary writes through content hashing
get_wiki_pageprovides flexible runtime access with security protections
Frequently Asked Questions
How does code-review-graph prevent filename collisions between communities?
When slugified names conflict, generate_wiki appends incrementing suffixes ("‑2", "‑3", etc.) to create unique paths within the generation run. This ensures no community page overwrites another regardless of naming similarities.
Can I force regeneration of unchanged wiki pages?
Yes. Pass force=True to generate_wiki. Without this flag, the function compares new content against existing files and skips writes when identical, tracking these as unchanged in the returned statistics.
What limits exist on the members table in community pages?
The _generate_community_page function caps the members table at 50 entries to prevent unwieldy documentation. All members remain queryable through the GraphStore directly; the wiki surfaces the most significant subset.
How does get_wiki_page protect against directory traversal attacks?
Before returning any file, get_wiki_page validates that the resolved path remains within the specified wiki directory. This prevents malicious inputs like "../../../etc/passwd" from escaping the intended documentation root.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →