codebase-explorer 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. codebase_explorer-2.2.0/.gitignore +19 -0
  2. codebase_explorer-2.2.0/LICENSE +21 -0
  3. codebase_explorer-2.2.0/PKG-INFO +233 -0
  4. codebase_explorer-2.2.0/README.md +187 -0
  5. codebase_explorer-2.2.0/plugin/agents/cbe-writer.md +16 -0
  6. codebase_explorer-2.2.0/plugin/skills/codebase-explorer/SKILL.md +101 -0
  7. codebase_explorer-2.2.0/plugin/skills/codebase-explorer/references/claude-code.md +63 -0
  8. codebase_explorer-2.2.0/plugin/skills/codebase-explorer/references/codex.md +37 -0
  9. codebase_explorer-2.2.0/pyproject.toml +106 -0
  10. codebase_explorer-2.2.0/src/cbe/__init__.py +9 -0
  11. codebase_explorer-2.2.0/src/cbe/__main__.py +4 -0
  12. codebase_explorer-2.2.0/src/cbe/aggregation.py +183 -0
  13. codebase_explorer-2.2.0/src/cbe/api_completion.py +410 -0
  14. codebase_explorer-2.2.0/src/cbe/batching.py +283 -0
  15. codebase_explorer-2.2.0/src/cbe/catalog_query.py +376 -0
  16. codebase_explorer-2.2.0/src/cbe/checks.py +390 -0
  17. codebase_explorer-2.2.0/src/cbe/cli.py +434 -0
  18. codebase_explorer-2.2.0/src/cbe/concrete_facts.py +321 -0
  19. codebase_explorer-2.2.0/src/cbe/data/LICENSE.tiktoken +30 -0
  20. codebase_explorer-2.2.0/src/cbe/data/o200k_base.tiktoken +199998 -0
  21. codebase_explorer-2.2.0/src/cbe/declarations.py +537 -0
  22. codebase_explorer-2.2.0/src/cbe/docs.py +929 -0
  23. codebase_explorer-2.2.0/src/cbe/generate.py +316 -0
  24. codebase_explorer-2.2.0/src/cbe/grammars.py +741 -0
  25. codebase_explorer-2.2.0/src/cbe/graph.py +857 -0
  26. codebase_explorer-2.2.0/src/cbe/graph_backends/__init__.py +43 -0
  27. codebase_explorer-2.2.0/src/cbe/graph_backends/_calls.py +262 -0
  28. codebase_explorer-2.2.0/src/cbe/graph_backends/_paths.py +42 -0
  29. codebase_explorer-2.2.0/src/cbe/graph_backends/identity.py +93 -0
  30. codebase_explorer-2.2.0/src/cbe/graph_backends/imports.py +256 -0
  31. codebase_explorer-2.2.0/src/cbe/graph_backends/joern.py +1021 -0
  32. codebase_explorer-2.2.0/src/cbe/graph_backends/resolution.py +288 -0
  33. codebase_explorer-2.2.0/src/cbe/graph_backends/toolchain.py +396 -0
  34. codebase_explorer-2.2.0/src/cbe/grounding.py +57 -0
  35. codebase_explorer-2.2.0/src/cbe/host_run.py +1752 -0
  36. codebase_explorer-2.2.0/src/cbe/model_settings.py +80 -0
  37. codebase_explorer-2.2.0/src/cbe/projection.py +305 -0
  38. codebase_explorer-2.2.0/src/cbe/prompts.py +316 -0
  39. codebase_explorer-2.2.0/src/cbe/records.py +200 -0
  40. codebase_explorer-2.2.0/src/cbe/skeleton.py +474 -0
  41. codebase_explorer-2.2.0/src/cbe/source_context.py +709 -0
  42. codebase_explorer-2.2.0/src/cbe/symbols.py +136 -0
  43. codebase_explorer-2.2.0/src/cbe/token_budget.py +68 -0
  44. codebase_explorer-2.2.0/src/cbe/treename.py +398 -0
  45. codebase_explorer-2.2.0/src/cbe/usage.py +300 -0
  46. codebase_explorer-2.2.0/src/cbe_install/__init__.py +11 -0
  47. codebase_explorer-2.2.0/src/cbe_install/cli.py +434 -0
