Skip to content

Documentation · bb 0.1.0

The Backbencher guide.

Install, index your first project, understand what the indexer does with your files, keep it fresh, and read the generated CLI reference. Everything here is generated against the real bb surface.

14 commands · 16 MCP tools · generated from the real bb CLI · verified by CI

Installation.

Backbencher runs fully local: the bb CLI, the SQLite index, and the analysis all live on your machine. Your source code never leaves it.

Primary · npm

npm

The published artifact every release ships, so the CLI and the package version always agree. Requires Node.js 18 or newer.

npm install -g @backbencher/brain

Shell installer

macOS & Linux

A one-line installer, an alternative to npm.

curl -fsSL https://backbencher.cc/install.sh | bash

PowerShell installer

Windows

A one-line installer, the Windows alternative to npm.

irm https://backbencher.cc/install.ps1 | iex

Both installers prefer npm and install the same package. Only when npm is unavailable do they fall back to a release binary from the backbencher-hq/backbencher-brain GitHub releases, and only after its sha256 checksum verifies against the release’s checksums.txt. Pin with VERSION=0.1.0 in front of either command ($env:VERSION="0.1.0" on Windows).

Pin the npm package with npm install -g @backbencher/brain@0.1.0.

Verify

bb --version

If bb is not found, check that your npm global prefix (npm prefix -g) or ~/.local/bin is on your PATH, then run the absolute path to verify.

Build the first index.

Run bb index from the repository root, then bb stats to see what landed. The four follow-ups below are what you reach for when the tree, the derived data, or a run needs attention.

cd /path/to/project
bb index
bb stats
bb index --changed
Incremental: only missing or changed files are reparsed.
bb index --force
Wipes the existing index for this project and rebuilds it in place.
bb index --post
Re-runs relationship resolution, enrichment, and health phases without reparsing source files — the remediation for stale derived data.
bb index --resume
Continues an interrupted run from its checkpoint: only missing or changed files are processed, then the bounded derived pass runs.

How the index works.

bb index walks your project, parses every file with the right grammar, extracts symbols and relationships, and persists them into one local database per project — the same store every read surface answers from. Nothing is sent anywhere: the index lives on your machine.

  1. 01

    Parse — a dedicated grammar per family

    For 50 of the 53 registry ids a dedicated analyzer (tree-sitter grammar or hand-written oracle) reads the file with AST precision. The other 3 — TSX, Sass and Terraform — are aliases served by the TypeScript, CSS and HCL analyzers rather than separate languages, so the editor lane can never exceed the analyzer set. See the language reference for the per-family depth label.

  2. 02

    Extract — symbols, bounds, relationships

    Each analyzer records what it can prove: symbols with a kind and exact byte bounds (functions, classes, modules, selectors, tables — whatever the family has), and the relationships between them — calls, imports, references, instantiations, uses. Cross-language edges carry an explicit evidence label (structural, import-based, usage-contextual, reference-qualified, or inferred), never a silent guess. What a file could not be parsed into is declared, not invented.

  3. 03

    Persist — one relational store per project

    Extracted rows land in one local SQLite database per project (the brain): files, symbols, relationships, imports, and index status as first-class tables; agent annotations and semantic embedding vectors stored alongside when configured; security taint flows and project health as derived tables. A migration layer keeps the schema versioned.

  4. 04

    Serve — every door reads the same store

    One index, several doors: the 16 MCP tools over bb mcp, the CLI (bb search, bb stats, bb health), and the editor integration, which talks to the same index through the LSP server — hover, symbol navigation, and call-graph views answer from the same rows a tool call reads.

  5. 05

    Guard — freshness and safe writes

    Reads resolve freshness against the live working tree and say so when the index is behind (and how to catch up). Writes are guarded: path checks, AST byte bounds, validation, and rollback, with dryRun previews before risky edits. After an edit, the changed file is reindexed so the agent answers from what it just wrote.

Depth is declared, never assumed

Symbol kinds, relationship edges, and depth labels on this site are audited against the analyzers. If a family parses deeper or shallower than documented, that is a bug worth reporting.

What gets indexed.

The indexer walks your project once and then keeps up incrementally. Three layers decide what it reads — in this order.

1 · Built-in directory skips

