A CLI and MCP server that pre-indexes codebases into SQLite — symbols, call graphs, imports, and file metadata — so AI agents can query project structure without parsing source at runtime.
Two situations where this matters:
-
Source isn't distributed. Binary releases, proprietary libraries, vendored dependencies — the consumer has no
.goor.tsfiles to read. An agentdb artifact gives agents the structural data anyway. -
Large codebases are expensive to parse on every session. Pre-indexing once in CI and distributing the result avoids repeated AST extraction on 100k+ LOC projects.
If agents can grep it in under 10 tool calls, this is overhead. For everything else — large codebases, distributed binaries, or repeated cross-package traversal — pre-indexing pays off.
go install github.com/roysland/agentdb@latestRequires Go 1.25+. Pure Go, no CGo, no build tags needed.
Configuration is read from ~/.config/agentdb/config.toml (or $XDG_CONFIG_HOME/agentdb/config.toml) with precedence: flags > environment variables > config.toml > built-in defaults.
Naming convention:
- Flags use kebab-case:
--embed-base-url - Environment variables use uppercase snake case with
AGENTDB_prefix:AGENTDB_EMBED_BASE_URL config.tomluses the exact sameAGENTDB_*keys as environment variables.
Canonical names are AGENTDB_* in both environment and config.
Example config.toml:
AGENTDB_DB_URL = "~/.local/share/agentdb/agentdb.db"
AGENTDB_DB_DRIVER = "auto"
AGENTDB_PROJECT_PATH = "~/Projects/my-repo"
AGENTDB_EMBED_PROVIDER = "ollama"
AGENTDB_EMBED_BASE_URL = "http://localhost:11434/v1"
AGENTDB_EMBED_MODEL = "nomic-embed-text"
AGENTDB_EMBED_TIMEOUT_SECONDS = "30"
AGENTDB_LINES_PER_CHUNK = "20"agentdb is local-first by default (local SQLite DB, stdio MCP server, local Ollama embedding endpoint), with explicit controls for stricter environments.
AGENTDB_EMBED_LOCAL_ONLY=1hard-fails startup when embeddings point to a non-localhost endpoint.AGENTDB_PLUGIN_SAFE_MODE=1disables all external parser plugin subprocess execution.AGENTDB_PLUGIN_ALLOWLIST=name1,name2restricts plugin loading to approved plugin names.- File traversal for indexing/analyzing/chunking only processes regular files confined to the target root; symlinks resolving outside the root are skipped.
- MCP request parameters are only logged at
AGENTDB_LOG_LEVEL=debugto reduce accidental sensitive text exposure in stderr collectors.
Recommended hardened setup:
export AGENTDB_EMBED_PROVIDER=disabled
export AGENTDB_EMBED_LOCAL_ONLY=1
export AGENTDB_PLUGIN_SAFE_MODE=1
export AGENTDB_LOG_LEVEL=info# Register and index a project
agentdb codebase register --path . --name my-project
agentdb index --codebase-id 1
agentdb analyze --codebase-id 1
# Start MCP server for agent access
agentdb mcp| Command | Description |
|---|---|
bootstrap |
Apply schema and ensure tables exist |
codebase register |
Register a codebase root path |
codebase list |
List registered codebases |
index |
Chunk and index source files (supports --incremental) |
analyze |
Extract symbols, call graphs, and relationships (supports --incremental) |
watch |
Watch a codebase for file changes and trigger incremental re-indexing |
locate-issue |
Locate likely impact area for a natural-language issue report |
export |
Export a codebase to a portable .agentdb artifact |
import |
Import a .agentdb artifact into the local database |
memory |
Manage agent long-term memories |
workspace create/add/remove/list |
Manage cross-repository workspaces |
mcp |
Run MCP stdio server |
version |
Print version |
agentdb mcp exposes all capabilities over JSON-RPC stdio (MCP protocol). Tools available:
During MCP initialization, agentdb also publishes a server description that frames proprietary-artifact usage: indexed data is for navigation/development assistance, and reconstructing or reproducing source implementation from search/symbol results is prohibited.
search— Ranked retrieval across memories and/or code chunks (lexical via FTS5, vector, or hybrid)semantic_search— Natural language symbol lookup via vector similarity with optional blast radius enrichment
register_codebase/list_codebases— Codebase managementindex_codebase/index_status— Indexing (supports incremental mode)analyze_codebase— Symbol and relationship extraction (supports incremental mode)codebase_context— Retrieve README/design/agent guidance docs for session bootstrapping; falls back toproject_overviewwhen no docs are indexed
find_symbol— Look up functions, types, methods by name (supports workspace-scoped queries)find_usages— Find all references to a symbol (supports workspace-scoped queries)get_file_symbols— List symbols defined in a fileget_callers/get_callees— Call graph traversal (supports workspace-scoped queries)get_imports— List imports for a fileproject_overview— High-level codebase summary (languages, LOC, packages, top files)locate_issue_impact_area— Triage a natural-language issue description into ranked impact candidates using hybrid search and blast radiuscompare_capabilities— Compare symbol coverage between two codebases (e.g., legacy vs. current); returns implemented/partial/missing/extra groups by file-path domain
server_stats— Runtime metrics: uptime, per-tool call counts, avg/p95 latency, error rates
{
"name": "search",
"arguments": {
"query": "incremental analyze",
"source": "chunks",
"mode": "lexical",
"codebase_id": 1,
"limit": 10
}
}agentdb watch monitors a codebase directory for file changes and triggers incremental re-indexing automatically — no CI step required for local development.
# Watch and re-index only (chunk index, no symbol extraction)
agentdb watch --codebase-id 1 --codebase-path .
# Watch and re-index + re-analyze (symbols, call graph)
agentdb watch --codebase-id 1 --codebase-path . --analyze
# Custom debounce window (default: 500ms)
agentdb watch --codebase-id 1 --codebase-path . --debounce 1000SIGINT/SIGTERM waits for any in-progress re-index to complete before exiting.
Both index and analyze support an --incremental flag that detects changed files via SHA-256 content hashing and only re-processes what changed. On a 150k LOC codebase with a few file edits, incremental runs complete in seconds instead of minutes.
File discovery for indexing/analyzing also honors .gitignore files (root and nested directories), in addition to built-in skip rules like .git, node_modules, and vendor, so ignored files are skipped by default.
# Full index (first run or when you want a clean slate)
agentdb index --codebase-id 1
agentdb analyze --codebase-id 1
# Incremental (subsequent runs — only processes changed files)
agentdb index --incremental --codebase-id 1
agentdb analyze --incremental --codebase-id 1Both commands output performance metrics: files processed, files skipped, duration, and throughput.
Group multiple codebases into a workspace for cross-repo symbol resolution and call graph traversal.
# Create a workspace and add codebases
agentdb workspace create --name platform
agentdb workspace add --workspace platform --codebase-id 1
agentdb workspace add --workspace platform --codebase-id 2
# MCP tools accept workspace_id to query across all members
# find_symbol, get_callers, find_usages all support workspace-scoped queriesWhen analyzing codebases in a workspace, unresolved imports that match symbols in sibling codebases are automatically linked as cross-repository edges.
The semantic_search MCP tool maps natural language queries to candidate symbols via vector similarity. Useful for bug triage from vague descriptions.
Tool: semantic_search
Input: {"query": "config parsing fails for special characters", "codebase_id": 1, "include_blast_radius": true}
Returns ranked symbols with similarity scores, plus optional blast radius (callers, callees, dependents) showing what might break.
For offline use with artifacts, export with --include-embeddings to preserve vectors, then supply a pre-computed query_embedding parameter at query time — no live embedding API needed.
The core CI workflow: analyze once, distribute the result.
# In CI: index, analyze, export
agentdb codebase register --path . --name my-lib
agentdb index --codebase-id 1
agentdb analyze --codebase-id 1
agentdb export --codebase-id 1 --output my-lib.agentdb
# With embeddings for offline semantic search
agentdb export --codebase-id 1 --output my-lib.agentdb --include-embeddings
# For proprietary distribution: strip source-bearing text while keeping graph metadata
agentdb export --codebase-id 1 --output my-lib.agentdb --strip-source
# On consumer machine: import and query
agentdb import my-lib.agentdb
agentdb mcpThe artifact is a standard SQLite file containing symbols, edges, source file metadata, chunks, and indexed file records for a single codebase. By default it excludes memories, tasks, and embedding vectors (embeddings are environment-specific and can be regenerated locally). Use --include-embeddings to preserve vectors for offline semantic search.
Use --strip-source to remove source-bearing text from exported data (chunks.snippet, symbols.doc_comment, symbols.body_snippet, and symbols.signature) while preserving the symbol graph and structural metadata.
- Upserts by matching on
root_path— re-importing replaces existing data --nameflag overrides the codebase name from the artifact- Schema version is validated before import
- Embedding metadata (
has_embeddings,embedding_model,embedding_dimensions) is preserved
name: Generate AgentDB Artifact
on:
release:
types: [published]
jobs:
build-artifact:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
- name: Install agentdb
run: go install github.com/roysland/agentdb@latest
- name: Index and export
run: |
CODEBASE_ID=$(agentdb codebase register --path . --name "${{ github.event.repository.name }}" | jq -r '.id')
agentdb index --codebase-id "$CODEBASE_ID"
agentdb analyze --codebase-id "$CODEBASE_ID"
agentdb export --codebase-id "$CODEBASE_ID" --output "${{ github.event.repository.name }}.agentdb"
- name: Attach to release
uses: softprops/action-gh-release@v2
with:
files: "${{ github.event.repository.name }}.agentdb"Language support is extensible via external parser plugins. Plugins are standalone executables that communicate with agentdb over JSON-RPC (stdin/stdout), so they can be written in any language.
~/.agentdb/plugins/
└── csharp-parser/
├── manifest.json
└── bin/csharp-parser
manifest.json:
{
"name": "csharp-parser",
"version": "1.0.0",
"languages": ["csharp"],
"binary": "./bin/csharp-parser"
}Plugins are discovered from ~/.agentdb/plugins/ (default) or a directory specified by AGENTDB_PLUGIN_DIR. When a plugin declares a language already handled by a built-in parser, the plugin takes priority.
The plugin protocol supports three methods: capabilities (handshake), parse (extract symbols/edges), and shutdown (graceful termination). Subprocesses are reused across files of the same language within a session.
The main binary (pure Go, no CGo) supports Go only via go/ast.
For Python, TypeScript, TSX, JavaScript, and Rust, install the agentdb-parsers plugin (requires CGo and a C compiler):
go install -tags treesitter github.com/roysland/agentdb/plugins/parsers@latestThen set it up as a plugin:
mkdir -p ~/.agentdb/plugins/agentdb-parsers
cp $(go env GOPATH)/bin/agentdb-parsers ~/.agentdb/plugins/agentdb-parsers/
cp $(go env GOPATH)/src/github.com/roysland/agentdb/plugins/parsers/manifest.json ~/.agentdb/plugins/agentdb-parsers/When using the parsers plugin:
- Error threshold — Files with >15% ERROR nodes in their AST fall back to text-based chunking.
- Merge conflict detection — Files with conflict markers are marked
partialand skipped for AST extraction. - Panic recovery — Parser crashes are caught and don't bring down the MCP server.
MCP tool responses annotate results from degraded files.
Go source is chunked at semantic boundaries (functions, types, methods) rather than fixed line counts. Chunks carry kind, name, and signature metadata. Large nodes (>100 lines) are subdivided at nested block boundaries.
Non-Go languages (handled by the parsers plugin) fall back to line-based chunking for the index step; symbol and call graph extraction via the plugin is still accurate.
Non-code content (markdown, prose) uses BPE token-count windowing with paragraph-boundary preference.
Chunk search uses SQLite FTS5 for lexical matching with BM25 ranking. The FTS5 index is kept synchronized with the chunks table via triggers.
- Lexical mode — FTS5 MATCH with BM25 scoring
- Hybrid mode — FTS5 candidates re-ranked by cosine similarity against embedding vectors
- Fallback — If FTS5 is unavailable, falls back to in-memory scan (with a warning)
New chunks are marked with pending_embedding status until the async embedding pipeline processes them. Hybrid search results flag chunks where vector re-ranking wasn't applied.
The MCP server emits structured JSON logs to stderr and tracks per-tool metrics in memory.
{"timestamp":"2024-01-15T10:30:00.123Z","level":"info","operation":"find_symbol","duration_ms":12,"status":"ok"}Configure log level via AGENTDB_LOG_LEVEL (debug, info, warn, error). At debug level, request parameters and response sizes are included.
The server_stats MCP tool returns runtime metrics:
- Uptime, total requests, active codebase count
- Per-tool breakdown: call count, average latency, p95 latency, error count
- P95 computed over a sliding window of the last 1000 calls
- Resettable via
reset: trueparameter
The MCP server uses a single persistent SQLite connection (SetMaxOpenConns(1)) with application-layer write serialization via sync.Mutex. This prevents WAL contention and SQLITE_BUSY errors.
- All operations have strict context deadlines (3s writes, 5s reads)
- Mutex acquisition timeout prevents indefinite blocking
- Health-check with automatic reconnection
PRAGMA journal_mode=WALandPRAGMA busy_timeout=3000as defense-in-depthPRAGMA auto_vacuum=INCREMENTALfor non-blocking storage reclamation
File change detection uses SHA-256.
- Streaming hash for files >10MB (no memory spikes)
- Post-migration incremental vacuum reclaims freed pages
- Integrity verification ensures no orphaned chunks after migration
Vector search is optional. Configure a provider to enable it:
export AGENTDB_EMBED_PROVIDER=openai
export AGENTDB_EMBED_BASE_URL=https://api.openai.com/v1
export AGENTDB_EMBED_API_KEY=sk-...
export AGENTDB_EMBED_MODEL=text-embedding-3-smallWhen unavailable, all search falls back to lexical mode. Artifacts exclude embeddings by default — use --include-embeddings to preserve them for offline semantic search.
You can run embeddings entirely locally using Ollama, removing the need for an external API key or network access.
-
Install Ollama from https://ollama.com and start the service.
-
Pull an embedding model:
ollama pull nomic-embed-text- Configure environment variables:
export AGENTDB_EMBED_BASE_URL=http://localhost:11434/v1
export AGENTDB_EMBED_PROVIDER=ollama
export AGENTDB_EMBED_MODEL=nomic-embed-text
export AGENTDB_EMBED_API_KEY=The API key can be left empty or unset — agentdb skips authentication for local endpoints.
# Start Ollama (if not already running)
ollama serve &
# Pull the embedding model
ollama pull nomic-embed-text
# Configure agentdb for local embeddings
export AGENTDB_EMBED_BASE_URL=http://localhost:11434/v1
export AGENTDB_EMBED_PROVIDER=ollama
export AGENTDB_EMBED_MODEL=nomic-embed-text
export AGENTDB_EMBED_API_KEY=
# Register, index, and use semantic search
agentdb codebase register --path . --name my-project
agentdb index --codebase-id 1
agentdb analyze --codebase-id 1
agentdb mcpSemantic search and hybrid mode now work without any external API dependency.
Ollama not running
If you see connection errors, make sure the Ollama service is running:
ollama serveOr check its status with ollama list. On macOS/Linux, Ollama may run as a background service — verify with ps aux | grep ollama.
Model not pulled
If embedding requests fail with a model-not-found error, pull the model first:
ollama pull nomic-embed-textVerify it's available with ollama list — you should see nomic-embed-text in the output.
Connection refused
If agentdb reports "connection refused" when calling the embedding endpoint:
- Confirm Ollama is listening on port 11434:
curl http://localhost:11434/v1/models - Check that
AGENTDB_EMBED_BASE_URLis set tohttp://localhost:11434/v1(not https, and include the/v1path) - If Ollama is bound to a different host/port, adjust the URL accordingly
--db-url Database file path (env: AGENTDB_DB_URL)
--db-driver Driver mode: auto|sqlite3 (env: AGENTDB_DB_DRIVER)
--project-path Default project path (env: AGENTDB_PROJECT_PATH)
--embed-provider Embedding provider: disabled|openai|ollama (env: AGENTDB_EMBED_PROVIDER)
--embed-base-url Embedding API base URL (env: AGENTDB_EMBED_BASE_URL)
--embed-api-key Embedding API key (env: AGENTDB_EMBED_API_KEY)
--embed-model Embedding model name (env: AGENTDB_EMBED_MODEL)
--embed-timeout-seconds Embedding timeout seconds (env: AGENTDB_EMBED_TIMEOUT_SECONDS)
SQLite database with these tables:
| Table | Purpose |
|---|---|
meta |
Schema version and artifact metadata |
codebases |
Registered project roots |
symbols |
AST-extracted symbols (functions, types, methods, consts) |
edges |
Directed relationships (imports, calls, type usage, cross-repo links) |
source_files |
File-level metadata (language, LOC, package) |
chunks |
Semantic code chunks with optional embeddings and FTS5 index |
chunks_fts |
FTS5 virtual table for lexical search |
indexed_files |
File indexing state with parse status tracking |
memories |
Agent long-term memory |
workspaces |
Logical groupings of codebases |
workspace_members |
Workspace-to-codebase membership |
Main binary (pure Go, no CGo):
go build -o ~/.local/bin/agentdb .Parser plugin:
CGO_ENABLED=1 go build -tags treesitter -o ~/.local/bin/agentdb-parsers ./plugins/parsers/MIT