@@ -0,0 +1,19 @@
1
+ # Local-only / generated (added at in-repo migration; original tree had no .gitignore)
2
+ .venv/
3
+ __pycache__/
4
+ *.py[cod]
5
+ .pytest_cache/
6
+ .coverage
7
+ .cc_test_logs/
8
+ claude_mcp_list.txt
9
+ .claude/
10
+ .DS_Store
11
+ experiments/**/node_modules/
12
+ experiments/**/.work/
13
+ .codebase-analysis/
14
+
15
+ # evaluation scratch (clones, raw model answers)
16
+ .eval/
17
+ evaluation/tree/commits/
18
+ evaluation/tree/results/*.json
19
+ evaluation/tree/results/*.jsonl
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 zlxdengtianhei and Codebase Explorer contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.5
2
+ Name: codebase-explorer
3
+ Version: 2.2.0
4
+ Summary: Source-grounded, navigable documentation for software repositories
5
+ Project-URL: Homepage, https://github.com/zlxdengtianhei/codebase-explorer
6
+ Project-URL: Documentation, https://github.com/zlxdengtianhei/codebase-explorer/blob/main/docs/running.md
7
+ Project-URL: Online example, https://zlxdengtianhei.github.io/codebase-explorer/?data=flask
8
+ Project-URL: Changelog, https://github.com/zlxdengtianhei/codebase-explorer/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/zlxdengtianhei/codebase-explorer/issues
10
+ Author: zlxdengtianhei
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: agent-skills,call-graph,claude-code,code-documentation,code-understanding,developer-tools,tree-sitter
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Documentation
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: <3.14,>=3.12
25
+ Requires-Dist: networkx>=3.2
26
+ Requires-Dist: tiktoken<1,>=0.9
27
+ Requires-Dist: tree-sitter-c==0.24.2
28
+ Requires-Dist: tree-sitter-cpp==0.23.4
29
+ Requires-Dist: tree-sitter-go==0.25.0
30
+ Requires-Dist: tree-sitter-java==0.23.5
31
+ Requires-Dist: tree-sitter-javascript==0.25.0
32
+ Requires-Dist: tree-sitter-python==0.25.0
33
+ Requires-Dist: tree-sitter-typescript==0.23.2
34
+ Requires-Dist: tree-sitter==0.26.0
35
+ Provides-Extra: graphs
36
+ Requires-Dist: grimp==3.17; extra == 'graphs'
37
+ Provides-Extra: languages
38
+ Requires-Dist: tree-sitter-c-sharp==0.23.5; extra == 'languages'
39
+ Requires-Dist: tree-sitter-php==0.25.1; extra == 'languages'
40
+ Requires-Dist: tree-sitter-ruby==0.23.1; extra == 'languages'
41
+ Requires-Dist: tree-sitter-rust==0.24.2; extra == 'languages'
42
+ Provides-Extra: languages-community
43
+ Requires-Dist: tree-sitter-kotlin==1.1.0; extra == 'languages-community'
44
+ Requires-Dist: tree-sitter-swift==0.7.4; extra == 'languages-community'
45
+ Description-Content-Type: text/markdown
46
+
47
+ <h1 align="center"><img src="https://raw.githubusercontent.com/zlxdengtianhei/codebase-explorer/v2.2.0/docs/media/logo.svg" width="40" height="40" alt="" align="absmiddle">&nbsp;Codebase Explorer</h1>
48
+ <p align="center">Codebase Explorer turns a source repository into a one-page module map and per-module explanations that people and coding agents can read and query.</p>
49
+ <p align="center"><b>English</b> | <a href="https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/README.zh-CN.md">简体中文</a></p>
50
+ <p align="center">
51
+ <a href="https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
52
+ <a href="https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/pyproject.toml"><img alt="Python 3.12 and 3.13" src="https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg"></a>
53
+ <a href="https://github.com/zlxdengtianhei/codebase-explorer/actions/workflows/wheel-install.yml"><img alt="CI" src="https://github.com/zlxdengtianhei/codebase-explorer/actions/workflows/wheel-install.yml/badge.svg"></a>
54
+ </p>
55
+
56
+ https://github.com/user-attachments/assets/f0c3cc47-d0c2-4727-820e-65508c19408c
57
+
58
+ <p align="center">Two minutes, narrated: Flask from its source files to the module map, the eight top-level modules, one module page, then <code>cbe find</code> and <code>cbe source</code>.<br><a href="https://zlxdengtianhei.github.io/codebase-explorer/?data=flask">Try the interactive map</a> · <a href="https://zlxdengtianhei.github.io/codebase-explorer/film.html">The same video with its transcript (English and Chinese)</a></p>
59
+
60
+ A file tree shows where files are, not what each part is for. CBE (Codebase Explorer) reads a repository and writes what the tree lacks: one page that lists the whole module tree with a line on what each module is responsible for, and a page per module that explains each function and class and links to the exact source lines. You read it. A coding agent can look things up in it with three commands.
61
+
62
+ **To try it:** `uv tool install codebase-explorer` (Python 3.12 or 3.13). Then generate inside Claude Code on your own subscription, or from the command line with any OpenAI-compatible endpoint (you name the model with `--model`). The steps are in [Quickstart](#quickstart).
63
+
64
+ ## What you get
65
+
66
+ - **A one-page map.** `docs/INDEX.md` shows the whole module tree, one line per module. Its size is capped at the larger of 2,000 tokens and 3% of the source's token count.
67
+ - **A tree without gaps, the same every time.** A program builds it: units that call or import each other, sit close together and use similar words are grouped. The same input gives the same tree. There are no empty nodes and no duplicate modules.
68
+ - **A page per module.** Each unit has its signature, a source link, and an explanation written by a model. The explanations are written for people to read.
69
+ - **Facts from commands, not from the model.** Signatures, calls and source lines come from `cbe find`, `cbe query` and `cbe source`. `cbe source` prints from the frozen snapshot and checks each file's SHA-256 against the digest recorded at freeze time before printing anything.
70
+
71
+ The start of a real `docs/INDEX.md`, generated for flask (unedited):
72
+
73
+ ```markdown
74
+ ## Modules
75
+
76
+ - [**Request Serving Application Runtime**](nodes/request-serving-application-runtime.md) — Combines the concrete WSGI Flask application with request and response wrappers, templating, context lifecycle, and view-facing helpers needed to serve live requests. (136 units; `flask/app.py`, `helpers.py`, `wrappers.py`)
77
+ - [**Request Helper Utilities and Tests**](nodes/request-helper-utilities-and-tests.md) — Provides view-facing helpers for files, flashing, redirects, streaming, and URL building, plus proxy globals and signal definitions, with focused behavioral tests. (42 units; `helpers.py`, `test_helpers.py`, `flask/blueprints.py`)
78
+ - [**Helpers, globals, and signals**](nodes/helpers-globals-and-signals.md) — Provides view-facing helpers for sending files, flashing messages, redirecting, streaming, and URL building, plus proxy globals and Flask's blinker signal definitions. (26 units; `helpers.py`, `flask/blueprints.py`, `globals.py`)
79
+ - [**Helper behavior tests**](nodes/helper-behavior-tests.md) — Verifies aborter selection and dispatch, app redirect delegation, open_resource read modes and encoding, and context-free redirect fallback behavior. (11 units; `test_helpers.py`)
80
+ - [**File and URL tests**](nodes/file-and-url-tests.md) — Tests custom URL converters, send_file family behavior with path-like objects, stream_with_context lifetime, and url_for inside request contexts. (5 units; `test_helpers.py`, `test_converters.py`)
81
+ - [**WSGI Request Dispatch Core**](nodes/wsgi-request-dispatch-core.md) — Implements the WSGI-callable Flask class and its pipeline: request entry, URL-to-view matching, response finalization, error handler resolution, and test and async wiring. (35 units; `flask/app.py`, `test_async.py`, `sansio/app.py`)
82
+ ```
83
+
84
+ Full example: [flask](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/flask/docs/INDEX.md). More in [Examples and docs](#examples-and-docs).
85
+
86
+ ## Quickstart
87
+
88
+ CBE is on PyPI as `codebase-explorer`. It needs Python 3.12 or 3.13. There are two ways to run it. Both end in the same `docs/` folder. The usual one is A: your coding agent loads the skill and does the work on your own subscription. B is for scripts and batch runs.
89
+
90
+ **A. The usual way: inside your coding agent, on your own subscription.** The steps below use Claude Code; the skill makes its subagents write the explanations.
91
+
92
+ 1. Install CBE: `uv tool install codebase-explorer` (or `pipx install codebase-explorer`).
93
+ 2. Optional, for the call graph: `cbe graph setup` downloads Joern and a Java runtime into your user cache directory (about 1.9 GB; Linux x86_64 and macOS).
94
+ 3. In your project, install the skill: `cbe-install install --host claude-code`.
95
+ 4. Start Claude Code there and ask: "Use the codebase-explorer skill to generate documentation for this repository."
96
+ 5. The agent prints the planned file, token, module and task counts, runs the subagents, and verifies the result.
97
+ 6. Open `<run_dir>/docs/INDEX.md`. The agent reports `run_dir`.
98
+
99
+ Other agents load the same skill: `cbe-install install --host` takes `claude-code`, `opencode`, `pi`, `codex` and `dsh`. What has run end to end: Claude Code (see [What it costs](#what-it-costs)); OpenCode and Pi, once each on a 22-file sample repository (in the Pi run the tasks were handed to separate Pi sessions by a dispatch skill on our machine; Pi has no subagents of its own). `codex` and `dsh` install the skill, and we have not run them end to end. Details: [docs/running.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/running.md#generate-through-a-host-agent).
100
+
101
+ **B. For scripts and batch runs: from the command line, with any OpenAI-compatible endpoint.** There is no default model: you must pass `--model`.
102
+
103
+ 1. Install CBE as in step 1 above.
104
+ 2. Put the key in an environment variable: `export CBE_API_KEY=...`
105
+ 3. Optional: build the call graph (`cbe graph setup`, then `cbe graph build /abs/repo --output /abs/graph.json`).
106
+ 4. Generate. Paths must be absolute:
107
+
108
+ ```sh
109
+ cbe generate /abs/repo --model MODEL --base-url https://your-endpoint.example/v1 \
110
+ --api-key-env CBE_API_KEY --graph /abs/graph.json --run-dir /abs/run
111
+ ```
112
+
113
+ 5. Open `/abs/run/docs/INDEX.md`. Drop `--graph` to run without a call graph.
114
+
115
+ Then look things up. `RUN` is the absolute run directory, and the ID is the second column of the `find` output:
116
+
117
+ ```sh
118
+ cbe find --run-dir "$RUN" --term url_for
119
+ cbe query --run-dir "$RUN" --id 'src/flask/helpers.py::function::url_for::6511'
120
+ cbe source --run-dir "$RUN" --id 'src/flask/helpers.py::function::url_for::6511' --context 2
121
+ ```
122
+
123
+ Every other command and option is in [docs/reference.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/reference.md).
124
+
125
+ ## How it works
126
+
127
+ ```mermaid
128
+ flowchart LR
129
+ A["Freeze the source"] --> B["Tree-sitter splits it at syntax boundaries"]
130
+ B --> C["Joern builds call and import graph (optional)"]
131
+ C --> D["Model explains each code unit"]
132
+ D --> E["Program groups units into a module tree"]
133
+ E --> F["Model names each module"]
134
+ F --> G["Render INDEX.md, module pages, catalog.json"]
135
+ classDef program fill:#dff7f3,stroke:#0f9b8e,color:#0f1b2d
136
+ classDef model fill:#fff0cc,stroke:#c98a00,color:#0f1b2d
137
+ class A,B,C,E,G program
138
+ class D,F model
139
+ ```
140
+
141
+ Teal steps are ordinary code and make no model call. Amber steps are model calls.
142
+
143
+ - **Freeze.** CBE keeps a hashed copy of the source, so every line number and quote can be checked later.
144
+ - **Split.** Tree-sitter cuts each file at syntax boundaries. Every byte lands in some chunk.
145
+ - **Explain.** The model writes the explanations batch by batch. It names symbols by the short numbers in a list, so it cannot invent an ID. The program asks again only for the symbols the model skipped.
146
+ - **Check.** A second model reads one batch's source and checks its explanations against it: wrong behaviour, a wrong condition or error, or an explanation of the wrong symbol. It does not judge style. Findings are sent back for one rewrite. `--review` chooses how many batches are read: `none`; `sample` (the default: the largest batch, and every batch if that one has any finding); or `all`. On flask a sampled review was 14% of the run's input tokens; reading every batch adds about 80%. Where batches have many errors the rewrites cost more than the reading: on six examples whose sample had findings, reviewing every batch and rewriting the flagged ones added 51–176% to the run's input tokens and made its output tokens 4 to 10 times as large, because a flagged batch is written again in full. A clean sample leaves the other batches unread, so use `--review all` for a repository that matters. `RUN.md` says which batches were read and what was found. A rewrite after review, like any new run, can regroup the map: module pages and their names may change. Symbol IDs (`cbe find`, `cbe query`) depend only on the source, so link to code by ID, not by page name.
147
+ - **Group.** The program, not the model, builds the module tree from calls and imports, location, and wording. The same input gives the same tree.
148
+ - **Name.** The model gives each module a name, one line on what it is responsible for, and two or three sentences on how to read it. It cannot add, drop or move a node.
149
+ - **Render.** The program writes `docs/INDEX.md`, one page per module, `DEPENDENCIES.md` and `RUN.md`, and the `catalog.json` that `find`, `query` and `source` read.
150
+
151
+ ## Code graph
152
+
153
+ Without a graph, CBE still works. With one, the explanation tasks and the dependency view also get static import, call and control-flow evidence. The graph comes from [Joern](https://joern.io/), which needs Java 21 or newer. `cbe graph setup` downloads the pinned Joern and, if no suitable Java is found, a Java runtime into your user cache directory (about 1.9 GB in total). `cbe graph setup --check` downloads nothing and reports what is installed. `cbe graph build` then writes the graph file that `--graph` takes. It does not export dataflow unless you pass `--with-dataflow`, because a generation run does not read it and it was over half of the graph file on flask (23 of 41 MB). To install Joern by hand, see [docs/reference.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/reference.md#optional-graph-analyzers).
154
+
155
+ | Status | Languages | Conditions |
156
+ |---|---|---|
157
+ | Works on real repositories | C, C++, Python, JavaScript, TypeScript, Java, Go, Ruby | Python imports use Grimp (the `graphs` extra); JavaScript and TypeScript imports use dependency-cruiser (Node.js). Go calls across packages can stay unresolved. Ruby's dynamic dispatch can bind a call to a method of the same name on another class: CBE marks such calls ambiguous, and some wrong bindings remain. |
158
+ | Needs an extra tool | Rust, PHP | Rust needs `cargo` and a Cargo project layout. PHP needs `php` (7 or later). |
159
+ | Builds, calls partly resolved | C# | On a 55-file repository the graph builds (declarations, control flow, imports). Of its 2,322 calls, 689 resolve to one repository method and 394 to a set of overloads (Joern's C# frontend does not type arguments well enough to pick the overload); 246 point outside the repository and 993 stay unresolved. |
160
+ | Fails on real repositories | Kotlin | Joern 4.0.654 failed on a 146-file Kotlin repository. Two-file examples work, so small inputs may succeed. |
161
+ | Not tested | Swift, TSX | |
162
+
163
+ `cbe languages` prints the same status for each language as `call_graph`. Source parsing and chunking work for every language in the table whatever the call-graph status is. Tree-sitter grammars for 13 languages come with the default install and two extras. More on analyzers and graph options: [docs/reference.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/reference.md#optional-graph-analyzers).
164
+
165
+ ## What it costs
166
+
167
+ Measured on flask, tests included: 65 files, 125k tokens. Model: GLM-5.3-Flash, called through `cbe generate`. One run to completion.
168
+
169
+ | Measure | Reading |
170
+ |---|---|
171
+ | Prompt tokens | 3.2–3.4 times the source tokens |
172
+ | Output tokens | about 0.9 times the source tokens |
173
+ | Explanation text the model wrote | about 30% of the source tokens |
174
+ | Prompt tokens spent on re-asks after a rejected answer | about 22% (43% before the answer-format change; that earlier run also stopped midway on upstream rate limiting) |
175
+
176
+ These readings come from calls through an OpenAI-compatible gateway to GLM-5.3-Flash. CBE ships default settings (for example `reasoning_effort: low`) only for model names it knows. For any other model name, pass the settings you need with `--config`; [docs/running.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/running.md#api-configuration-keys) lists every key.
177
+
178
+ The host-agent path, measured once on flask's `src/` (24 files, about 75k tokens) with headless Claude Code (`claude -p`) and Sonnet subagents:
179
+
180
+ | Measure | Reading |
181
+ |---|---|
182
+ | Subagent tasks | 8: 4 explanation batches, 1 sampled review, 2 tree-naming tasks, 1 overview. All were accepted on the first answer |
183
+ | Wall clock | 293 seconds |
184
+ | `cbe host verify` | all 15 checks passed |
185
+ | Tokens | not collected for this run |
186
+
187
+ Each table is one repository and one run. A host-agent run uses your subscription instead of an API key. Building the graph makes no model call. An older cost table for repositories up to 1.7 million tokens is in [docs/running.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/running.md#what-a-run-costs-the-earlier-table); it was measured before the answer-format change, so do not compare it with the table above.
188
+
189
+ ## How well does it work
190
+
191
+ What we measured, and what it shows. Everything here has conditions; the files in [`evaluation/tree/results/`](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/evaluation/tree/results/) hold the tables.
192
+
193
+ The page you read first got smaller. Size of that page in `o200k_base` tokens, on three full runs (the earlier version's tree is in the "before" column):
194
+
195
+ | Repository | Before | Now | Empty tree nodes before / now |
196
+ |---|---:|---:|---:|
197
+ | flask | 16,076 | 3,078 | 22 / 0 |
198
+ | ruby_llm | 15,938 | 2,074 | 8 / 0 |
199
+ | gson | 12,643 | 2,514 | 16 / 0 |
200
+
201
+ - **Tree structure.** The new trees have no empty nodes and no duplicate modules on the three repositories above. The earlier trees had 22, 8 and 16 empty nodes.
202
+ - **Call labels.** In seven repositories we took 10 edges of each status and checked them back against the source. For example, all 307 "unresolved" calls in cJSON were macros; they are no longer counted as calls. In fmt, "external" calls fell from 2,748 to 22.
203
+ - **Does the tree help find the code to read?** We took 30 real commits from each of five repositories and asked three models which three modules to look at for the change. The new tree and the earlier tree could not be told apart. Against a plain directory listing, the module tree made no clear difference in repositories whose directories already have levels. It narrowed the reading only where directories are flat (flask, fmt): the three chosen modules held about 40% of the source and about 0.75–0.8 of the changed lines.
204
+ - **How far to trust that ruler.** It is noisy: asked the same question again, the model gave an identical answer in only 9 to 23 of 30 cases.
205
+ - **Earlier question-answering rounds** (CBE before the program-built tree). On flask and pytest (48 questions each), an agent with CBE documents and commands scored no differently from a source-only agent, and rarely ran the commands. One exploratory reading on curl scored higher with CBE (+5.60 rubric points, interval [+0.90, +10.82]) and comes with caveats listed in [evaluation/README.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/evaluation/README.md).
206
+
207
+ What we do not claim: that grouping by function lets an agent locate code more accurately than a directory tree does, or that CBE improves an agent's answers. The measurements above do not show either.
208
+
209
+ ## Known limitations
210
+
211
+ - The call graph needs Joern and Java 21 or newer. `cbe graph setup` downloads both (about 1.9 GB).
212
+ - C# calls to overloaded methods resolve only to the set of overloads, and about 43% of the calls in the one real repository measured stay unresolved. Kotlin graphs fail on real repositories under the pinned Joern version; two-file examples work.
213
+ - Ruby's dynamic dispatch can bind a call to the wrong class's method. CBE marks many of these as ambiguous, and some wrong bindings remain.
214
+ - C and C++ files are not preprocessed. A header with many macros is cut into coarse chunks, and a macro can be taken for a function name.
215
+ - A model writes the explanations. `cbe host verify` passing shows that the structure and references are consistent. It does not show that an explanation is correct. Check explanations against the source (`cbe source`).
216
+ - There are no incremental updates: when the source changes, generate again.
217
+
218
+ ## Examples and docs
219
+
220
+ - Generated documents: [flask](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/flask/docs/INDEX.md), [cJSON](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/cjson/), [fmt](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/fmt/), [gson](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/gson/), [ruby_llm](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/ruby_llm/), [tsdown](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/tsdown/), [polyglot](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/examples/polyglot/). Each example's README names the CBE commit that generated it; most were generated by an earlier version.
221
+ - [docs/reference.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/reference.md): install options, languages, graph analyzers, `find`, `query`, `source`, named declaration coverage.
222
+ - [docs/running.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/running.md): host-agent and API runs, the run directory, resume and verify, cost details, troubleshooting.
223
+ - [docs/videos.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/docs/videos.md): walkthrough videos.
224
+ - [evaluation/README.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/evaluation/README.md) and [CHANGELOG.md](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/CHANGELOG.md).
225
+
226
+ ## Development and license
227
+
228
+ ```sh
229
+ uv sync --python 3.13 --group dev
230
+ uv run pytest -q
231
+ ```
232
+
233
+ Tests that need a real analyzer need that analyzer configured. The product license is [MIT](https://github.com/zlxdengtianhei/codebase-explorer/blob/v2.2.0/LICENSE); external analyzers and grammar packages keep their own licenses.
@@ -0,0 +1,187 @@
1
+ <h1 align="center"><img src="docs/media/logo.svg" width="40" height="40" alt="" align="absmiddle">&nbsp;Codebase Explorer</h1>
2
+ <p align="center">Codebase Explorer turns a source repository into a one-page module map and per-module explanations that people and coding agents can read and query.</p>
3
+ <p align="center"><b>English</b> | <a href="README.zh-CN.md">简体中文</a></p>
4
+ <p align="center">
5
+ <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
6
+ <a href="pyproject.toml"><img alt="Python 3.12 and 3.13" src="https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg"></a>
7
+ <a href="https://github.com/zlxdengtianhei/codebase-explorer/actions/workflows/wheel-install.yml"><img alt="CI" src="https://github.com/zlxdengtianhei/codebase-explorer/actions/workflows/wheel-install.yml/badge.svg"></a>
8
+ </p>
9
+
10
+ https://github.com/user-attachments/assets/f0c3cc47-d0c2-4727-820e-65508c19408c
11
+
12
+ <p align="center">Two minutes, narrated: Flask from its source files to the module map, the eight top-level modules, one module page, then <code>cbe find</code> and <code>cbe source</code>.<br><a href="https://zlxdengtianhei.github.io/codebase-explorer/?data=flask">Try the interactive map</a> · <a href="https://zlxdengtianhei.github.io/codebase-explorer/film.html">The same video with its transcript (English and Chinese)</a></p>
13
+
14
+ A file tree shows where files are, not what each part is for. CBE (Codebase Explorer) reads a repository and writes what the tree lacks: one page that lists the whole module tree with a line on what each module is responsible for, and a page per module that explains each function and class and links to the exact source lines. You read it. A coding agent can look things up in it with three commands.
15
+
16
+ **To try it:** `uv tool install codebase-explorer` (Python 3.12 or 3.13). Then generate inside Claude Code on your own subscription, or from the command line with any OpenAI-compatible endpoint (you name the model with `--model`). The steps are in [Quickstart](#quickstart).
17
+
18
+ ## What you get
19
+
20
+ - **A one-page map.** `docs/INDEX.md` shows the whole module tree, one line per module. Its size is capped at the larger of 2,000 tokens and 3% of the source's token count.
21
+ - **A tree without gaps, the same every time.** A program builds it: units that call or import each other, sit close together and use similar words are grouped. The same input gives the same tree. There are no empty nodes and no duplicate modules.
22
+ - **A page per module.** Each unit has its signature, a source link, and an explanation written by a model. The explanations are written for people to read.
23
+ - **Facts from commands, not from the model.** Signatures, calls and source lines come from `cbe find`, `cbe query` and `cbe source`. `cbe source` prints from the frozen snapshot and checks each file's SHA-256 against the digest recorded at freeze time before printing anything.
24
+
25
+ The start of a real `docs/INDEX.md`, generated for flask (unedited):
26
+
27
+ ```markdown
28
+ ## Modules
29
+
30
+ - [**Request Serving Application Runtime**](nodes/request-serving-application-runtime.md) — Combines the concrete WSGI Flask application with request and response wrappers, templating, context lifecycle, and view-facing helpers needed to serve live requests. (136 units; `flask/app.py`, `helpers.py`, `wrappers.py`)
31
+ - [**Request Helper Utilities and Tests**](nodes/request-helper-utilities-and-tests.md) — Provides view-facing helpers for files, flashing, redirects, streaming, and URL building, plus proxy globals and signal definitions, with focused behavioral tests. (42 units; `helpers.py`, `test_helpers.py`, `flask/blueprints.py`)
32
+ - [**Helpers, globals, and signals**](nodes/helpers-globals-and-signals.md) — Provides view-facing helpers for sending files, flashing messages, redirecting, streaming, and URL building, plus proxy globals and Flask's blinker signal definitions. (26 units; `helpers.py`, `flask/blueprints.py`, `globals.py`)
33
+ - [**Helper behavior tests**](nodes/helper-behavior-tests.md) — Verifies aborter selection and dispatch, app redirect delegation, open_resource read modes and encoding, and context-free redirect fallback behavior. (11 units; `test_helpers.py`)
34
+ - [**File and URL tests**](nodes/file-and-url-tests.md) — Tests custom URL converters, send_file family behavior with path-like objects, stream_with_context lifetime, and url_for inside request contexts. (5 units; `test_helpers.py`, `test_converters.py`)
35
+ - [**WSGI Request Dispatch Core**](nodes/wsgi-request-dispatch-core.md) — Implements the WSGI-callable Flask class and its pipeline: request entry, URL-to-view matching, response finalization, error handler resolution, and test and async wiring. (35 units; `flask/app.py`, `test_async.py`, `sansio/app.py`)
36
+ ```
37
+
38
+ Full example: [flask](examples/flask/docs/INDEX.md). More in [Examples and docs](#examples-and-docs).
39
+
40
+ ## Quickstart
41
+
42
+ CBE is on PyPI as `codebase-explorer`. It needs Python 3.12 or 3.13. There are two ways to run it. Both end in the same `docs/` folder. The usual one is A: your coding agent loads the skill and does the work on your own subscription. B is for scripts and batch runs.
43
+
44
+ **A. The usual way: inside your coding agent, on your own subscription.** The steps below use Claude Code; the skill makes its subagents write the explanations.
45
+
46
+ 1. Install CBE: `uv tool install codebase-explorer` (or `pipx install codebase-explorer`).
47
+ 2. Optional, for the call graph: `cbe graph setup` downloads Joern and a Java runtime into your user cache directory (about 1.9 GB; Linux x86_64 and macOS).
48
+ 3. In your project, install the skill: `cbe-install install --host claude-code`.
49
+ 4. Start Claude Code there and ask: "Use the codebase-explorer skill to generate documentation for this repository."
50
+ 5. The agent prints the planned file, token, module and task counts, runs the subagents, and verifies the result.
51
+ 6. Open `<run_dir>/docs/INDEX.md`. The agent reports `run_dir`.
52
+
53
+ Other agents load the same skill: `cbe-install install --host` takes `claude-code`, `opencode`, `pi`, `codex` and `dsh`. What has run end to end: Claude Code (see [What it costs](#what-it-costs)); OpenCode and Pi, once each on a 22-file sample repository (in the Pi run the tasks were handed to separate Pi sessions by a dispatch skill on our machine; Pi has no subagents of its own). `codex` and `dsh` install the skill, and we have not run them end to end. Details: [docs/running.md](docs/running.md#generate-through-a-host-agent).
54
+
55
+ **B. For scripts and batch runs: from the command line, with any OpenAI-compatible endpoint.** There is no default model: you must pass `--model`.
56
+
57
+ 1. Install CBE as in step 1 above.
58
+ 2. Put the key in an environment variable: `export CBE_API_KEY=...`
59
+ 3. Optional: build the call graph (`cbe graph setup`, then `cbe graph build /abs/repo --output /abs/graph.json`).
60
+ 4. Generate. Paths must be absolute:
61
+
62
+ ```sh
63
+ cbe generate /abs/repo --model MODEL --base-url https://your-endpoint.example/v1 \
64
+ --api-key-env CBE_API_KEY --graph /abs/graph.json --run-dir /abs/run
65
+ ```
66
+
67
+ 5. Open `/abs/run/docs/INDEX.md`. Drop `--graph` to run without a call graph.
68
+
69
+ Then look things up. `RUN` is the absolute run directory, and the ID is the second column of the `find` output:
70
+
71
+ ```sh
72
+ cbe find --run-dir "$RUN" --term url_for
73
+ cbe query --run-dir "$RUN" --id 'src/flask/helpers.py::function::url_for::6511'
74
+ cbe source --run-dir "$RUN" --id 'src/flask/helpers.py::function::url_for::6511' --context 2
75
+ ```
76
+
77
+ Every other command and option is in [docs/reference.md](docs/reference.md).
78
+
79
+ ## How it works
80
+
81
+ ```mermaid
82
+ flowchart LR
83
+ A["Freeze the source"] --> B["Tree-sitter splits it at syntax boundaries"]
84
+ B --> C["Joern builds call and import graph (optional)"]
85
+ C --> D["Model explains each code unit"]
86
+ D --> E["Program groups units into a module tree"]
87
+ E --> F["Model names each module"]
88
+ F --> G["Render INDEX.md, module pages, catalog.json"]
89
+ classDef program fill:#dff7f3,stroke:#0f9b8e,color:#0f1b2d
90
+ classDef model fill:#fff0cc,stroke:#c98a00,color:#0f1b2d
91
+ class A,B,C,E,G program
92
+ class D,F model
93
+ ```
94
+
95
+ Teal steps are ordinary code and make no model call. Amber steps are model calls.
96
+
97
+ - **Freeze.** CBE keeps a hashed copy of the source, so every line number and quote can be checked later.
98
+ - **Split.** Tree-sitter cuts each file at syntax boundaries. Every byte lands in some chunk.
99
+ - **Explain.** The model writes the explanations batch by batch. It names symbols by the short numbers in a list, so it cannot invent an ID. The program asks again only for the symbols the model skipped.
100
+ - **Check.** A second model reads one batch's source and checks its explanations against it: wrong behaviour, a wrong condition or error, or an explanation of the wrong symbol. It does not judge style. Findings are sent back for one rewrite. `--review` chooses how many batches are read: `none`; `sample` (the default: the largest batch, and every batch if that one has any finding); or `all`. On flask a sampled review was 14% of the run's input tokens; reading every batch adds about 80%. Where batches have many errors the rewrites cost more than the reading: on six examples whose sample had findings, reviewing every batch and rewriting the flagged ones added 51–176% to the run's input tokens and made its output tokens 4 to 10 times as large, because a flagged batch is written again in full. A clean sample leaves the other batches unread, so use `--review all` for a repository that matters. `RUN.md` says which batches were read and what was found. A rewrite after review, like any new run, can regroup the map: module pages and their names may change. Symbol IDs (`cbe find`, `cbe query`) depend only on the source, so link to code by ID, not by page name.
101
+ - **Group.** The program, not the model, builds the module tree from calls and imports, location, and wording. The same input gives the same tree.
102
+ - **Name.** The model gives each module a name, one line on what it is responsible for, and two or three sentences on how to read it. It cannot add, drop or move a node.
103
+ - **Render.** The program writes `docs/INDEX.md`, one page per module, `DEPENDENCIES.md` and `RUN.md`, and the `catalog.json` that `find`, `query` and `source` read.
104
+
105
+ ## Code graph
106
+
107
+ Without a graph, CBE still works. With one, the explanation tasks and the dependency view also get static import, call and control-flow evidence. The graph comes from [Joern](https://joern.io/), which needs Java 21 or newer. `cbe graph setup` downloads the pinned Joern and, if no suitable Java is found, a Java runtime into your user cache directory (about 1.9 GB in total). `cbe graph setup --check` downloads nothing and reports what is installed. `cbe graph build` then writes the graph file that `--graph` takes. It does not export dataflow unless you pass `--with-dataflow`, because a generation run does not read it and it was over half of the graph file on flask (23 of 41 MB). To install Joern by hand, see [docs/reference.md](docs/reference.md#optional-graph-analyzers).
108
+
109
+ | Status | Languages | Conditions |
110
+ |---|---|---|
111
+ | Works on real repositories | C, C++, Python, JavaScript, TypeScript, Java, Go, Ruby | Python imports use Grimp (the `graphs` extra); JavaScript and TypeScript imports use dependency-cruiser (Node.js). Go calls across packages can stay unresolved. Ruby's dynamic dispatch can bind a call to a method of the same name on another class: CBE marks such calls ambiguous, and some wrong bindings remain. |
112
+ | Needs an extra tool | Rust, PHP | Rust needs `cargo` and a Cargo project layout. PHP needs `php` (7 or later). |
113
+ | Builds, calls partly resolved | C# | On a 55-file repository the graph builds (declarations, control flow, imports). Of its 2,322 calls, 689 resolve to one repository method and 394 to a set of overloads (Joern's C# frontend does not type arguments well enough to pick the overload); 246 point outside the repository and 993 stay unresolved. |
114
+ | Fails on real repositories | Kotlin | Joern 4.0.654 failed on a 146-file Kotlin repository. Two-file examples work, so small inputs may succeed. |
115
+ | Not tested | Swift, TSX | |
116
+
117
+ `cbe languages` prints the same status for each language as `call_graph`. Source parsing and chunking work for every language in the table whatever the call-graph status is. Tree-sitter grammars for 13 languages come with the default install and two extras. More on analyzers and graph options: [docs/reference.md](docs/reference.md#optional-graph-analyzers).
118
+
119
+ ## What it costs
120
+
121
+ Measured on flask, tests included: 65 files, 125k tokens. Model: GLM-5.3-Flash, called through `cbe generate`. One run to completion.
122
+
123
+ | Measure | Reading |
124
+ |---|---|
125
+ | Prompt tokens | 3.2–3.4 times the source tokens |
126
+ | Output tokens | about 0.9 times the source tokens |
127
+ | Explanation text the model wrote | about 30% of the source tokens |
128
+ | Prompt tokens spent on re-asks after a rejected answer | about 22% (43% before the answer-format change; that earlier run also stopped midway on upstream rate limiting) |
129
+
130
+ These readings come from calls through an OpenAI-compatible gateway to GLM-5.3-Flash. CBE ships default settings (for example `reasoning_effort: low`) only for model names it knows. For any other model name, pass the settings you need with `--config`; [docs/running.md](docs/running.md#api-configuration-keys) lists every key.
131
+
132
+ The host-agent path, measured once on flask's `src/` (24 files, about 75k tokens) with headless Claude Code (`claude -p`) and Sonnet subagents:
133
+
134
+ | Measure | Reading |
135
+ |---|---|
136
+ | Subagent tasks | 8: 4 explanation batches, 1 sampled review, 2 tree-naming tasks, 1 overview. All were accepted on the first answer |
137
+ | Wall clock | 293 seconds |
138
+ | `cbe host verify` | all 15 checks passed |
139
+ | Tokens | not collected for this run |
140
+
141
+ Each table is one repository and one run. A host-agent run uses your subscription instead of an API key. Building the graph makes no model call. An older cost table for repositories up to 1.7 million tokens is in [docs/running.md](docs/running.md#what-a-run-costs-the-earlier-table); it was measured before the answer-format change, so do not compare it with the table above.
142
+
143
+ ## How well does it work
144
+
145
+ What we measured, and what it shows. Everything here has conditions; the files in [`evaluation/tree/results/`](evaluation/tree/results/) hold the tables.
146
+
147
+ The page you read first got smaller. Size of that page in `o200k_base` tokens, on three full runs (the earlier version's tree is in the "before" column):
148
+
149
+ | Repository | Before | Now | Empty tree nodes before / now |
150
+ |---|---:|---:|---:|
151
+ | flask | 16,076 | 3,078 | 22 / 0 |
152
+ | ruby_llm | 15,938 | 2,074 | 8 / 0 |
153
+ | gson | 12,643 | 2,514 | 16 / 0 |
154
+
155
+ - **Tree structure.** The new trees have no empty nodes and no duplicate modules on the three repositories above. The earlier trees had 22, 8 and 16 empty nodes.
156
+ - **Call labels.** In seven repositories we took 10 edges of each status and checked them back against the source. For example, all 307 "unresolved" calls in cJSON were macros; they are no longer counted as calls. In fmt, "external" calls fell from 2,748 to 22.
157
+ - **Does the tree help find the code to read?** We took 30 real commits from each of five repositories and asked three models which three modules to look at for the change. The new tree and the earlier tree could not be told apart. Against a plain directory listing, the module tree made no clear difference in repositories whose directories already have levels. It narrowed the reading only where directories are flat (flask, fmt): the three chosen modules held about 40% of the source and about 0.75–0.8 of the changed lines.
158
+ - **How far to trust that ruler.** It is noisy: asked the same question again, the model gave an identical answer in only 9 to 23 of 30 cases.
159
+ - **Earlier question-answering rounds** (CBE before the program-built tree). On flask and pytest (48 questions each), an agent with CBE documents and commands scored no differently from a source-only agent, and rarely ran the commands. One exploratory reading on curl scored higher with CBE (+5.60 rubric points, interval [+0.90, +10.82]) and comes with caveats listed in [evaluation/README.md](evaluation/README.md).
160
+
161
+ What we do not claim: that grouping by function lets an agent locate code more accurately than a directory tree does, or that CBE improves an agent's answers. The measurements above do not show either.
162
+
163
+ ## Known limitations
164
+
165
+ - The call graph needs Joern and Java 21 or newer. `cbe graph setup` downloads both (about 1.9 GB).
166
+ - C# calls to overloaded methods resolve only to the set of overloads, and about 43% of the calls in the one real repository measured stay unresolved. Kotlin graphs fail on real repositories under the pinned Joern version; two-file examples work.
167
+ - Ruby's dynamic dispatch can bind a call to the wrong class's method. CBE marks many of these as ambiguous, and some wrong bindings remain.
168
+ - C and C++ files are not preprocessed. A header with many macros is cut into coarse chunks, and a macro can be taken for a function name.
169
+ - A model writes the explanations. `cbe host verify` passing shows that the structure and references are consistent. It does not show that an explanation is correct. Check explanations against the source (`cbe source`).
170
+ - There are no incremental updates: when the source changes, generate again.
171
+
172
+ ## Examples and docs
173
+
174
+ - Generated documents: [flask](examples/flask/docs/INDEX.md), [cJSON](examples/cjson/), [fmt](examples/fmt/), [gson](examples/gson/), [ruby_llm](examples/ruby_llm/), [tsdown](examples/tsdown/), [polyglot](examples/polyglot/). Each example's README names the CBE commit that generated it; most were generated by an earlier version.
175
+ - [docs/reference.md](docs/reference.md): install options, languages, graph analyzers, `find`, `query`, `source`, named declaration coverage.
176
+ - [docs/running.md](docs/running.md): host-agent and API runs, the run directory, resume and verify, cost details, troubleshooting.
177
+ - [docs/videos.md](docs/videos.md): walkthrough videos.
178
+ - [evaluation/README.md](evaluation/README.md) and [CHANGELOG.md](CHANGELOG.md).
179
+
180
+ ## Development and license
181
+
182
+ ```sh
183
+ uv sync --python 3.13 --group dev
184
+ uv run pytest -q
185
+ ```
186
+
187
+ Tests that need a real analyzer need that analyzer configured. The product license is [MIT](LICENSE); external analyzers and grammar packages keep their own licenses.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: cbe-writer
3
+ description: Completes exactly one Codebase Explorer task from a CBE instruction file and writes the JSON result file. Use only for tasks handed out by `cbe host next`.
4
+ tools: Read, Write
5
+ ---
6
+
7
+ You complete one Codebase Explorer task. The message names an instruction file. Read it, follow it exactly, and write the one JSON object it asks for to the path it gives.
8
+
9
+ The task kind decides the result shape:
10
+
11
+ - A structured-detail batch lists its symbols as numbered lines, and either the source files with their line ranges or the source text itself. Read each listed file completely (page through long files). Return `{"units": [{"h": [12], "explain": "..."}, {"h": [20, 21], "title": "...", "explain": "..."}]}`, naming symbols only by their number (`h` with several numbers is a group). Leave out constants, imports and trivial accessors; group the tests that pin one behavior into one unit and say what they pin. Do not write ids, kinds, dispositions, line numbers or a source field: the program derives them. A re-ask lists only the gaps; return only the additional units.
12
+ - The responsibility-tree task lists the accepted detail units and no raw source. Return `{"nodes": [...], "depends_on": [...]}`; every unit id must appear in exactly one node.
13
+ - A review task shows one batch's units and its source. Return `{"decision": "accepted"|"needs_repair", "issues": [...]}`.
14
+ - The naming and overview tasks return the short JSON shapes their instruction file states.
15
+
16
+ Read only the source the instruction file lists. Do not run commands, edit other files, or add commentary to the JSON. Reply with the single line the instruction file specifies.
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: codebase-explorer
3
+ description: Generate a navigable, source-grounded documentation map (INDEX, a semantic responsibility tree, node pages with structured detail units and program-derived source anchors, and a symbol catalogue) for a code repository. Inside Claude Code, Codex, or another agent harness with subagents, the host agent runs `cbe host` and dispatches one subagent per reading task on the user's own subscription; with an OpenAI-compatible endpoint, run `cbe generate`. Also use it to query a generated map, resume an interrupted run, or report a run's token usage and cost.
4
+ ---
5
+
6
+ # Codebase Explorer
7
+
8
+ CBE splits documentation generation into deterministic CLI steps and model work. The CLI freezes one source snapshot (and validates an optional analyzed graph against it), builds the symbol inventory and reading batches, hands out tasks, checks every JSON result, builds the module tree from the call and import edges, renders node pages with program-derived source anchors, and builds the catalogue for `cbe find`. The model work is one fresh completion per task: one structured-detail payload per batch, the names of the modules in the tree (`tree_name_<k>` for the leaf modules, `tree_top` for the groups above them; the program decides the structure and the model cannot change it), optional reviews, and the system overview. Each detail unit has exactly one primary owner in the tree; the program, never the model, writes the published line ranges.
9
+
10
+ Pick the path by where you run:
11
+
12
+ | You are | Use | Model work runs on |
13
+ |---|---|---|
14
+ | Claude Code, Codex, or another harness that can start subagents | `cbe host ...` (below) | your subagents, on the user's subscription |
15
+ | A shell or service that reaches an OpenAI-compatible endpoint, with no harness login | `cbe generate` (end of this file) | that endpoint, one tool-free request per task |
16
+
17
+ ## Runtime
18
+
19
+ Use the absolute `cbe` command from the "Installed runtime" note if `cbe-install` added one above. Otherwise try `cbe --version`, then `"$(uv tool dir --bin)/cbe" --version`. If CBE is missing, ask the user before installing it.
20
+
21
+ The `cbe` CLI and this Skill are **one build**: the structured-detail, responsibility-tree, `cbe graph` and `cbe context` protocol above exists only in a build that ships with this Skill. An older `cbe` will plan a different run and reject new flags, so install a build matching this Skill, not a remembered version number.
22
+
23
+ - Published release: install the wheel or tag that ships with this Skill. Do not assume a tag name; use whatever the Skill's release page names.
24
+ - Development build from a checkout (use this while the build is unpublished). Point `uv` at the checkout so the CLI and this Skill come from the same commit:
25
+
26
+ ```sh
27
+ uv tool install --python 3.13 /path/to/codebase-explorer
28
+ ```
29
+
30
+ After installing, confirm `cbe --version` and that the newest surface is present, for example `cbe context --help` and `cbe graph capabilities --help`; a CLI without those commands predates this Skill.
31
+
32
+ ## Host-driven generation
33
+
34
+ 1. **Plan.** From the repository root:
35
+
36
+ ```sh
37
+ cbe host plan . --review sample --jobs 4 --host claude-code # or --host codex
38
+ cbe host plan . --graph /abs/path/graph.json # analyzed graph for the same source
39
+ ```
40
+
41
+ `.` is the repository root; the CLI turns it into an absolute path. `--run-dir`, `--repo`, and `--graph` need absolute paths. The command freezes `context.json` (the source snapshot), builds the symbol inventory and reading batches, and prints `run_dir`, `run_tag`, and the file, token, module, and task counts. `RUN` in the commands below is that `run_dir`, written out in full. Tell the user these counts before dispatching, and that the `tasks` count is only the planned tasks: each review finding queues one more repair task later, so the run can finish with more. `--review` is `none`, `sample` (default: one review of the largest batch), or `all` (one review per batch; each finding queues one repair). `--jobs` caps concurrent subagents; keep it within the user's subscription capacity. `--graph` is optional: without it the run records the graph as not provided; with it, CBE rejects a graph whose `source_manifest` does not match the frozen source.
42
+
43
+ 2. **Dispatch.** Run `cbe host next --run-dir RUN`. It leases every task it returns to you, including a re-ask of a task whose answer `submit` rejected. Start one fresh subagent for each returned task, re-asks included, whose whole prompt is the task's `dispatch_message`. Label it with the task's `description` (Claude Code) or `codex_task_name` (Codex), copied exactly; the label lets CBE find that subagent's exact usage later. Attempts at one task share its label, and `import-usage` adds them together. Start the subagents for one `next` batch concurrently. The host page says how you learn that a subagent has finished: in Claude Code its hand-back message starts your next turn, in Codex you wait with `wait_agent`. Do not poll the run directory or sleep in a loop while subagents run. The host-specific calls are in [claude-code.md](references/claude-code.md) and [codex.md](references/codex.md).
44
+
45
+ 3. **Submit.** When a subagent has finished, run `cbe host submit --run-dir RUN --task TASK`, adding the usage numbers the harness showed for that subagent when it shows any. Do not wait for usage that arrives later: a task submitted without usage still gets exact usage from `import-usage`. Submit every finished task before you call `next` again: `next` counts a task as running until `submit` settles it, and a free slot appears only then. The CLI reads the JSON file that the subagent wrote. Module and repair detail tasks allow 3 answers; other tasks allow 2. A detail answer names symbols by the short numbers in its instruction file. CBE keeps every usable unit and re-asks with only the gaps: functions, methods or classes with logic that no unit explains, and rejected units. After the last answer, symbols that are still unexplained are indexed without prose and flagged `unexplained` (STATUS, summary and RUN.md list them), and the task still completes. Other tasks go back to the queue with the exact error and a correction request; on their final invalid answer, usable content is normalized, accepted, and flagged, or the task is marked `failed`. If no answer of a detail task is a JSON object with a `units` list, the task fails and requires resume; the rest of the run continues.
46
+
47
+ `submit` prints one JSON object and exits 0 whether it accepts or rejects, so read `accepted` first. With `accepted: true`, `normalized` and `flags` say whether CBE corrected the answer; a repeated submit of a finished task returns `already: true` and neither key. With `accepted: false` there is no `normalized` or `flags`: `error` holds the checker's message, `attempts` counts the answers so far, and `task_status` is `pending` (a re-ask is queued and `next` returns it) or `failed` (the attempts are used up; see step 4). Both outcomes also add a line to `RUN/progress.log`. The `error` text and that log line are enough to tell the user why an answer was rejected; do not open the instruction files for it. The re-asked subagent finds the same error in its own instruction file.
48
+
49
+ 4. **Repeat** `next` and `submit` until `status` is `complete` or `partial`. Structured-detail batches come first. Reviews may run as their batches finish, alongside other detail work; findings queue repairs. When all detail and review has settled, the program freezes the module tree and the naming tasks appear (`tree_name_<k>` in parallel, then `tree_top`); an accepted repair or late batch makes the tree again. A node the model cannot name gets a program-made title and a note. The overview comes last. Follow `next` for the current dependency order. CBE renders the docs when the overview arrives or when nothing more can run. With `partial`, every finished batch is rendered, the pending work is named in the notes of `docs/RUN.md`, and failed parts stay pending. Report the failed tasks and their errors to the user (the `failed` list in `next`, `submit`, and `status` output names each task with its last error); after the cause is fixed, `cbe host resume` gives them fresh attempts.
50
+
51
+ 5. **Verify.** `cbe host verify --run-dir RUN` runs the deterministic structural and coverage checks: every task is done, the sources did not change, every file is in exactly one reading batch, every detail unit has exactly one primary owner, the responsibility tree is single-rooted and acyclic, every unit's published range is present and in bounds, relative links resolve, the catalogue covers every file, and symbol/unit queries resolve to their actual primary page anchors (or explicitly explain an index-only disposition). These checks do not judge whether an explanation is true. Truth of the prose stays with the separate `review_*` task (one fresh subagent) and the final independent verification, so a run that reports `complete` with passing checks is structurally sound, not thereby semantically reviewed. Report any failed check and say which of the three states applies: run finished, structure valid, semantic review done.
52
+
53
+ Rules for the host agent:
54
+ - Do not read the instruction files or the source yourself, and do not write or edit result JSON. The subagent does that work; the CLI checks it. This keeps your own context and cost small.
55
+ - Do not run more than `--jobs` subagents at once. `next` never hands out more.
56
+ - Never mark a task done by hand. Only `submit` accepts work.
57
+
58
+ ## Progress and resume
59
+
60
+ The run records where it is while it runs: `RUN/progress.log` (one line per claim, acceptance, re-ask, normalization, failure, retry, and render, with timings), `RUN/STATUS.md` (every task's state, attempts, seconds, and output path), and `RUN/host/state.json`. `cbe host status` prints the same table. Any host can continue from these records: `cbe host resume --run-dir RUN` (or `--repo /abs/path/to/repo`, which picks the repository's latest run) accepts results that subagents finished writing before an interruption, returns lost leases to the queue, gives failed tasks fresh attempts (`--keep-failed` skips that), and prints the next action. Then continue at step 2. If it reports changed sources, start a new plan: the old plan no longer matches the code.
61
+
62
+ ## Cost and usage
63
+
64
+ Report cost after every run. The rule: **use the harness's exact numbers when it records them; otherwise estimate, and say clearly that it is an estimate.**
65
+
66
+ 1. Run `cbe host import-usage --run-dir RUN --harness claude-code` (or `codex`). It reads the per-subagent usage that the harness already wrote to disk.
67
+ 2. Run `cbe host cost --run-dir RUN`. Rows with imported usage are `exact` and are priced by the model recorded in their transcript; the rest are `estimate`, computed from instruction, source, and result sizes. Add `--model MODEL` (for example `claude-sonnet-5-5`) only when `import-usage` listed `tasks_without_exact_usage`: it prices those estimated rows, which otherwise show `null` dollars. Token certainty and pricing are separate: unknown model prices produce `null` dollar values in JSON and `unknown` in the report. Supply current rates with `--price INPUT,OUTPUT,CACHE_WRITE,CACHE_READ` when needed; CBE does not silently substitute a comparison price. It writes `host/COST.md` and `host/cost.json`.
68
+ 3. Tell the user: the number of subagent runs, the wall time (from the `plan` line to the last `render` line in `RUN/progress.log`), the token totals and whether they are exact or estimated, and the API-list-price equivalent. Say that the dollar figure is not a bill: a subscription spends plan quota. Your own orchestration turns are not included. The harness shows their total with a command that only the user can type (`/usage` in Claude Code, `/status` in Codex); ask the user to run it if they want that total.
69
+
70
+ ## Read and query the result
71
+
72
+ Start at `RUN/docs/INDEX.md`: the overview, then the module tree, one line per module saying what it is responsible for. Pick the module that matches the maintenance question and open its node page; if the tree is not enough, use `cbe find --run-dir RUN --term WORD` to locate a symbol, `cbe query` to read one unit and `cbe source` for its frozen source. `DEPENDENCIES.md` holds the dependency view and `RUN.md` the graph coverage and generation notes. On a node page select a unit. The page keeps the explanation, necessary boundary notes, uncertainties, and compact relation links. Its footer shows how to find the selected title's ID and then query it.
73
+
74
+ The dependency view uses **graph-confirmed** for pairs found in both the tree and resolved call/import edges, **model-inferred** for tree-only pairs, and **graph-only** for graph-only pairs. The first two count edges between subtrees; graph-only counts direct node owners. **Containment** rows show ancestor direct units versus a descendant subtree as `→ N / ← M`, relative to the listed pair. **Within containment** rows list direct owner pairs separately. Both containment categories stay out of Mermaid and the three dependency totals. Graph-only and within containment each keep up to 40 pairs, ranked by edge count, with independent omitted counts. `summary.json` reports the full within containment count in `within_containment`. If the model supplies no key flows, the report shows the first five **Program candidates, not selected by the model**. Program labels and navigation use English; model prose keeps its original language.
75
+
76
+ `RUN` is the absolute run directory. Find an ID, then retrieve its complete explanation and evidence:
77
+
78
+ ```sh
79
+ cbe find --run-dir RUN --term SEARCH_TERM
80
+ cbe query --run-dir RUN --id ID
81
+ cbe query --run-dir RUN --id ID --json
82
+ cbe query --run-dir RUN --id ID --edges cfg,dataflow
83
+ cbe query --run-dir RUN --id ID --edges all --json
84
+ cbe source --run-dir RUN --id ID --context 2
85
+ ```
86
+
87
+ `ID` can be a unit ID, inventory symbol ID, or file path. `query` returns explanation text, full signatures, all source ranges, folded members, relation evidence, and incoming and outgoing call/import edges with their original statuses. CFG/dataflow edges are counted by default; use `--edges cfg,dataflow` or `--edges all` to expand original outgoing edges from the frozen graph. Dataflow is only in graphs built with `cbe graph build --with-dataflow`; on other graphs `--edges dataflow` says so and `internal_edge_counts` has no `dataflow` entry. Use `--json` for the machine-readable object. A grouped symbol retains its own source range; take `unit_id` from `query --json` and query that ID for the owning unit and all its ranges. A file query lists its symbols and associated units. An index-only symbol returns its recorded reason instead of invented prose.
88
+
89
+ `source` prints numbered code from `RUN/context.json`. It verifies each selected file's SHA-256 before printing any code. It reports a digest mismatch as an error. `--context N` adds N surrounding lines and must be nonnegative. Use this command to inspect the precise code behind an explanation.
90
+
91
+ `catalog.json` preserves the unit records and indexes graph edges. Complete graph evidence stays once in the frozen context and `query` expands it on demand. `summary.json` reports token ratios and their scope. Graph evidence describes static analysis; it does not prove runtime behavior. Confirm that the explanations answer the maintenance question before claiming semantic quality.
92
+
93
+ ## Script-driven generation (OpenAI-compatible API)
94
+
95
+ ```sh
96
+ cbe generate . --model gpt-oss-120b \
97
+ --base-url https://api.example.com/v1 --api-key-env MY_API_KEY
98
+ ```
99
+
100
+ `cbe generate` speaks the OpenAI-compatible `POST {base-url}/chat/completions` shape. The API key comes from the named environment variable (default `OPENAI_API_KEY`) or a standard config file, never from a flag, and CBE never writes it to the run log or any durable artifact. The command runs every completion itself on the same run state as `cbe host`, prints `run_dir`, `index`, status, token totals, and elapsed time, and records each physical call in `calls.csv`. It exits 0 when complete and 3 when the docs are rendered with pending parts; continue with `cbe generate . --resume`. Review modes are `none`, `sample`, and `all`.
101
+