Always on, in every project, before any of your own rules are read. These directories never reach the parser:

.gitnode_modulesdistbuildoutcoverage.nexttarget__pycache__.venvvenv

2 · Your gitignore rules are respected

Anything git ignores, the indexer skips — a .gitignore at any level of the tree is read as it walks, so a project that is already gitignored correctly needs no extra configuration.

3 · Your .bbignore overrides all of it

A project-local .bbignore file (gitignore syntax) has higher priority than .gitignore — use it when you want git to track something but the indexer to skip it, like large generated fixtures. After you add it, bb index --changed applies it. If an unexpected directory shows up in your index, that is the fix — and it is a bug worth reporting.

Size tiers — a guardrail, not a silent cap

One generated blob can stall a whole run, so very large files are handled by tier instead of being parsed blindly:

File sizeWhat the indexer does
up to 1 MBFull AST parse — symbols with byte bounds, and the relationships between them.
1 MB–5 MBStructural symbols only, for .json, .yaml, .yml, .toml, .xml, .xsd, .dtd, .md, .proto — the formats where a huge file is usually machine-generated.
over 5 MBSkipped, never parsed (5 MB walk limit). The tiers are tuned, not dogma: if a file you care about is skipped, tell us.

How long indexing takes

The first index is the expensive pass: it parses every discovered file and then runs the derived phases. A re-run of an unchanged project is fast, because files whose size and modification time are unchanged are not re-parsed at all. Progress streams while it runs, and bb status reports per-phase timings of the last run.

Keeping the index fresh.

A code index is only useful while it matches the working tree. Three mechanisms, in the order you will normally meet them.

1 · Reads refresh stale files inside a budget

When a read path touches files that are stale or missing in the index, it repairs exactly those files within a budget before answering, and says so in an auto-refreshed N files in Xms line. The budget is 25 files or 2 MiB of changed bytes, whichever comes first, and it is tunable through the environment:

BB_NO_AUTO_REFRESHBB_AUTO_REFRESH_MAX_FILESBB_AUTO_REFRESH_MAX_BYTES

BB_NO_AUTO_REFRESH=1 opts out entirely. If the repair would exceed the budget, or another index run holds the lock, the tool answers from existing data with a staleness footer instead of pretending the index is current.

2 · Incremental, on purpose

Routine sync

Changed files only

bb index --changed

Re-parses only files changed since the last index, and runs the bounded derived-data pass so relationships stay current. This is the routine “I edited things, sync my index” command.

One file

A single file

bb index --file src/session.ts

Re-indexes one file’s symbols and relationships. Use it right after an agent creates or edits a function.

Derived data

Without re-parsing

bb index --post

Re-runs the derived phases without re-parsing anything — the remediation when derived data was skipped or went stale (for example after --skip-post-processing).

Interrupted run

From the checkpoint

bb index --resume

Continues an interrupted run from its checkpoint: only missing or changed files are processed, then the bounded derived pass runs.

What a changed file recomputes

Only what the changed files touch — never the whole index. This is the exact list, phase by phase:

DataUpdated for changed filesHow
symbolsyesChanged files are re-parsed by the same analyzers and their symbol rows are rewritten; unchanged files are not touched.
relationshipsyesThe re-parsed file's own edges resolve at insert time; cross-file edges from other files pointing into the changed file are repaired; unresolved external targets are re-resolved, scoped to the touched symbols.
enrichmentyesRe-run scoped to the touched source symbols.
gravityyesRecomputed for the touched symbols, plus every symbol whose in-degree changed because of the edit.
taintyesResolution re-processes only the flows that are still unresolved.
healthyesRecomputed (cheap SQL aggregates).
analyzeyesSQLite's own ANALYZE, so the query planner has statistics. Without sqlite_stat1 it guesses: measured on a real 4.8 GB index, that guess cost a full brain_symbol scan per graph hop — about 15s per bb_graph call, and bb_patterns timed out at 45s. With the statistics present the same hops are sub-millisecond. One-time cost around 8s on that index, covered by the single-flight index lock.
deleted filesyesPurged from the index, including their derived rows.
embeddingsqueuedNew and changed symbols are queued for the embedding provider during storage; vectors fill in asynchronously with a local fallback when no provider is configured.

