The context and communication layer for coding agents.
basemind turns any repo into an always-current map of its code, documents, history, and memory —
so agents answer from structure and search instead of burning their context window on grep and
file reads — and gives a team of agents a while they work. One
server does both.
Full AI context layer over MCP — tree-sitter code-map, document RAG (PDF/Office/HTML/email + OCR + reranker), shared agent memory, on-demand web crawl, git history + blame + per-symbol diff. 300+ languages, 10+ coding-agent harnesses, content-addressed Fj
2026-11-13
Estrellas
—
Herramientas
—
Disponibilidad
—
shared channel to coordinate
Code map across 300+ languages · documents in 90+ formats · semantic + full-text search ·
git history & blame · shared memory · web crawl · agent-to-agent comms
basemind answers with file paths, line numbers, and signatures — not whole files — so a question
about your code costs a small fraction of the tokens it takes to read the source.
Capability
What it does
Key tools
Code intelligence
Read the code map instead of opening files: a file's structure (outline), find a definition by name (symbols), regex content search (grep), enumerate or fuzzy-find files (files · find, documents included), resolve a reference position to the definition it binds to (definition — scope- and import-aware, JS/TS via oxc, Python & Java via in-tree stack-graphs), every call site of a name (references, name-only) or of one specific definition (callers), implementors of a trait / interface / base class (implementations), the reverse import lookup (dependents), one symbol's raw body (expand), and search by meaning over indexed chunks (semantic → chunk, needs --features code-search). Layered over 300+ languages.
Walk the typed code-graph: who calls what and what a function reaches (calls), a symbol's n-hop blast radius (neighbors), the confidence-weighted shortest route between two symbols (path), a readable centrality-cut neighborhood (subgraph), the repo's de-facto modules (communities), and the whole-repo architecture ranked by PageRank + git churn with its dependency cycles (map). Render it as node-link JSON / DOT / Mermaid / GraphML / Cypher / offline interactive HTML / static SVG (export), show it to a human in their desktop viewer (display), or open the interactive UI at a live http://…/ui URL (open, which needs the daemon's opt-in HTTP front-end and otherwise falls back to a file:// export) — both take open: false to return the path or URL without launching anything. Every edge carries provenance + confidence; every result is deterministic and bounded.
Ask what changed recently, who last touched a function or a line, where the churn is, when a symbol's body actually changed, how a file's structure differs across commits, and full-text search commit authors + messages at full branch depth.
A per-repo memory agents write to and search by meaning — clones of the same repo share it, unrelated repos stay separate — plus semantic search over PDFs, Office files, HTML, email, and images (OCR included, no extra setup), and a review queue of notes mined from files that change together, which you approve before anything is kept.
Fetch a page or follow links from a starting URL; results join the document search above.
web (scrape · crawl · map)
Agent comms
Threads addressed by subject, path-glob, and members; scope discovery; inbox delivery; lifecycle status; and dry-run/apply retention cleanup.
agents (register · list · thread_start · thread_list · join · leave · members · add_member · remove_member · archive · post · history · message · inbox · ack · wait · cleanup · status)
Agent shells
Run headless terminal sessions in the background, capture recent retained output after commands exit, and explicitly stop sessions when their work is done. Visual terminal attachment is opt-in through [shells].visual.
Refresh the index after edits, check index health and repo identity, see what's been queried and how many tokens were saved, inspect or clean the on-disk cache, and shrink what an agent carries: a file's outline instead of its text, a diff instead of a re-read, a checkpoint instead of a transcript, plus a wasteful-tool-use report.
Machine-wide repo/worktree/branch coordination, backed by the daemon's always-on registry. Advisory claims let agent sessions avoid colliding on the same worktree.
Three ways to run basemind, easiest first. All three share the same local index and are safe to run
side by side.
The MCP plugin downloads the basemind program for you on first use. Pi, the MCP-server,
and CLI paths need it installed yourself — see Install the program.
1. As a plugin (recommended)
The curated plugin under plugin/ contains ten public skills and six commands for eleven runtime
profiles. See the plugin installation guide for local installation and release
prerequisites. The repository root also retains the existing OpenCode terminal adapter and Pi
extension; those integrations have separate package entry points.
Restart, then run /bm-statusline once to turn on the live statusline (a one-time step — see
Statusline). Turn on auto-update for the basemind marketplace
(Claude Code's plugin manager): the plugin then tracks each new release automatically, and the
launcher resolves the matching published release. Prefer to control timing? Update the
marketplace regularly by hand instead.
In the app: open the Plugins sidebar and add basemind. The CLI and IDE share one config file.
The generated plugin uses the matching published GitHub release, or a local BASEMIND_BIN override.
In Agent chat: /add-plugin basemind (once listed), or go to Dashboard → Settings → Plugins →
Team Marketplaces → Import from Repo and point it at https://github.com/Goldziher/basemind.
git clone https://github.com/Goldziher/basemind
cd basemind
gemini extensions install ./plugin --skip-settings
Update later with gemini extensions update basemind.
Kimi doesn't support the comms auto-notifications, but the chat tools still work.
Load the plugin/ directory as an Agent Plugins 1.0.0 package. It contains
plugin.json, mcp.json, and ten public skills. Copilot shares this portable layout. The MCP
launcher downloads the matching published basemind binary, or uses BASEMIND_BIN for a local build.
Install the program first. Install the locally generated wheel into the
same Python environment Hermes runs in, then enable the plugin:
Restart Hermes. The plugin registers ten skills, six slash commands, scoped comms notifications,
and basemind_call, which bridges the local MCP server's nine domains and returns JSON text.
The binary must be on PATH. Comms notifications are
best-effort. You can also configure mcp_servers.basemind with command: basemind and
args: [serve] for direct domain tools.
PyPI version 0.29.3 predates the skill-registration fix and MCP bridge. Use the source wheel above
until a newer release includes these changes; reinstalling that published version will not add them.
Antigravity uses a shared MCP config — install the program, then add the
generic MCP block. If you already use the Gemini extension,
agy plugin import gemini brings it across.
The package includes ten skills and a native extension that loads basemind context at session start
and after compaction. Pi runs basemind through its shell tool using the CLI.
No MCP bridge or binary is included. Add -l to save the package in the current project's configuration.
The next release adds these resources to the existing basemind-opencode npm package.
After that release, use pi install npm:basemind-opencode for registry installation and
Pi package-catalog discovery. Both installation paths carry the same extension and skills.
Public skills only. Install the ten public skills independently:
npx skills add Goldziher/basemind
Discovery uses the root skills/ mirror. Maintainer governance and private agents are not included.
For the curated Pi package's ten skills and six prompts, run pi install ./plugin from this checkout;
it carries no automatic context extension. The root Git package above retains the custom extension.
Local or development builds with the plugin. The launcher runs the release that matches the
plugin manifest. Set BASEMIND_BIN=/path/to/basemind to run your own build instead: it is honoured
whatever version it reports (the launcher logs a notice when that differs from the manifest's), and it
wins over BASEMIND_FORCE_VERSION. A build on a different release minor resets the cache on first open
(wipe and rebuild). BASEMIND_FORCE_VERSION=<x.y.z> pins the launcher to one published release
instead of the manifest's.
2. As an MCP server
If your tool speaks MCP but you're not using the plugin, install the program,
then register it:
Each tool has a title and says whether it only reads or can change things, so your client can
auto-approve the safe ones and ask before the rest. The server also exposes four on-demand MCP
resources whose bodies equal the matching tool result: basemind://status, basemind://repo/map,
basemind://outline/{path} and basemind://memory/{key}. If basemind isn't found, use the full path
from which basemind.
Claude Code — claude mcp add basemind -- basemind serve (add --scope user for all
projects; the -- is required). Or commit a .mcp.json at the repo root with the block above.
Cursor — put the block above in .cursor/mcp.json (project) or ~/.cursor/mcp.json (global).
Continue — .continue/mcpServers/basemind.yaml with command: basemind, args: [serve].
OpenCode (without the plugin) — opencode.json under key mcp, with command as an array
["basemind", "serve"].
Hermes — mcp_servers.basemind in ~/.hermes/config.yaml (YAML: command: basemind,
args: [serve]). For helper skills and notifications, install the source wheel and enable the
plugin as described in the Hermes installation section.
Any other tool — point it at the command basemind with the argument serve.
3. As a CLI
The standalone program, for scripts, headless runs, and CI. Install it, then:
basemind scan # index the project once
basemind code symbols "parseQuery" # find a definition by name
basemind code references "processFile" # find everywhere it's called
basemind git blame src/main.rs # who last changed each line
basemind watch # keep the index fresh as files change
The Homebrew / npm / pip / GitHub downloads include the full feature set — documents, OCR, search,
web crawl, shared memory, agent comms, and agent shells — so the first run downloads the models it
needs. The plain cargo install builds the code-map and git tools only: the one-shot CLI works, but
basemind serve relays to the daemon and so needs the comms feature (--features full has it).
Get started
After installing, run basemind init (CLI) — or /bm-init if your tool supports slash
commands — from the repo root. It's re-runnable and safe to call again later:
Writes a commented basemind.toml scaffold at the repo root, if one doesn't already exist.
Lets you pick which capabilities to advertise (interactive prompt in a TTY, or non-interactive
with --yes, --with <capability>, --without <capability>). Capability slugs:
code-search-navigation, code-mapping-architecture, git-history, file-finding, agent-comms,
worktree-coordination, documents-rag, semantic-search.
Injects a "prefer basemind over grep/read/git" rules block. By default it never writes a committed
file unasked: with .ai-rulez/config.toml present it writes the gitignored
.ai-rulez/local/rules/basemind-usage.md; otherwise a terminal run asks, defaulting to the
personal, gitignored CLAUDE.local.md, and a scripted run writes CLAUDE.local.md (or
AGENTS.local.md in a repo that has an AGENTS.md and no CLAUDE.md). It adds the file to
.gitignore. The block is delimited
(/) so re-running replaces it in place
instead of duplicating it.
Preview changes without writing with --print; skip the rules step with --no-rules; steer the
target explicitly with --rules-target <auto|claude|claude-local|agents|agents-local|ai-rulez|ai-rulez-local|none>
(the committed CLAUDE.md, AGENTS.md and .ai-rulez/rules/basemind-usage.md are explicit opt-ins).
--settings-target <local|shared|none> adds basemind's tools to Claude Code's auto-approved
permissions; a non-interactive run skips that unless you pass the flag.
Run /bm-statusline once. This is a one-time step because Claude Code doesn't let plugins set the
main statusline themselves — so basemind asks the assistant to make the one-line settings change on
your behalf, and it sticks from then on.
The dot is green when basemind is live and fresh, amber when idle, red when stale. The middle shows
activity by type, then tokens saved, then unread messages. Adjust with
BASEMIND_STATUSLINE=full|compact|minimal, or hide the top line with BASEMIND_STATUSLINE_CONTEXT=0.
Demos
How it works
basemind scan reads your project once, in parallel. It maps your code with
tree-sitter (across 300+ languages) and pulls text out of your documents with
xberg, then saves the result to a global cache under the XDG data directory, keyed by workspace —
nothing is written into your repo. After that, the background daemon keeps the map in memory (one
shared copy per workspace) and answers questions instantly — no re-reading the project for each one;
basemind serve is a thin stdio relay to it. When files change, it updates only what changed. The
daemon is the sole writer to that cache, so multiple sessions on the same repo (or on different
worktrees of it) all read and write concurrently instead of one falling back read-only. See
Global cache & the daemon below.
Navigation is scope- and import-aware for JavaScript/TypeScript, Python, and Java: basemind
resolves each use to the definition it actually binds to, so a shadowed local isn't confused with an
import and code mode definition lands on the right target (including across files for imports). Every
other language still gets fast tree-sitter scope binding. Precise Python/Java resolution runs GitHub
stack-graphs-style .tsg name-binding rules via an in-tree engine (crates/), with no per-language
LSP server.
Resolution refines, but never shrinks, a result set.code mode callers reports every call site
whose callee matches the name — the same sound floor mode references uses — and marks each hit resolved
when resolution proved it binds to that definition (resolved_total counts them). It deliberately
does not return only the resolved subset: resolution cannot see through a module-object import
(from pkg import mod then mod.f()) or an unresolvable path alias, so filtering to it would drop
real callers and report the remainder as complete. Filter on resolved when you want precision; trust
total when you need completeness.
The code map is code only. Prose, data and config files — Markdown, reStructuredText, AsciiDoc,
vimdoc, CSV, JSON, YAML, TOML, INI, XML, .properties, .env, diffs, .gitignore/.gitattributes
and Fluent — go to the document tier instead: they are chunked and searched as text with memory
mode documents (gated by [documents] include / exclude), and no longer show up as symbols in
code modes outline, symbols and grep. files and find still cover them, labelled by
grammar name or extension. An existing index migrates on its next scan. A build
without the documents feature keeps the old behaviour, where those files are outlined as code.
flowchart LR
A(["Coding agent"])
R["Your project<br/>code · documents · git"]
S["basemind scan<br/>map code & read documents"]
D[("Global cache<br/>per-OS data dir")]
V["basemind serve<br/>answers questions"]
R --> S --> D --> V
A <-->|asks questions| V
classDef accent fill:#2563eb,stroke:#1e40af,color:#fff
class S,V accent
Search and memory are powered by a vector store (LanceDB).
The daemon answers the MCP handshake immediately and warms the code map into memory in the
background, so a client never blocks waiting for a large repo to load. The status tool reports
warming (still loading) and, once done, warm_ms; a first-time index build similarly reports
indexing / index_build_ms.
While the server isn't fully ready, status and every code-map read tool may carry a notice
object — { state, message, retry } — instead of (or alongside) their normal result:
state
Meaning
retry
warming_up
Loading an existing index into memory.
true
building_index
Indexing from scratch (no cache entry for this workspace yet).
true
rescanning
Incremental rescan after a file change; current results are usable but may be stale.
false
Treat an empty or partial result carrying a notice as "retry shortly," not "no matches" — poll
status (or just retry the call) until the notice clears.
Index state lives under a single global cache — ~/.local/share/basemind/ on Linux,
~/Library/Application Support/basemind/ on macOS (override with BASEMIND_DATA_HOME) — keyed by
workspace, never inside your repo. The
content-addressed blob store is machine-wide too: identical file content scanned from different repos
or worktrees is extracted and stored once.
A new linked worktree's working view is seeded from a sibling checkout's index with a copy-on-write
clone, so its first scan only touches files that differ. Only the view is cloned: the vector store is
not, so the seeded worktree's first scan rebuilds its vector rows from the cached blobs without
re-embedding. A sibling whose workspace lock is held (a daemon or another scan is writing it) is not a
seed source, and neither is one too large to copy on a filesystem without reflinks; the new worktree
then scans from scratch. Set BASEMIND_NO_SEED=1 (any non-empty value other than 0) to opt out.
Linked worktrees share one git-history index per clone. A worktree whose HEAD descends from the
indexed head appends the new commits; one that diverges leaves the index alone and answers history
queries by walking git directly (correct, just slower), rather than wiping and rebuilding it on every
worktree switch. The first build may come from any worktree.
Memory is bounded by design:
[resources] max_footprint_mb (auto by default) is a best-effort ceiling on the process footprint.
The scan processes files in bounded chunks and pauses between them while over the ceiling; if it
is still over after five seconds it halves its chunk size and worker count and carries on, then
widens again once memory clears. A large-file parse is likewise admitted anyway after five seconds.
Document extraction is admitted exclusively: over the ceiling exactly one document runs at a time
(an otherwise idle process is admitted immediately), and a document whose header-derived
working-set estimate exceeds the whole ceiling is skipped and counted as too large.
ONNX Runtime runs on the CPU provider by default (onnx_provider = "cpu"): on macOS the platform
default, CoreML, measured 7.6 GB resident after embedding one 2 KB SVG against 0.8 GB on CPU. In
every basemind process ONNX has no memory-pattern planning and no retained CPU arena, which
otherwise grow to the largest batch seen and never shrink. Intra-op threads are the auto
embed-thread count (max(2, logical CPUs / 4)), or 2 in the daemon, which also drops its resident
embedding models once the last concurrent embedding pass ends; the next pass reloads them.
Precise Python/Java resolution abandons a file past 600,000 builder steps, 4,096 stitching phases
(about a million path extensions), 50,000 partial paths or 3 seconds, and runs at most two
stack-graph builds at once. The stitcher checks those budgets every 256 path extensions, not once
per phase, so a pathological file cannot grow between checks.
On macOS the allocator (mimalloc) heap is tagged as application memory (Mach VM tag 254), so
footprint, vmmap and Activity Monitor no longer report it as IOAccelerator "GPU" memory.
A workspace root must be a project: a git repository, or a directory containing a basemind config
(basemind.toml at the root, or under the .config/ convention). Anything else is refused, because
basemind opens a root read-write and indexes every file beneath
it — so an accidentally inherited root (/, your home directory, or wherever an MCP host happened
to start) would become a whole-filesystem scan. Run basemind init to mark a directory you do want
indexed, or set BASEMIND_ALLOW_ANY_ROOT=1 to skip the check. A filesystem or volume root is
refused unconditionally and cannot be overridden.
A single background daemon per machine is the sole writer to that cache and hosts the MCP server:
basemind serve is a thin stdio relay that ensures the daemon is up and pumps bytes to it, so N
sessions on the same repo — or on different worktrees of it — share one read stack per workspace
and all read and write concurrently instead of a second session silently falling back to a stale,
read-only view. The daemon holds the single-writer index, so references, callers and
implementations run inside it and return complete results with no per-session copy. The daemon
also keeps a cheap, always-on registry of repos, worktrees, and branches (workspace modes
workspaces / worktrees / branches), and modes claim / release give agent sessions an
advisory way to avoid colliding on the same worktree.
basemind statusline queries the daemon for the workspaces currently active and prints a compact
line for your shell prompt; it prints nothing when no daemon is running.
The daemon is started on demand, detached with setsid(2). That changes the session and the process
group but not the cgroup, so on Linux an auto-spawned daemon lives in the cgroup of whatever
shell or editor happened to start it — outside any MemoryMax you configured for basemind. No code
in basemind can change that; a process cannot move its own children into a cgroup it does not
control. If you want an enforced memory ceiling, your unit has to be the thing that starts the
daemon: set BASEMIND_NO_AUTOSPAWN=1 everywhere (basemind then connects to a running daemon but
never starts one; basemind comms start deliberately still does) and install the ready-made user
unit at docs/systemd/basemind-comms.service, which also
lists the two commands that verify the ceiling is real rather than merely configured.
The daemon can additionally serve MCP over streamable HTTP on loopback, but that front-end is
opt-in: it binds only when BASEMIND_ALLOW_HTTP is truthy in the daemon's environment, and every
request must then present the bearer token published as the second line of <comms_dir>/http.addr
(mode 0600). Plugin manifests and the CLI use the stdio transport and need none of this.
A single shared service in the background lets agents talk to each other — even across different
tools and different repos on the same machine. Agents coordinate in threads — each addressed by
at least two of subject / path-glob / members, discovered by scope rather than joined globally — and
each has a personal inbox. Messages come in two parts: a short headline (subject and sender)
that's cheap to skim, and the full body, fetched only when an agent wants to read it. An agent never
sees its own posts in its inbox. Idle threads auto-archive. wait blocks for 30 seconds by default
(at most 40) and ends early when the client cancels the request.
The client–daemon protocol is version 4: the daemon serves it on an 8-worker async runtime, and
every request carries an id, so replies are matched to
requests and most calls have a deadline (BASEMIND_COMMS_REQUEST_TIMEOUT_SECS, 10 s;
BASEMIND_COMMS_HANDSHAKE_TIMEOUT_SECS, 30 s). After an upgrade, run basemind comms stop so the
old daemon is replaced. A post can carry an idempotency_key: a retry with the same key returns the
original message id instead of storing a duplicate (keys are remembered for an hour, and generated when
omitted). The stdio relay replays read-only requests and keyed posts once if the daemon restarts
underneath it, instead of failing the call, and fails a request that outlives
BASEMIND_RELAY_REQUEST_TIMEOUT_SECS (180 s). Other tool responses carry a short notice when you have
unread messages. A detached daemon logs to a size-rotated <comms_dir>/daemon.log, which
basemind comms doctor shows.
The plugin makes sure agents notice messages without being asked — through the built-in instructions,
a notice at session start and each turn, and a quiet background check every few seconds.
flowchart LR
A["Agent A<br/>Claude Code · repo X"]
B["Agent B<br/>Cursor · repo Y"]
BR["Shared comms service<br/>threads · inboxes"]
A <-->|post · read| BR
B <-->|post · read| BR
classDef accent fill:#2563eb,stroke:#1e40af,color:#fff
class BR accent
Included in every prebuilt download (and in cargo install --features shells / full): agents can
open terminal sessions in the background, type into them, and read what's on screen — no extra tools
to install. Sessions can be fully headless, or opened in a real terminal tab or window so you can
watch along. A spawned session and the agent that started it can message each other over comms.
Token saving
The plugin nudges agents toward the cheap path by default:
Get a file's outline before opening it — then read only the part you need.
Search for a definition instead of grepping for it.
Look up who calls a function instead of grepping for call sites.
Refresh the index after edits instead of restarting the server.
Don't re-read a file basemind already mapped.
Optional guardrails enforce this at the moment a tool is used:
Guard — gently redirects grep-style searches to the matching basemind tool. On by default;
set BASEMIND_GUARD=off to disable, or redirect to block instead of nudge.
Output compressor — BASEMIND_COMPRESS_OUTPUT=1 shrinks long command output. It never touches
anything that looks like a credential and leaves output alone if it can't help.
Re-read shortcut — BASEMIND_DELTA_READS=1 shows just what changed when an agent re-reads a
file it already read this session.
basemind shrinks code by keeping the shape and dropping the bodies — function signatures and imports
stay, the implementations go — because a signature is useless without its shape. For prose it does a
light cleanup (extra whitespace, filler, repeated paragraphs). It reports honest before/after token
counts, and the code version is exact — nothing is lost, just set aside. expand brings any one
function's full body back when an agent actually needs it: compress to an outline, expand only what
you need.
basemind admin eval runs a task file of lookups through the same code the MCP tools use, scores
each answer against gold generated from your repository (precision/recall, hit@k, MRR, nDCG),
records latency and response tokens, and compares the token cost with the grep-and-read baseline
an agent would otherwise pay. Savings only count when basemind's answer was actually correct, and
the report flags any mode whose measured ratio deviates from the dashboard's fixed multiplier.
--baseline <report.json> turns it into a regression gate. Gold generators and the workflow are in
benchmarks/eval/; measured savings, including the cases where grep is
cheaper for a single narrow hit, are in benchmarks/README.md.
Performance
Measured on an Apple M4 (10 cores — 4 performance + 6 efficiency, 16 GB, macOS 26) with the
hardening harness (scripts/harden.sh), which clones each upstream repo fresh and scans its code
map. Warm, steady-state numbers; the first scan of a cold project is slower.
Project
Files
Languages
Scan time
gin
130
Go
0.1 s
requests
128
Python
0.1 s
ripgrep
221
Rust
0.6 s
tokio
861
Rust
0.4 s
react
7 242
TS / JSX
2.0 s
django
7 065
Python
2.4 s
TypeScript compiler
81 324
TS / JS / JSON
18 s
The TypeScript compiler is the worst case — 81k files in about 18 seconds. Re-scans only look at
what changed, so keeping a project up to date is far faster than the first scan.
Once running, code questions answer from memory rather than from disk each time — in milliseconds
even on a very large repository (next section).
Measured with the built-in harness (basemind admin eval --warmup, see
Measure it on your own repo) on a 74k-file, ~350 MB monorepo checkout, 60 tasks per
mode, in-process (no transport or process start-up). Gold is generated from the repository itself;
benchmarks/eval/README.md states what each mode's gold encodes.
code / git / memory mode
p50
p95
precision
recall
outline
1.0 ms
2.2 ms
1.00
1.00
references
1.4 ms
6.0 ms
0.81
1.00
symbols
3.7 ms
5.3 ms
0.97
1.00
dependents
4.0 ms
5.6 ms
0.84
1.00
callers
4.6 ms
10.4 ms
0.87
1.00
find (ranked, hit@1 0.72)
6.6 ms
9.0 ms
0.29
0.75
gitsearch (ranked, hit@1 1.00)
55 ms
96 ms
1.00
0.91
memorydocuments (hit@1 0.48, hit@5 0.63)
106 ms
260 ms
0.18
0.63
grep (15 tasks, trigram prefilter)
~130 ms
190–270 ms
0.91
1.00
symbols and dependents answer from a resident term index, and references, callers and
implementations from a resident dictionary of distinct callee and trait names, which is why they
sit in the millisecond range instead of walking every call site. grep skips files a per-file
trigram bloom filter proves cannot match (index cost ≈ 12.8 % of the indexed code bytes; results are
identical to the full sweep, which took 3.6–7.8 s p50 on the same tasks; see
ADR-0012). Set BASEMIND_GREP_BLOOM=0 to force the full
sweep. Numbers vary with hardware and load; rerun the harness on your repository.
basemind precomputes a per-repo git-history index (path → commit posting lists, stored newest-first)
so the history modes — touching, recent, churn, by_path, and symbol_history's commit walk
— are posting-list lookups. Warm in-process query latency on the same M4:
Repo
Commits
gittouching
gitrecent
index build
index size
django
2 000
39 µs
15 µs
0.5 s
1.7 MB (6 % of .git)
tokio
3 984
37 µs
13 µs
0.9 s
2.1 MB (12 %)
requests
6 480
38 µs
15 µs
1.0 s
1.9 MB (14 %)
TypeScript
2 000
37 µs
13 µs
3.2 s
30 MB (12 %)
History queries answer in tens of microseconds, flat across history depth, because the
newest-first posting lists decode only the commits a query returns. The index builds in well under a
second to a few seconds and costs 6–22 % of .git on disk.
It is a pure accelerator: the tools use it only when it is fresh (last_indexed_head == HEAD) and
otherwise walk history directly, so it can never serve stale results — and it rebuilds automatically
when history is rewritten (filter-repo / rebase / force-push). Reproduce with
cargo bench --bench git_history or the git-ops block in scripts/harden.sh.
Every latency-relevant mode — all of code and graph, all of git, the admin read modes, and
the document / memory search modes — reports its own latency as elapsed_us on its response.
Don't wrap the CLI in time; ask basemind.
Resolution is microseconds on purpose: an indexed git mode touching is ~37 µs, so
millisecond granularity would round the hot path to 0.
What elapsed_us includes — the tool body's own execution: index and store lookups, git walks,
ranking, and building the response.
What it excludes — MCP / JSON-RPC transport (which the server cannot observe), argument
deserialization, and serialization of the response itself. Excluding encoding keeps the number
comparable across format: "json" and format: "toon" and across result-set sizes: it reports
query cost, not encoding cost.
The one caveat, stated plainly: most read tools begin by awaiting the in-RAM code map, and the
git tools lazily build their history index on first use. Both waits happen inside the measured
region, so a first call against a cold server is much slower than the steady-state call after it.
When the server is still warming or building, the response carries a notice
(warming_up / building_index / rescanning) — discard any sample carrying a notice if you
are measuring steady-state latency.
The CLI adds a second number, startup_us, covering process startup: clap parsing, the tokio runtime,
the store open, and the config/git-cache load. It is reported separately because it is exactly the
part of a time basemind … measurement that was never the query — and a long-running MCP server pays
it once at boot, not per call:
$ basemind code symbols run_workspace_grep --limit 1 --json
{
...
"elapsed_us": 90, # the query
"startup_us": 957887 # everything else a `time` wrapper would have charged to it
}
$ basemind code references parse_kind --limit 3
...
(6.5 ms query · 852.9 ms startup) # stderr: stdout carries only the answer
That first example is the whole point: the query took 90 µs, while the process spent ~0.96 s getting
ready to run it. A time basemind … wrapper would have reported the second number and told you
nothing about the first.
Configuration
The config lives at the repo root as basemind.toml (committed). The cache it drives is derived
state — held in the global cache under the XDG data directory, wiped and rebuilt on schema bumps —
so config never belongs there and nothing basemind-owned is written into your repo. Run
basemind init to drop a fully-commented scaffold (documenting every option) at the root. It can
also live under the project-level .config/ convention —
.config/basemind.toml or .config/basemind/config.toml — which is auto-discovered read-only; the
root basemind.toml still wins when both exist. basemind init --config-dir .config (or
--config-dir .config/basemind) scaffolds the convention. The legacy in-cache path
(.basemind/basemind.toml, from before the global-cache move) is still read as a fallback for older
checkouts. The full schema is at schema/basemind-config-v1.schema.json:
# basemind.toml (repo root — commit this)
"$schema" = "v1"
[scan]
respect_gitignore = true
# Follow symlinks during the walk. Off by default — symlinks often escape the repo (e.g. Bazel's
# bazel-* convenience symlinks). Turn on for repos that symlink real source into place. Ignored
# (forced false) in a repository's own file unless the operator sets BASEMIND_ALLOW_FOLLOW_SYMLINKS=1.
follow_symlinks = false
# Glob syntax (include / exclude here, and every include / exclude / embed_* list below): paths are
# repo-relative with forward slashes, matching is case-sensitive, and `*` also crosses `/` (so
# `src/*.rs` matches `src/a/b.rs`). A pattern with no glob characters is gitignore-like: `generated`
# matches every path segment of that name at any depth and everything beneath it; `docs/api` is
# anchored at the root. Exclude beats include. An invalid glob, a negated (`!`) pattern, or an empty
# `include` (it would index nothing) is a config error. For `extra_roots` files the globs are
# matched against the path relative to that root.
include = ["**/*"]
# `exclude` is ADDED ON TOP of an always-on floor (node_modules, target, dist, build, out, .venv,
# venv, __pycache__, *.pyc, .pytest_cache/.mypy_cache/.ruff_cache/.tox, .next/.nuxt/.svelte-kit,
# vendor, .gradle, .terraform, coverage, bazel-*, .git, .basemind, .idea, .DS_Store) and of a
# credential floor, so a secret never becomes searchable by every agent that can query the index:
# .env and .env.*, .aws/, .ssh/, .gnupg/, .npmrc, .pypirc, .netrc, .git-credentials, id_rsa /
# id_dsa / id_ecdsa / id_ed25519, *.pem, *.key, *.p12, *.pfx, *.jks, *.keystore. Note `.env.*` also
# drops `.env.example`; list `.env.*` in floor_allow to index those templates (needs the
# BASEMIND_ALLOW_REPO_CREDENTIALS grant below).
exclude = []
# Remove entries from that floor so the tree is indexed, by directory name (`build`), file name or
# glob (`.env.*`, `*.pem`) or floor pattern (`**/build/**`). `.git` and `.basemind` can never be
# allowed; an entry naming nothing is ignored with a warning. A credential entry (`.env`, `*.pem`,
# keys) is honoured only with BASEMIND_ALLOW_REPO_CREDENTIALS=1 in the environment — a repository's
# own file cannot un-exclude your secrets. The default `exclude` separately lists
# dist/target/node_modules/.venv/bazel-*, so drop those from `exclude` too when allowing them.
floor_allow = []
# Index directories outside the repo root too — e.g. a Bazel external repo cache — so their
# symbols resolve in search / references / outlines. External files are keyed by absolute path;
# (re-)indexed on a full `basemind scan` only (not live-watched). Requires the operator to set
# BASEMIND_ALLOW_EXTRA_ROOTS in the environment: this file lives inside the repository, so
# without that opt-in a cloned repo could point basemind at your ~/.ssh. Even with the grant, a root
# under .ssh / .aws / .gnupg or /etc, a filesystem root, and a root inside the repo are skipped.
# Extra roots count toward max_candidates and follow symlinks only when follow_symlinks is on.
extra_roots = ["/private/var/tmp/_bazel_you/abc123/external"]
# Ceiling on how many candidate files one scan may keep, across the repo walk and every extra root.
# Exceeding it aborts before any extraction or index write, and the error names the heaviest
# contributing directories — so a vendored tree that slipped past .gitignore is a one-line fix
# instead of an out-of-memory kill. It also bounds how far the walk may travel to find them. It does
# NOT bound bytes read or index size, and does not apply to `--staged` / `--rev` (those enumerate
# from git, not from a walk). 0 disables both bounds.
max_candidates = 500_000
# Per-grammar overrides, keyed by tree-sitter-language-pack grammar name (see `basemind lang list`;
# an unknown key is a config error that suggests near matches).
[languages.vimdoc]
# false stops parsing that grammar's files as code (fixes misdetections: `.txt` is vimdoc, `.conf`
# is nginx). They are then handled like any unrecognised file: routed to the document tier, where
# `[documents] exclude` can drop them entirely. Already-indexed files are removed on the next scan.
enabled = false
[languages.jinja2]
# Map extra suffixes (leading dot optional, case-insensitive, compound allowed) and exact file
# names onto the grammar. Overrides beat built-in detection; a filename beats an extension.
extensions = [".mako", ".tpl"]
filenames = ["BUILD.in"]
# `basemind lang install` also fetches this grammar (otherwise only the languages basemind ships
# queries for are pre-fetched and the rest download on first use).
preload = true
[code_intel]
# Precise, scope- and import-aware resolution (JS/TS via oxc; Python/Java via stack-graphs). On by
# default. Set false to fall back to fast tree-sitter locals binding for every language. Applies to
# files (re)scanned after the change.
precise_resolution = true
[documents]
enabled = true
# Embed documents for semantic search (ON — embeddings pay off on real prose / OCR).
embed = true
# Model preset: fast | balanced (default, 768-dim) | quality | multilingual.
# Changing the preset forces a FULL RE-EMBED of the corpus (time + CPU): every document is
# re-encoded at the new model's dimension.
embedding_preset = "balanced"
# Which non-code files become documents. Prose, data and config files (markdown, rst, json, yaml,
# toml, xml, csv, ini, ...) are NOT in the code map; they are documents and are gated here. Default
# (empty include) is everything that passes [scan]; exclude applies to document indexing itself and
# beats include (same glob syntax as [scan]).
# The default `exclude` drops low-value bulk: SVG icon/vector assets, lockfiles and test-data
# directories (removing an entry re-indexes it). Setting the key REPLACES that list (it is not
# merged): `exclude = []` indexes all of them, and a custom list must repeat any default entry you
# still want.
include = []
exclude = [
"*.svg", "pnpm-lock.yaml", "package-lock.json", "yarn.lock", "Cargo.lock", "poetry.lock", "*.lock",
"**/test_data/**", "**/testdata/**", "**/fixtures/**", "**/__snapshots__/**",
]
# Per-document size cap in bytes, independent of [scan] max_file_bytes (which caps source files), so
# large PDFs / Office files are still extracted. Files over it are skipped and counted as too large
# in the scan summary.
max_file_bytes = 52428800
# Backstop against pathological chunking cost: structured data (json, yaml, xml, svg, csv) is always
# chunked linearly, and other text-like documents over these sizes (bytes, minimum
# 1024) are chunked by a linear fixed-size chunker instead and counted as `docs_degraded` in the scan summary.
# PDFs / Office files are never affected. text/plain (.txt, .log) has no markup to exploit, so its
# cutover is lower.
# A text-like file that xberg rejects (Helm template named .yaml, huge CSV, SVG with a huge entity) is also read as
# text/plain through this chunker and counted as `docs_text_fallback`.
markdown_chunk_max_bytes = 1048576
plain_text_chunk_max_bytes = 4194304
# Wall-clock budget (seconds) for one document's extraction + chunking. A document that overruns is
# abandoned, skipped, and counted as `doc_timeouts`. It is remembered by content hash and not retried
# while the file and these limits (this value, the two cutovers above, max_pages) are unchanged; editing
# the file or changing a limit retries it.
extraction_timeout_secs = 120
# Wall-clock budget (seconds) for the whole document phase of one scan, started at the first document
# that needs a real extraction (never below extraction_timeout_secs). Once spent, the remaining
# documents are deferred (counted as `docs_deferred`, not failed) and picked up by the next scan.
phase_budget_secs = 1800
# A timed-out extraction cannot be cancelled and keeps a core busy until it finishes. At this many
# still-running abandoned extractions (1 to 64), further documents are deferred instead of spawning
# another thread. A soft bound; the live count shows as `abandoned_extractions` in the scan summary.
max_abandoned_extractions = 4
# Extra extensions to skip on top of the built-in archive/binary floor (case-insensitive; ".pdf" and
# "pdf" are the same).
extension_denylist = []
# Embedding scope: with a non-empty embed_include only matching documents are embedded; embed_exclude
# always wins. Left-out documents stay extracted + keyword-searchable. Editing either (or `embed`)
# deletes the vector rows of documents that stop being eligible on the next scan.
embed_include = []
embed_exclude = []
# Route archives (.zip/.tar/.jar/…) into the recursive extractor. Off by default so one archive
# can't explode into thousands of embeds; true binaries are always skipped.
extract_archives = false
[code_search]
enabled = true
# Vector embeddings for code are OFF by default — a general English model on code isn't worth the
# cost, and NL→symbol is already served by the BM25 keyword lane. Chunking + keyword search work
# regardless. Turn on only for vector search over code (downloads an ONNX model, re-embeds on
# preset change).
embed = false
# Same semantics as the [documents] pair: allow-list, with embed_exclude winning. Files left out are
# still chunked and keyword-searchable; newly ineligible files lose their vector rows on the next scan.
embed_include = []
embed_exclude = []
# Cap on chunks indexed per source file. A generated parser table or a checked-in bundle otherwise
# fans one file out into a chunk count bounded only by max_file_bytes, and every chunk costs a
# keyword posting, a vector row, and (with embed on) an embed. Over-cap files are still chunked and
# cached — outline and grep are unaffected — they just contribute no postings and no vector rows.
max_chunks_per_file = 2000
[resources]
# Memory ceiling for this process, in MiB. A positive integer is an explicit ceiling; 0 or "auto"
# (the default) derives one — 75% of an enforced cgroup limit, or 25% of machine RAM, floored at
# 2048 MiB; "off" disables it. ADVISORY: workers park while over the ceiling and are admitted anyway
# after five seconds, so it shapes peak memory rather than enforcing a hard limit (document
# extraction is stricter: over the ceiling one document runs at a time). To actually cap the
# daemon's memory, run it from your own resource-controlled unit — see
# `docs/systemd/basemind-comms.service`.
max_footprint_mb = "auto"
# Byte budget (MiB) for the MCP read stack's decoded-outline cache, per workspace. 0 = unbounded.
# A miss costs one blob read and never changes an answer.
max_map_cache_mb = 256
# ONNX Runtime execution provider for embeddings, reranking, layout detection and NER: cpu (default)
# | auto | coreml | cuda | tensorrt. `auto` restores the platform default (CoreML on macOS), which
# measured 7.6 GB resident for one tiny document against 0.8 GB on cpu.
onnx_provider = "cpu"
Overrides. Only the documents.* and llm.* keys can be overridden, by a CLI flag or its
environment variable (each flag's name is in --help; the variable is the flag upper-cased with a
BASEMIND_ prefix and underscores, e.g. --llm-model is BASEMIND_LLM_MODEL, --documents-overlap
is BASEMIND_DOCUMENTS_OVERLAP). Every other setting is file-only. Overrides apply to the CLI
command they are passed to (the MCP tools do not accept them); a daemon-hosted scan or read
stack loads only the file (plus the daemon caps below), so set those keys in basemind.toml for
daemon workloads. Overrides are validated after merging, so an override cannot smuggle in a value
the file would be rejected for (documents.max_characters under 64, overlap >= max_characters,
language.min_confidence outside 0..1).
Trust boundary.basemind.toml is authored by the repository, not by you, so settings that
reach outside the process are gated on the operator's environment:
Setting in the repo's file
Honoured only when
[llm] base_url
BASEMIND_ALLOW_REPO_LLM=1; otherwise ignored with a warning (a clone could aim it at a host that collects your API key and document text). Pass it by --llm-base-url / BASEMIND_LLM_BASE_URL instead.
[llm] api_key = { env = "NAME" }
NAME is the chosen provider's standard variable (OPENAI_API_KEY for openai/..., ANTHROPIC_API_KEY for anthropic/..., ...) or BASEMIND_LLM_API_KEY, or BASEMIND_ALLOW_REPO_LLM=1.
[crawl] allow_private_network = true
BASEMIND_ALLOW_PRIVATE_HOSTS=1; otherwise reset to false with a warning. The same variable governs the URL guard for web fetches.
[scan] follow_symlinks = true
BASEMIND_ALLOW_FOLLOW_SYMLINKS=1; otherwise reset to false with a warning (a tracked link can point at ~/.ssh).
[scan] floor_allow (a credential entry: .env, *.pem, id_rsa, ...)
BASEMIND_ALLOW_REPO_CREDENTIALS=1; otherwise the entry is ignored with a warning and the secret stays excluded (a clone could otherwise un-exclude your untracked .env and have every agent query it). Entries for build artifacts (build, vendor) need no grant.
[scan] extra_roots
BASEMIND_ALLOW_EXTRA_ROOTS=1 (every workspace this process scans) or a list of absolute workspace roots separated by : (; on Windows), which grants only those workspaces and their descendants. A relative entry is ignored with a warning, as is any other non-truthy word (on). A daemon is one long-lived process serving many repositories, so prefer the list form there: the bare 1 also opens extra_roots for any workspace it serves later. Credential directories (.ssh, .aws, .gnupg, /etc) and filesystem roots are refused even with the grant.
[documents] extract_archives = true
In the daemon only: BASEMIND_DAEMON_ALLOW_EXTRACT_ARCHIVES=1 in the daemon's environment; otherwise reset to false with a warning.
Grant variables accept 1, true or yes (case-insensitive). They are read from the process
environment; the env and CLI override layers are operator-supplied and never gated.
Credential and key files are not indexed by default: the exclude floor (see [scan] above) drops
.env, .env.* (which includes .env.example), .aws/, .ssh/, .gnupg/, .npmrc, .pypirc,
.netrc, .git-credentials, SSH private keys and *.pem / *.key / *.p12 / *.pfx / *.jks /
*.keystore. Opt a file class back in with [scan] floor_allow = [".env.*"] — a credential entry
only takes effect with the operator's BASEMIND_ALLOW_REPO_CREDENTIALS=1 grant, so a repository's
own file cannot un-exclude it. Unless
follow_symlinks is granted, working-tree reads (including the watcher and rescan paths) refuse a
symlinked file or a path that resolves outside the workspace, and a basemind.toml that is a symlink
leaving the workspace is not followed.
The daemon treats [resources] and [scan] max_candidates as ceilings. The effective value is
the smaller of the file's and the daemon's cap; the [resources] sentinels 0 / "auto" / "off"
resolve to the cap. The operator raises a cap in the daemon's own environment (a repository cannot):
Variable
Caps
Default
BASEMIND_DAEMON_MAX_SCAN_THREADS
scan_threads
4
BASEMIND_DAEMON_MAX_EMBED_THREADS
embed_threads
4
BASEMIND_DAEMON_MAX_EMBED_BATCH
embed_batch_size
8
BASEMIND_DAEMON_MAX_CONCURRENT_DOCUMENTS
max_concurrent_documents
4
BASEMIND_DAEMON_MAX_FOOTPRINT_MB
max_footprint_mb
3072
BASEMIND_DAEMON_MAX_MAP_CACHE_MB
max_map_cache_mb
1024
BASEMIND_DAEMON_MAX_CANDIDATES
[scan] max_candidates
2000000
BASEMIND_DAEMON_MAX_FILE_BYTES
[scan] max_file_bytes
67108864 (64 MiB)
BASEMIND_DAEMON_MAX_DOCUMENT_BYTES
[documents] max_file_bytes
536870912 (512 MiB)
BASEMIND_DAEMON_MAX_DOCUMENT_PAGES
[documents] max_pages
5000
BASEMIND_DAEMON_MAX_EXTRACTION_SECS
[documents] extraction_timeout_secs
1800
BASEMIND_DAEMON_MAX_CHUNKS_PER_DOCUMENT
[documents] max_chunks_per_document
20000
BASEMIND_DAEMON_MAX_CRAWL_PAGES
[crawl] max_pages, and the per-call webcrawl override
500
BASEMIND_DAEMON_MAX_CRAWL_DEPTH
[crawl] max_depth, and the per-call override
8
BASEMIND_DAEMON_MAX_CRAWL_BODY_BYTES
[crawl] max_body_size
67108864 (64 MiB)
BASEMIND_DAEMON_MIN_DEBOUNCE_MS
floor for [watch] debounce_ms (a minimum, not a ceiling)
50
A cap variable must be a positive integer; anything else falls back to the default.
Other operator variables.
Variable
Effect
BASEMIND_DATA_HOME
Root of the machine-global cache (default: the XDG data directory).
BASEMIND_GREP_BLOOM=0
Force code grep to sweep every file instead of using the per-file trigram bloom prefilter.
BASEMIND_BLOB_GC_GRACE_SECS
Age (seconds) below which the blob sweep keeps a blob; default 6 hours.
BASEMIND_WARM_READ_STACKS
Daemon-hosted read stacks kept warm at once; default 3.
BASEMIND_NO_AUTOSPAWN=1
Connect to a running daemon but never start one.
BASEMIND_MAX_DAEMONS
Ceiling on live daemons per machine before a spawn is refused; default 8.
BASEMIND_NO_SEED=1
Do not seed a new worktree's index from a sibling checkout.
BASEMIND_BIN, BASEMIND_FORCE_VERSION
Plugin launcher: run a local build / pin a release (see Installation).
Reload. The daemon re-reads a workspace's basemind.toml on the next request after it changes
(size or modification time) and logs config changed. A file that no longer parses keeps the last
good config and logs a warning. A hosted read stack with live sessions keeps its config until they
reconnect, and scan_threads is fixed for the process lifetime (the daemon logs that a restart is
required). admin status reports config_stamp (<bytes>B@<unix seconds>) to spot an edit.
Reserved keys. These parse but nothing reads them yet, and setting one to a non-default value
logs a warning: [watch] live_l2, [cache] file_map_lru, [mcp] transport, [memory] enabled /
scope_strategy / default_visibility, [comms] enabled / idle_timeout_secs /
max_messages_per_room / retention_secs / max_rooms / workspace_root, [shells] keep_on_exit,
[documents.ocr] backend / languages, and [documents.language] preferred_languages.
Config changes take effect on the next scan. Cached chunks and documents carry a fingerprint of
the settings that shape them ([code_search]max_characters / overlap / max_chunks_per_file;
[documents] chunk size, page cap, language detection, keywords, NER, summarization, extract_archives,
[resources] document_models and [llm] model), so changing one re-chunks or re-extracts only the
affected files. Embedding scope (embed, embed_include, embed_exclude, and the enabled switches)
is reconciled too: the first scan after a change deletes the vector rows of files that are no longer
eligible (and, when [code_search] enabled = false, their keyword postings) and rebuilds the rows of
files that became eligible from the cached blobs, without re-embedding.
CLI reference
Every MCP tool mode maps to a CLI command, or is declared CLI-only / MCP-only with a reason (enforced
by tests/cli_parity/). Add --json for
machine-readable output (the same response types the MCP tools return, including agents and
workspace). Human output prints source bodies, diffs and exports in full; only table cells are cut
(to 200 characters, with a note on stderr), and the timing line goes to stderr. List commands take
--cursor (resume from a previous next_cursor) and --max-tokens; code semantic also takes
--rerank-top-k; --format toon returns compact TOON tables.
Exit codes
Code
Meaning
0
Success.
1
Runtime error.
2
Usage error: bad flag or argument (including an invalid rescan path, or a destructive command without --yes).
3
Busy: another process holds the workspace writer lock. Retry later, or use basemind rescan, which the daemon serves.
4
A required daemon is unreachable.
130
Interrupted by Ctrl-C; completed work is committed and the index stays consistent.
With a comms daemon running, the one-shot CLI forwards memory operations, reference/caller reads,
the grep prefilter and rescans to it (the daemon is the sole index writer) instead of failing or
degrading to a truncated in-memory view.
Architecture overview: hub modules/symbols ranked by centrality + churn, plus dependency cycles (SCCs). --edges selects lanes (calls/imports/inherits/both/all); every edge carries a provenance tag (extracted/inferred/ambiguous) + confidence.
export [--format --focus --edges --write]
Render as node-link JSON / DOT / Mermaid / GraphML / Cypher / HTML / SVG.
display [--format --no-open]
Open a rendered view in the human's desktop viewer. --no-open writes the artifact and returns its path.
open [--format --no-open]
Return a live http://…/ui URL for the interactive graph (or a file:// export). The live page needs the daemon's HTTP front-end, which is opt-in — set BASEMIND_ALLOW_HTTP=1 in the daemon's environment; without it you get the file:// export. --no-open launches nothing.
Git (basemind git)
Command
Purpose
status
What's staged and unstaged right now.
recent [--limit] [--no-files]
Recent commits with their files (a recency window, not a search).
Score retrieval quality and token savings against gold from a JSONL task file; --baseline gates regressions. See benchmarks/eval/.
tokens --stdin
Count tokens in stdin with the real o200k tokenizer (needs the tokenizer feature).
The other former admin verbs live at the top level: status, rescan, cache stats|gc|clear, delta,
checkpoint and detect-waste.
Cache (basemind cache)
Command
Purpose
stats
Disk footprint (per-component + total, matches du) and process RAM.
gc [--dry-run]
Reap blobs no workspace on the machine references. Cross-workspace reference-counted, keeps blobs younger than 6 h (BASEMIND_BLOB_GC_GRACE_SECS), serialised by a machine-wide lock. --dry-run only counts the blobs in the store and deletes nothing.
clear --component <comp> [--yes]
Clear part of the cache (blobs, views, views:<name>, lance, git-cache, telemetry, all; default git-cache). Everything but git-cache asks for confirmation on a terminal and needs --yes otherwise. blobs is the machine-global store shared by every workspace. Refuses (exit 3) while a writer holds the workspace lock, and for blobs while the daemon runs.
Web (basemind web)
Command
Purpose
scrape <url>
Fetch and index a single page.
crawl <seed-url>
Follow links from a starting URL.
map <url>
Discover a site's pages without fetching bodies.
Agents (basemind agents, --features comms)
Every command takes --as-agent <ID> to act as a named sub-identity.
Command
Purpose
register [--name --description --version --skill] / list [--thread]
Publish your identity card / list agents the broker knows.
The broker daemon: run it, ensure it, stop it (--all stops every live daemon on the machine), or inspect pid / version / uptime.
doctor [--probe --clear-fatal]
List every live daemon on the machine (pid / comms dir / version / uptime), pruning dead registry entries, and flag a pile-up over the ceiling (BASEMIND_MAX_DAEMONS, default 8). --probe also asks each daemon whether it can serve; --clear-fatal acknowledges a recorded fatal store error.
Re-runnable onboarding: write basemind.toml (at the root or under the .config/ convention), select capabilities, inject usage rules.
lang <list|install|clean>
Manage downloaded language grammars.
hook install [--force]
Add a git pre-commit hook that runs basemind scan --staged. Honours core.hooksPath, works in linked worktrees, never blocks a commit, and refuses to overwrite a hook it did not write unless --force (the old one is kept as pre-commit.bak).
Full AI context layer over MCP — tree-sitter code-map, document RAG (PDF/Office/HTML/email + OCR + reranker), shared agent memory, on-demand web crawl, git history + blame + per-symbol diff. 300+ languages, 10+ coding-agent harnesses, content-addressed Fj
Herramientas
Herramientas
Aún no hay lista de herramientas. Los servidores remotos la reciben tras la primera comprobación de estado.
Preguntas frecuentes
Preguntas
¿Cómo instalo Basemind Opencode?
Copia en esta página la configuración stdio para Cursor, Claude Desktop, Claude Code o VS Code. Usa la instalación del publicador, no un proxy de PlugMCP.