Codebase Trainer docs
Set it up, learn the eight tools, configure it for your team, and see exactly how it was measured.
Quick start
Run one command in the root of your repository, restart your editor, and ask your agent a question.
Register the server and build the index
npx codebase-trainer setup
It finds the editors you use and adds codebase-trainer to their project config (.mcp.json for Claude Code, .cursor/mcp.json, .vscode/mcp.json), keeping any other servers in those files. Then it indexes the repo. Add --dry-run to see what it would write, or --client claude cursor to choose.
Restart your editor
The editor starts the server itself (npx -y codebase-trainer mcp) from the repository folder. Commit the config files so your team gets the same setup.
Ask
Use codebase-trainer feature_slice to show me everything involved in password reset,
then tell me which files I need to change to add rate limiting.
Requirements
Node.js
The index uses Node's built-in node:sqlite. On Node versions without it, the index falls back to a JSON file automatically. Tested on Node 22 and 24.
Operating system
CI runs the full test suite on all three. Paths are reported with forward slashes on every platform.
Git
Needed for diff review, test selection for your working-tree changes, and learning commit conventions. Everything else works without it.
Disk and memory
A 10,000-file repo needs about 24 MB in .codebase/. The server keeps the index and parsed files in memory while it runs.
Connect your editor
npx codebase-trainer setup does this for you. To do it by hand, add the server to your client's config. The server indexes the folder it is started in, so use project-level configs where your client supports them.
Claude Code
Project config, committed with the repo: .mcp.json at the repo root.
{
"mcpServers": {
"codebase-trainer": { "command": "npx", "args": ["-y", "codebase-trainer", "mcp"] }
}
}
Or from the terminal, in the repo root:
claude mcp add --scope project codebase-trainer -- npx -y codebase-trainer mcp
Cursor
.cursor/mcp.json in the repo (or Settings → MCP → Add new server with the same command).
{
"mcpServers": {
"codebase-trainer": { "command": "npx", "args": ["-y", "codebase-trainer", "mcp"] }
}
}
VS Code (Copilot agent mode)
.vscode/mcp.json in the repo. Note the servers key and type.
{
"servers": {
"codebase-trainer": { "type": "stdio", "command": "npx", "args": ["-y", "codebase-trainer", "mcp"] }
}
}
Windsurf and other clients
Windsurf keeps a per-user file, ~/.codeium/windsurf/mcp_config.json, with the same mcpServers entry; npx codebase-trainer setup --client windsurf writes it. Any MCP client that can start a stdio server works: the command is npx -y codebase-trainer mcp, started in the repository folder.
Faster start with a global install
npm install -g codebase-trainer, then use cb-trainer with args ["mcp"] instead of npx. Upgrade with npm install -g codebase-trainer@latest.
Config generator
Pick your editor and copy the file, or run npx codebase-trainer setup to write it for you.
{
"mcpServers": {
"codebase-trainer": {
"command": "npx",
"args": [
"-y",
"codebase-trainer",
"mcp"
]
}
}
}
Or run in the repo root: claude mcp add --scope project codebase-trainer -- npx -y codebase-trainer mcp
The eight tools
Every tool takes budget_tokens and reports what it cut. The examples are real responses from the published 2.0.0 package on the benchmark apps, shortened where marked.
search
FIND CODERanked snippets labelled code, test, doc or config, with file:line. Keyword ranking (BM25 over stemmed words, exact symbols, PageRank) with code ranked first; fused with a local neural model when the repo opts in. scope: "workspace" searches sibling repos; detail: "refs" returns locations only.
"Where are comments added to an article? Use codebase-trainer search."
{
"semanticResults": [
{
"filePath": "src/app/routes/article/article.controller.ts",
"startLine": 152, "endLine": 163, "kind": "code", "score": 18.2,
"snippet": "const comments = await getCommentsByArticle(req.params.slug, req.auth?.user?.id); …"
},
{
"filePath": "src/app/routes/article/article.service.ts",
"startLine": 476, "endLine": 487, "kind": "code", "score": 17.7,
"snippet": "const comment = await prisma.comment.create({ …"
}
],
"mode": "lexical",
"index": { "fullRebuild": false, "refreshedFiles": 0, "removedFiles": 0 },
"budget": { "tokens": 348, "budgetTokens": 8000 }
}
codebase://conventionsConventions learned from the code, with the counts behind each.
codebase://routesRoutes the repo serves and the ones it calls.
codebase://permissionsAuth, scopes and roles per route, with findings.
codebase://driftClient/server contract mismatches.
codebase://graph/circularImport cycles.
codebase://graph/qualityHotspots and sync I/O in request paths.
Using it with an agent
Agents pick tools from their descriptions, so naming the tool helps the first few times. These are the moments it pays off most.
One call instead of a dozen greps and file reads.
Dependents, other references, and the tests that reach the file.
Ordered steps with file:line evidence, and a Mermaid diagram.
Secrets, broken imports, contract drift and permission problems on changed routes.
Routes without guards, deletes allowed by edit scopes, read scopes on writes.
Conventions with the evidence behind each, module diagram and hotspots.
How it works
Everything runs inside one local Node.js process. No API keys, no vector database, no language server, no telemetry.
Parse
TypeScript, TSX, JavaScript and Python are parsed with tree-sitter (grammars ship in the package). Other languages use pattern-based extractors.
Link
Imports (tsconfig paths, workspace packages), call sites, client requests to route handlers, ORM calls to models, dependency injection, tRPC procedures and auth guards become one graph.
Index
Syntax-aligned chunks in a SQLite database (.codebase/index.sqlite) with BM25 terms and PageRank scores. Only changed files are re-indexed.
Serve
Eight MCP tools over stdio, each with a token budget. While the server runs it watches the repo, so no tool call re-scans it.
Honest limits
- Static analysis: dynamic dispatch, runtime configuration and guards applied where a router is mounted are not traced.
feature_slicefavours recall: about a third of the files it returns were labelled as needed, the rest are neighbours a change often touches.- The permission map is a heuristic with evidence, not a security audit. It checks for a signed-in user, not whether that user may act on a record.
- Search is keyword-based unless you opt in to the neural model; it matches word families (resolve / resolver / resolution), not synonyms.
- Best on JavaScript and TypeScript; Python is partly supported, Go, Java and Rust only lightly.
CLI reference
Every command takes -d <path> for the repo (default: current folder), and most take --json. Run cb-trainer <command> --help for all options. With npx, use npx codebase-trainer <command>.
| Command | What it does |
|---|---|
| Set up | |
setup [--client …] [--dry-run] | Register the MCP server with Claude Code, Cursor, VS Code (Windsurf when named) and build the first index. |
mcp | Start the MCP server over stdio (your editor runs this). |
init [--embeddings] | Build the index and learn conventions; --embeddings also enables neural search. |
embeddings enable | disable | status | Turn the optional local neural model on or off for this repo. |
| Understand code | |
search "<query>" | Ranked code snippets with file:line. |
slice "<feature>" [--budget 6000] | Everything a feature touches, by layer, packed to a token budget. |
flow "<feature>" | Execution flow with evidence and a Mermaid sequence diagram. |
impact <file or symbol> | Dependents, references and the tests to run. |
tests [files…] [--base main] [-c] | Tests affected by the given files, or by your git changes; -c prints only the commands. |
architecture | Module dependency diagram (Mermaid) and import cycles. |
| Review and audit | |
review [--base main] [--format sarif] [-o file] | Check your diff (or one file); exits non-zero on error findings. |
permissions [--findings-only] | Auth requirement, scopes and roles per route, with findings. |
routes · drift | Routes served and called; client/server contract mismatches. |
security · duplicates · audit | Secrets and risky code; duplicated blocks; import cycles and sync I/O. |
pr-review [--base main] | A Markdown review of your diff for a pull request. |
| Maintain | |
update · watch | Re-index changed files now, or on every save. Search already refreshes changed files before each query. |
docs · ui | Write an onboarding guide; open an HTML dashboard. |
Configuration
Nothing needs configuring. For team-wide settings, commit a codebase-trainer.yaml at the repo root. Unknown or malformed settings are ignored and reported by codebase_overview.
exclude: ["generated/**", "**/*.snap"] # on top of .gitignore and .codebaseignore
embeddings: false # or { enabled: true, model: Xenova/all-MiniLM-L6-v2 }
auth:
guards: [ensureTeamMember] # your own auth middleware, for the permission map
publicPaths: ["/api/status"] # routes that are public by design
budgets:
defaultTokens: 8000 # per tool call
featureSliceTokens: 6000
What is indexed
Source, config and docs files up to 500 KB that are not excluded by .gitignore, .git/info/exclude, .codebaseignore or the built-in list (node_modules, dist, build, .next, virtualenvs, caches). Credential files such as .env and *.pem are never indexed, and secrets inside indexed files are redacted.
Environment variables
| Variable | Effect |
|---|---|
CODEBASE_TRAINER_AUTO_REFRESH=0 | Do not re-index changed files before a search; results from changed files are marked stale. |
CODEBASE_TRAINER_EMBEDDINGS=0 | Turn neural search off even if the repo opted in. |
CODEBASE_TRAINER_MODEL_CACHE | Where the neural model is stored (default ~/.cache/codebase-trainer/models). |
CODEBASE_ENCRYPTION_KEY | Encrypt the index at rest (AES-256-GCM); init --encrypt creates a local key instead. |
CODEBASE_TRAINER_PARSER=regex | Use the pattern-based extractors instead of tree-sitter. |
Files it writes
Everything generated lives in .codebase/ (index, conventions, reports); add it to .gitignore. Commit codebase-trainer.yaml and your editor's MCP config instead.
Optional neural search
A small local model whose ranking is fused with keyword search by reciprocal rank fusion. It runs on your CPU; nothing leaves your machine. Without opting in, nothing is downloaded.
npm install @huggingface/transformers # optional peer dependency (~300 MB with its ONNX runtime)
cb-trainer embeddings enable # downloads MiniLM-L6 (23 MB) once and embeds the index
cb-trainer embeddings status
cb-trainer embeddings disable
| All 104 questions | Keyword only | With MiniLM-L6 |
|---|---|---|
| Right file in the top 5 | 84% | 94% |
| Mean reciprocal rank | 0.71 | 0.75 |
| Feature files in the top 10 | 59% | 65% |
| Search time on the benchmark apps | 20–40 ms | 90–160 ms |
Four small models were compared on the tuning questions (MiniLM-L6, bge-small, arctic-embed-xs, jina-v2-small); MiniLM-L6 was best and the gain held on the 28 held-out questions. Encrypted indexes keep neural search off, because vectors would be stored unencrypted. Teams can switch it on for everyone with embeddings: true in codebase-trainer.yaml.
CI and code scanning
Review every pull request with the same checks and see findings in GitHub's Code Scanning tab.
name: codebase-trainer review
on: pull_request
permissions:
contents: read
security-events: write
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: actions/setup-node@v4
with: { node-version: 22 }
- uses: om0852/codebase-trainer@v1
with: { base: "origin/${{ github.base_ref }}" }
- uses: github/codeql-action/upload-sarif@v3
if: always()
with: { sarif_file: codebase-trainer.sarif }
Without the action: npx codebase-trainer review --base origin/main --format sarif --output review.sarif. The step fails on error-severity findings (such as a committed secret); set fail-on-error: false on the action to only report.
Benchmark and limits
104 hand-labelled questions on four open-source apps pinned to exact commits: taxonomy (Next.js + Prisma), node-express-realworld (Express + Prisma), nestjs-realworld (NestJS + TypeORM) and create-t3-turbo (tRPC monorepo). The baseline is what an agent does without an index: grep the question's words and open the files with the most matches. Settings were tuned on 76 questions and confirmed on 28 held out.
Finding code (80 "where is X" questions, 24 feature questions)
| Codebase Trainer | + neural search | grep and read | |
|---|---|---|---|
| Right file ranked first | 60% | 61% | 24% |
| Right file in the top 5 | 84% | 94% | 66% |
| Mean reciprocal rank | 0.71 | 0.75 | 0.43 |
| Median tokens read to reach the right file | 1,062 | 945 | 3,974 |
| Share of a feature's files in the top 10 | 59% | 65% | 42% |
feature_slice: one call per feature (24 questions)
| Result | |
|---|---|
| Share of the needed files returned | 83% |
| Features with every needed file | 50% |
| Median tokens for the whole slice | 4,552 |
| Share of returned files labelled as needed | 33% |
Search's top 10 holds 59% of a feature's files and reading files until all are found costs a median 7,500 tokens.
Scale: a generated 10,000-file Next.js + Prisma repo
| 1.4 | 2.0 | Target | |
|---|---|---|---|
| Search, warm p50 / p95 | 2.1 s / 2.7 s | 43 / 50 ms | p95 < 150 ms |
| Search right after editing a file | 31 s | 38 ms | |
feature_slice, warm | 17 s | 88 ms | |
impact, warm | 26 s | 0.3 s | |
| Index build / size | 13 s / 41 MB | 13 s / 24 MB | < 60 s / < 100 MB |
Synthetic code measures speed and size only, not ranking quality.
Tests to run, and routes that need auth
| Codebase Trainer | grep | |
|---|---|---|
| Failing tests selected when each source file breaks (mutation, 44 files) | 220 / 220 | — |
| Share of the test suite skipped per change | 60% | — |
| Failing tests found for 3 changes in this repo | 24 / 24 | 5 / 24 |
| Routes with the right auth requirement (4 apps) | 57 / 57 | — |
| Permission findings / false positives | 1 / 0 | — |
The one permission finding is real: nestjs-realworld's DELETE /api/users/:slug has no guard.
Where it is still weak
feature_sliceprecision is 33% against the labels, below our 60% target, and tRPC monorepos (t3-turbo) score lowest.- Neural search doubles search time (90–160 ms on these repos) and the first embedding of a repo takes 20–70 s.
- A one-shot CLI command that needs call edges on a 10,000-file repo still parses every file the first time (about 13 s); the MCP server does this in the background.
- The permission rules about scopes are only tested on fixtures: none of the four apps uses scopes.
Reproduce with npm run bench:setup && npm run bench. Results, labels and scripts are in bench/.
Upgrading from 1.x
- Node 22 or later is required.
- The index moves from
.codebase/embeddings.jsonto.codebase/index.sqliteand is rebuilt automatically on first use. - MCP tools have new names. The old names keep working through 2.x and log a deprecation note once per session.
| 1.x tool | 2.0 tool |
|---|---|
search_codebase, search_global_workspace | search (scope: workspace) |
trace_execution_flow | trace_flow |
impact_analysis, get_change_impact_analysis | impact |
check_diff_against_standards, generate_pr_review | review_diff (format: markdown) |
get_microservice_api_routes, detect_api_drift, get_permission_map | api_map |
get_codebase_conventions, visualize_architecture, analyze_codebase_quality, get_model_health_status, generate_onboarding_guide | codebase_overview |
scan_security_vulnerabilities, scan_code_duplication, get_tech_debt_items | quality_scan |
get_context_pack | still available; feature_slice is the better choice |
Troubleshooting and FAQ
My editor says the MCP server failed to start
Check node --version is 22 or later, and that npx -y codebase-trainer mcp starts in a terminal (it waits silently for input; press Ctrl+C). On Windows, if npx is not found by the editor, install globally and use cb-trainer with args ["mcp"].
It indexed the wrong folder
The server indexes the folder it is started in. Use a project-level config (.mcp.json, .cursor/mcp.json, .vscode/mcp.json) so your editor starts it in the repo, or run setup from the repo root.
The first call is slow on a big repo
The first index and the first call graph parse every file once (seconds on a 10,000-file repo). The server does this in the background right after it starts, and after that only changed files are processed.
Does any code leave my machine?
No. No tool makes network calls, and a test runs all eight with sockets, DNS and fetch disabled. The only download is the optional neural model, after you enable it.
Results look out of date
Changed files are re-indexed before every search, and the server watches the repo. If you set CODEBASE_TRAINER_AUTO_REFRESH=0, results from changed files are marked stale; run cb-trainer update. To start over, delete .codebase/.
A finding is wrong
Findings are static heuristics with evidence; check the evidence lines. For the permission map, add your own guard names under auth.guards and public routes under auth.publicPaths in codebase-trainer.yaml. Please report false positives on GitHub.