Two honest edges: embeddings are asynchronous, so semantic search can lag symbol and relationship freshness by a few seconds after an edit; and a derived phase that fails leaves the run’s status partial rather than silently claiming success. A run summary reports what it did as derivedPass: full | bounded | deferred | skipped-unchanged — a bounded pass covers the touched files, a full pass covers everything, and a deferred pass means the derived data is still owed (run bb index --post).

Only a full rebuild recomputes everything

bb index --force wipes the project’s index and rebuilds it from scratch. Incremental runs cover every case above, so you should rarely need it.

Turn on semantic search.

Semantic search (bb_ask semantic mode) uses embedding vectors. Without a provider key, the indexer still works — semantic search just falls back to weaker local vectors, and the CLI tells you so honestly.

bb setup        # interactive: provider, API key, model
bb setup show   # inspect config — the key is shown as a fingerprint only

Diagnose a broken setup or inconsistent index:

bb doctor

bb doctor is read-only. bb doctor --fix repairs file-permission problems only (0600 on the config); it changes nothing else. The first bb index run also offers the setup wizard interactively — skip it once with bb index --no-setup.

Keys stay on your machine

The API key is stored with owner-only permissions (0600) and is never sent to any AI agent — tools see a fingerprint only.

The agent tools.

Backbencher exposes 16 public MCP tools for indexed discovery, analysis, documentation, guarded mutation, diagnostics, security analysis, migration planning, and graph export. These are tool calls an MCP client invokes — not shell subcommands. Each row carries the tool’s registry summary; the tool reference adds the full contract — the complete generated description, modes, defaults, parameters and examples.

ToolGroupWhat it does
bb_searchDiscoveryUnified lexical, content, exact-symbol, and file retrieval.
bb_askDiscoveryExact aggregates, exact-name lookups, and scored semantic or lexical matches — each labelled with its route and bounds.
bb_patternsAnalysisPattern/orphan analysis ranked by confidence, with a bounded page, a declared census, per-finding staleness, and optional persisted run history.
bb_migrateAnalysisBatch cross-language migration plans with ordering, waves, cohort rollup, scope completeness, and unsupported mappings.
bb_analyzeAnalysisOne typed analysis surface over the graph, the file graph, project counts, complexity, impact and test evidence. Every mode is bounded, declares its own bounds, and reports what it returned against what exists.
bb_docAnalysisCited Markdown or JSON documentation over indexed source and relationships, with declared bounds, emitted-citation freshness counts, and a payload-measured output budget.
bb_graphAnalysisPer-symbol graph with per-edge evidence tiers — the agent view of the editor's graph panel.
bb_impactAnalysisBounded impact with declared truncation — identical numbers to the editor's impact mode.
bb_cross_languageAnalysisStored cross-language pairs, each naming both ends, with member rows reported separately as the member's, absence declared as a property of the store, and declared bounds and truncation.
bb_annotateAnalysisAgent note with enforced provenance, stored where the human reads.
bb_annotationsAnalysisAnnotations with full provenance; declared absence; both name forms matched; path canonicalized.
bb_healthDiagnosticsUnified index, schema, freshness, embeddings, runtime, integrity, completeness and analysis-history report — status by default, one explicit refresh behaviour, and no mode parameter.
bb_securityDiagnosticsTaint-flow findings over the index, with optional persisted run history. A flow is a finding only when both endpoints resolve to indexed symbols; one-sided flows are reported as unvalidated observations. A findings answer states the pre-cap census so a capped scan is never mistaken for a complete one; a history answer states its run count and its finding total, and its findings page is capped and declared. Reads open the index read-only and refuse an unindexed project; recordRun is the one write. Not detected: hardcoded secrets; genuine cross-language taint; standalone weak crypto.
bb_visualizeDiagnosticsScoped canonical dependency graphs with explicit truncation and provenance.
bb_editOperationsUnified safe source editing with preview, validation, rollback, and reindex.
bb_indexOperationsImmediately refresh the index for a just-written/edited file or directory; mode=post re-derives relationships/taints/health without re-parsing.

Full schemas, defaults, safety behavior, and limitations

From the terminal, run any tool with JSON arguments:

bb tool bb_search --args '{"mode":"symbol","query":"createSession"}'

Connect an MCP client.

