Local, offline code intelligence for Clojure codebases. Indexes source code with clj-kondo, stores metadata in SQLite with FTS5, and provides hybrid BM25 search via CLI tools or MCP server. Includes an AST-targeted edit engine for surgical source rewriting by qualified symbol name, and conversation history search for Claude Code sessions.
| Binary | Purpose | Required |
|---|---|---|
clj-kondo |
Clojure static analysis | Yes |
git |
Version history indexing | Yes |
ollama |
Embedding model inference | Yes (for semantic search) |
| Java 21+ | Runtime | Yes |
Clojure CLI (clj) |
Build & run | Yes |
# Index a Clojure project
vestiga index -p /path/to/project
# Search indexed code
vestiga search "handle request"
# Find all callers of a function
vestiga refs my.app.core/handler
# Find namespace dependents
vestiga deps my.app.db
# Impact analysis before a refactor
vestiga impact my.app.core/handler
# Search git history
vestiga history "authentication"
# Index and list Claude Code conversation sessions
vestiga conversations --index -p /path/to/project
# Search conversation history
vestiga conversation-search "FTS5 search"
# View a single conversation
vestiga conversation <session-id>vestiga <command> [options] [args]
Commands:
conversation View a single conversation session
conversation-search Search across conversation history
conversations List indexed conversation sessions
deps Find all namespaces that depend on a namespace
history Search git commit history
hotspots Find most frequently changed files
impact Analyse impact of changing a symbol
index Index a project for searching
mcp Start the MCP JSON-RPC server (for AI tool integration)
refs Find all references to a symbol
search Search indexed code
Run 'vestiga <command> --help' for command-specific options.
vestiga search [opts] <query>
-d, --db PATH Database path (default: .vestiga/db.sqlite)
-l, --limit N Max results (default: 20)
-k, --kind KIND Filter by symbol kind (defn, defmacro, defprotocol, etc.)
-n, --namespace NS Filter by namespace (supports * glob)
# Examples
vestiga search "parse request"
vestiga search -k defn "validate"
vestiga search -n "my.app.*" "config"vestiga refs [opts] <qualified-name>
-d, --db PATH Database path
# Examples
vestiga refs my.app.core/handle-requestvestiga deps [opts] <namespace>
-d, --db PATH Database path
# Examples
vestiga deps my.app.dbvestiga impact [opts] <qualified-name>
-d, --db PATH Database path
# Shows: callers, namespace dependents, recent git commits
vestiga impact my.app.core/handle-requestvestiga history [opts] <query>
-d, --db PATH Database path
-l, --limit N Max results (default: 20)
-f, --file PATH Filter to commits touching this file
# Examples
vestiga history "authentication"
vestiga history -f src/my/app/auth.clj "fix"vestiga conversations [opts]
-p, --project-root PATH Project root directory (default: .)
-d, --db PATH Database path
-l, --limit N Max sessions (default: 20)
-i, --index Index conversations before listing
# Examples
vestiga conversations --index -p /path/to/project
vestiga conversations -l 5vestiga conversation [opts] <session-id>
-d, --db PATH Database path
-r, --role ROLE Filter by role (user/assistant)
# Examples
vestiga conversation abc123-def456
vestiga conversation --role user abc123-def456vestiga conversation-search [opts] <query>
-d, --db PATH Database path
-l, --limit N Max results (default: 20)
-r, --role ROLE Filter by role (user/assistant)
-t, --tool TOOL Filter by tool name (e.g. Read, Bash, Edit)
# Examples
vestiga conversation-search "FTS5 search"
vestiga conversation-search --role assistant "refactor"
vestiga conversation-search --tool Bash "deploy"vestiga index [opts]
-p, --project-root PATH Project root directory (default: .)
-d, --db PATH Database path (default: <project-root>/.vestiga/db.sqlite)
-f, --full Force full re-index
# Examples
vestiga index -p /path/to/project
vestiga index -p . -f # full re-indexvestiga mcp [opts]
-d, --db PATH Database path (default: .vestiga/db.sqlite)Starts the MCP JSON-RPC server over stdio. Used by AI tools (Claude Code, etc.).
Add to .mcp.json in your project root:
{
"mcpServers": {
"vestiga": {
"command": "/path/to/vestiga",
"args": ["mcp"]
}
}
}Or for development:
{
"mcpServers": {
"vestiga": {
"command": "clj",
"args": ["-M:dev", "-m", "vestiga.server.core", "mcp"],
"cwd": "/path/to/vestiga"
}
}
}| Tool | CLI equivalent |
|---|---|
search_code |
vestiga search |
find_references |
vestiga refs |
find_dependents |
vestiga deps |
impact_analysis |
vestiga impact |
search_history |
vestiga history |
index_project |
vestiga index |
edit_code |
— (MCP only) |
search_conversations |
vestiga conversation-search |
list_conversations |
vestiga conversations |
The edit_code tool applies AST-targeted edits to Clojure source files. Edits target definitions by namespace-qualified name rather than by line number or text matching, eliminating transcription errors.
Operations:
| Operation | Target | Description |
|---|---|---|
replace_form |
my.ns/my-fn |
Replace an entire top-level form |
replace_body |
my.ns/my-fn |
Replace only the body of a single-arity defn (preserves name, arglist, docstring) |
add_form_before |
my.ns/my-fn |
Insert a new form before the target |
add_form_after |
my.ns/my-fn |
Insert a new form after the target |
delete_form |
my.ns/my-fn |
Remove a top-level form |
add_require |
clojure.string :as str |
Add a :require clause to the ns form (idempotent) |
replace_ns |
— | Replace the entire (ns ...) form |
append_to_ns |
my.ns |
Append a new form at the end of the file |
replace_defmethod |
my.ns/dispatch :http |
Replace a specific defmethod by dispatch value |
Example (JSON-RPC):
{
"operations": [
{"operation": "add_require",
"target": "clojure.string :as str",
"file": "src/my/app/handler.clj"},
{"operation": "replace_body",
"target": "my.app.handler/process-request",
"content": " (-> req validate transform persist!)"}
]
}The engine uses rewrite-clj for whitespace-and-comment-preserving source rewriting. It runs fresh clj-kondo analysis on each call to resolve qualified names to file locations.
Polylith workspace with 8 components and 1 base.
server (base)
|- CLI + MCP entry point
v
.------+------+------+------+------+------+--------------.
| | | | | | | |
config db index embed search mcp ast conversation
| Component | Responsibility |
|---|---|
| config | Configuration loading from .vestiga/config.edn |
| db | SQLite connection, schema, CRUD operations, FTS5 search queries |
| index | clj-kondo analysis, source chunking, git history extraction, indexing orchestration |
| embed | EmbeddingProvider protocol, Ollama HTTP client, Ollama process lifecycle |
| search | Hybrid search engine, Reciprocal Rank Fusion ranking |
| mcp | MCP JSON-RPC server, tool definitions and handlers, stdio transport |
| ast | AST-targeted edit engine: resolve symbols by qualified name, surgical source rewriting via rewrite-clj |
| conversation | Claude Code conversation history: JSONL parsing, session discovery, FTS5-indexed search |
vestiga/
workspace.edn # Polylith workspace config
deps.edn # Root deps with :dev, :test, :poly aliases
build.clj # Uberjar + GraalVM native-image build
components/ # 8 components (config, db, index, embed, search, mcp, ast, conversation)
bases/server/ # CLI entry point
projects/vestiga/ # Deployable project
development/ # REPL + shared test utilities
# Run all tests via Polylith (recommended)
clj -M:poly test :all
# Run only tests for changed bricks (CI-friendly)
clj -M:poly testclj -M:dev -m vestiga.server.core search "query"
clj -M:dev -m vestiga.server.core refs my.ns/fn-name
clj -M:dev -m vestiga.server.core index -p .clj -M:poly info # workspace overview
clj -M:poly check # validate workspace
clj -M:poly deps # brick dependency graph
clj -M:poly libs # library usage# Uberjar
clj -T:build uber
java -jar target/vestiga-0.1.0-standalone.jar search "query"
# GraalVM native image
./script/build-native.sh
./target/vestiga search "query"Create .vestiga/config.edn in your project root:
{:embed-model "nomic-embed-text"
:embed-dim 768
:ollama-base-url "http://localhost:11434"
:index-paths ["src" "test"]
:file-extensions #{".clj" ".cljs" ".cljc" ".bb"}
:git-max-commits 10000
:search-limit 20}All indexes are stored in <project-root>/.vestiga/db.sqlite. Delete .vestiga/ to reset.
Copyright 2024-2026.
Distributed under the Eclipse Public License 2.0.