bb mcp starts the Backbencher MCP server over stdio. Point any MCP client at it — Claude Code, Cursor, VS Code, opencode, and others.

# Claude Code
claude mcp add backbencher -- bb mcp --dir /path/to/project

# Generic MCP client configuration
{
  "mcpServers": {
    "backbencher": {
      "command": "bb",
      "args": ["mcp", "--dir", "/path/to/project"]
    }
  }
}

bb mcp starts a server, it does not configure clients

bb mcp is the server process. Client registration happens in your MCP client’s own configuration, as shown above.

The CLI reference.

All 14 top-level commands and every flag they accept. This reference is generated from the CLI’s own help text, so it cannot list a flag the binary does not have — run bb <command> --help for the same output on your machine.

bb help [options] [command...]

display help for a command, or list all commands

Arguments

  • command — command to describe; include a subcommand for bb help <cmd> <sub> (omit for the command list)

bb tool [options] <name> [unexpected...]

run one of the public tools with JSON arguments

Arguments

  • name — public tool name, e.g. bb_search or bb_doc
  • unexpected — rejected: tool arguments are passed with --args '<json>' so a stray positional is an error, not a silent no-op
FlagWhat it does
--dir <dir>project directory (default: cwd)
--args <json>tool arguments as a JSON object (default: "{}")

bb index [options] [dir]

index a project (default: current directory)

Arguments

  • dir — project directory (default: current directory)
FlagWhat it does
--forcewipe the existing index and rebuild
--no-setupskip the first-run embedding setup prompt
--skip-post-processingparse + store only; SKIP relationship resolution/enrichment/gravity/taint/health (derived data goes stale until: bb index --post)
--postre-run relationship/enrichment/gravity/taint/health phases only — no re-parse (remediation for stale derived data after --changed/--resume/agent edits)
--file <path>reindex a single file's symbols + relationships, relative to <dir> or absolute and must be inside the project (runs a scoped derived-data pass for that file; refuses a missing/outside path)
--changedreindex only files changed since the last index (runs the bounded derived-data pass for touched files — relationships stay current)
--resumecontinue from an interrupted run's checkpoint (incremental: only missing/changed files; runs the bounded derived-data pass)
--import <db>adopt an existing brain.db file (re-home a moved project's index)
--exclude <globs>skip files matching comma-separated globs during discovery (repeatable); NON-DESTRUCTIVE: files already indexed by an earlier run keep their rows (default: [])
--concurrency <n>worker count for this run (1-64; default max(2, min(cpus-1, 12)))

bb setup [options] [command]

embedding provider setup (API key, model)

Subcommands

bb setup show

bb doctor [options]

diagnose embedding setup and index consistency (read-only)

FlagWhat it does
--dir <dir>project directory (default: cwd)
--fixrepair permission problems (0600 only; this IS the explicit apply — without it doctor is read-only)

bb upgrade [options]

check for a newer bb and report exactly how to install it

FlagWhat it does
--checkonly report whether a newer version exists; change nothing
--to <dist-tag-or-range>npm dist-tag or version range to compare against (default: latest)

bb stats [options] [dir]

query index counts anytime: files/symbols/relationships/embeddings (default:

Arguments

  • dir — project directory (default: current directory)
FlagWhat it does
--jsonmachine-readable JSON output (stable keys for scripts)

bb status [options] [dir]

show in-flight/last-run index state and per-phase timings (default: cwd)

Arguments

  • dir — project directory (default: current directory)
FlagWhat it does
--jsonmachine-readable JSON output (stable keys for scripts)

bb projects [options]

list every indexed project: DB path, size, counts, last index (default: all

FlagWhat it does
--sort <field>sort by name|size|time (default: "name")
--remove <id>remove one indexed project by id (reclaims its DB + embeddings)
--forceremove even if that project is currently being indexed
--jsonmachine-readable JSON output for the project list (stable keys for scripts)

bb health [options] [dir]

index health and freshness

Arguments

  • dir — project directory (default: cwd)
FlagWhat it does
--refreshreindex the project before reporting
--forceforce a full in-place reindex (implies --refresh)
--no-waitdo not wait for the refresh to finish
--completecheck freshness for all files (not just a sample)
--integrityrun the 12-point index integrity check
--sample-size <n>freshness sample size (default: 200) (default: "200")
--verbose-configshow effective embedding config + per-field source

bb onboard [options] [dir]

write the bb tools guidance section into <dir>/AGENTS.md (generated from the

Arguments

  • dir — project directory (default: current directory)
FlagWhat it does
--checkreport drift/ghost tool names without writing (exit 1 when not current)
--printprint the generated section to stdout without writing
--file <path>guide file to write (default: <dir>/AGENTS.md)

bb mcp [options]

start the MCP server over stdio (for Claude Code, Cursor, VS Code…)

FlagWhat it does
--dir <dir>default project directory (default: cwd)

bb version [options]

print the bb version

Global flags, accepted by every command: -v, --version · --verbose · --quiet.

Daily diagnostics:

bb stats          # counts
bb status         # is an index running? what did the last run do?
bb health         # is the index healthy and fresh?
bb doctor         # is the embedding setup consistent?

Data, upgrades & uninstall.

Where the index lives, what an upgrade keeps, and how to clean up.

Where the index lives

One directory, keyed per project, outside your repository and outside the installed program:

~/.bb/projects/<project-id>/brain.db
The index: symbols, relationships, embeddings.
~/.bb/wasm
The parser cache.

The <project-id> is a sha1 of the project's absolute path, so two checkouts of the same repository at different paths have separate indexes. Override the whole location with BB_DATA_DIR — recommended where the home directory is not reliably writable or persistent (sandboxes, CI, editor hosts).

Upgrading keeps your data

New releases run idempotent schema migrations when they open the database: an upgraded bb either uses the existing index as it is or upgrades it in place — it never wipes it. To move to a new release, run npm install -g @backbencher/brain@latest (or re-run the installer, which does the same thing through npm); npm install -g @backbencher/brain@0.1.0 pins a specific release. There is no separate in-place upgrade subcommand.

Uninstall and reinstall

Uninstalling removes the program, not ~/.bb. Reinstall and every index, embedding and history entry is exactly where you left it. You start from zero only if the project moved to a different absolute path — then:

bb index --import /path/to/old-brain.db

adopts (re-homes) an existing index for the project at its current location. Moving a database between machines works the same way when the codebase fingerprint matches.

See and reclaim disk space

bb projects                  # every indexed project: DB path, size, counts, last index
bb projects --sort size      # biggest indexes first
bb projects --remove <id>    # delete one project's index + embeddings
bb stats                     # committed counts for the current project

Removing a project is the only operation that deletes an index. Nothing else in the CLI does, and no command sends your code or your index anywhere.

Troubleshooting.

Symptom-based fixes. Each one names a real command that resolves it.

Freshness

Search results look stale

Indexed results state their freshness. Reindex changed files, or re-run the derived phases without a full re-parse:

bb index --changed
# or, when only derived data (relationships, health) is stale:
bb index --post

Recovery

Repair a corrupted index

Wipes this project's index and rebuilds it in place. Your source files are never touched:

bb index --force

Interrupted run

An index run was interrupted

Check where the run stopped, then continue from its checkpoint:

bb status
bb index --resume

Embeddings

Semantic search is weak or unavailable

Without a configured embedding provider, semantic modes fall back to weaker local vectors. Check your setup and its consistency:

bb setup show
bb doctor

Configure a provider with bb setup. bb doctor --fix repairs file-permission problems only (0600 on the config) — it is explicit and changes nothing else.

Evidence

A tool reports missing or fresh=false data

Tool results carry a freshness block (fresh/stale/missing counts plus a remediation command). Run the remediation it names — usually bb index --changed or bb index --post:

bb health

Diagnostics

Verbose diagnostics

Show debug logs and per-file worker/WASM lines for any command; suppress informational output with --quiet:

bb --verbose stats
bb --quiet search createSession

Still stuck? Send the output of bb health and bb stats to support.

Upgrading keeps your data

To move to a new release, run npm install -g @backbencher/brain@latest — it replaces the installed package in place, leaves your index untouched, and there is no separate in-place upgrade subcommand. Details in Data, upgrades & uninstall.

Where to go next.

The guide stops where the references begin. These pages go deeper than a guide can.

Documentation is generated against the current CLI surface and verified by CI. Some safety and semantic features depend on index freshness, grammar availability, and an active language server.