comindly indexes a whole team's repositories into one versioned knowledge graph, then serves it to coding agents (Claude Code, Cursor, …) over MCP. Unlike grep or per-repo search, it answers structural, cross-repo questions deterministically:
- Who breaks if I change this? — org-wide blast radius (
ripple) - What's the minimal context to change X safely? — token-budgeted read-set (
context_pack) - How does this flow work? — a call-trace walkthrough (
flow) - Where across the org is this used / how do I …? — hybrid search + a pre-generated question catalog
Written in Rust. One static binary. No server required (one container if a team wants one), no per-developer re-indexing.
Why it's different
- Deterministic graph, not fuzzy RAG. Calls, imports, inheritance and instantiation come from the AST (tree-sitter) — exact, reproducible, cheap to build. Python, TypeScript/JavaScript, Go, Java, Kotlin and Rust. Where a repo has a SCIP index (or a SCIP indexer is installed), its compiler-grade answers take precedence.
- Cross-repo by design. A global symbol identity (SCIP scheme) links a definition in one repo to
its users in every other.
ripplegives blast radius across the whole org. - Built once, read everywhere. CI builds a new atomically-versioned index (a folder or a bucket); every agent reads the same fresh artifact. Incremental — only changed files/symbols are recomputed.
- Graph-aware hybrid search. Local static embeddings (Model2Vec) + BM25 + a dependency-graph centrality signal no pure search tool has.
- Provider-agnostic LLM enrichment. Optional summaries, question catalogs, and flow walkthroughs via Rig — OpenAI, any OpenAI-compatible endpoint, or a local model.
Install
Prebuilt binaries (macOS arm64/x64, Linux x64/arm64) are published to
GitHub Releases on each vX.Y.Z tag:
|
Or from crates.io (needs Rust 1.95 or newer, plus protoc and cmake):
Or from source:
&&
# Try the deterministic engine on any repo, no network or bucket needed:
Quick start
Zero-config: with no --index-dir, comindly reads and writes a default index location
(~/.local/share/comindly, XDG-aware — see comindly config path).
Explicit location — a folder or a bucket (s3://, gs://, az://), shared across a team. The same --index-dir
builds and reads it (comindly manages the internal dataset layout):
# 1. Build the org index from several repos (embeddings + LLM enrichment/flows/guide run by
# default when OPENAI_API_KEY is set; add --no-enrich / --no-flows / --no-guide to skip, or --no-llm for all)
# 2. Explore / search the prebuilt index (instant, no re-parse)
# 3. Serve it to an agent over MCP
Register it with your agent. Claude Code:
Cursor, Codex, VS Code and other MCP clients: see Getting started,
or open comindly ui --web → Get started, which fills in your index path and checks your setup.
MCP tools (15):
- Navigate:
search,find,zoom,thread,flow,repos,suggest. - Before a change:
ripple(blast radius, across repos and service contracts),context_pack(minimal read-set + known constraints),preflight(constraints, dead ends, contracts, missing companions for a planned edit),contracts(HTTP routes, queues, buckets, tables and who uses them),guide(measured conventions and recipes). - Reasoning ledger:
why(recorded decisions, failed attempts and constraints about a symbol),remember,review.
Results are handed to the agent as markdown by default (structured JSON is also attached; use serve --format json for raw JSON). Hooks, the ledger, self-enforcing constraints, signing and privacy are described in the docs (guides).
In the app
comindly app (macOS) or comindly ui --web shows the same graph to people: the org map, contracts, the
ledger, packages and search. Shown here on the example shop in examples/acme.
Commands
| Command | Purpose |
|---|---|
comindly index <repo> [--enrich] [--flows] [--guide] [--no-embed] [--incremental] |
Index a single repo (embeds by default) |
comindly link <repos…> [--enrich] [--flows] [--guide] [--no-embed] [--incremental] |
Link several repos (cross-repo edges + blast radius) |
comindly explore <focus> [--index-dir <dir>] |
Zoom, blast radius, and context pack for a symbol |
comindly search <query…> [--repo <name>] [--index-dir <dir>] [--format md|table] |
Graph-aware hybrid code search |
comindly find <query> [--repo <name>…] [--index-dir <dir>] |
Locate symbols by name/path substring |
comindly repos [--index-dir <dir>] |
List indexed repositories + symbol counts |
comindly stats [--repo <name>…] [--index-dir <dir>] |
Per-repo stats: symbols, edges, kinds, enrichment coverage |
comindly guide [--repo <name>…] [-o <file>] [--index-dir <dir>] |
Per-repo inferred coding style guides (built with --guide) |
comindly flow <focus> [--index-dir <dir>] |
Pre-generated flow walkthrough + live call trace |
comindly changed <repo> [--since <sha>] |
Files changed since a commit (git diff) |
comindly serve [--index-dir <dir>] [--format md|json] |
MCP server over stdio |
comindly contracts [--type http|sqs|sns|s3|table] [--dangling] |
Service contracts with providers and consumers (FastAPI, Next.js, Express, Spring MVC, Feign, RestTemplate, WebClient, Go net/http/gin/echo/chi, axum, actix, reqwest, httpx/requests/fetch/axios, boto3, SQL; Terraform queues/topics/buckets and subscriptions) |
comindly packages [--skew] |
Internal packages: publisher, consumers, version skew |
comindly conventions [--repo <name>] |
Measured conventions, org baseline, recipes from history, and the team's own (each with an id) |
comindly conventions add "<rule>" [--repo <name>] [--dimension <d>] | edit <id> "<rule>" | rm <id> | restore <id> |
Add a team convention, rewrite or hide one (measured ones can be restored); stored under <index>/_conventions/, untouched by re-indexing |
comindly preflight [repo] [--base <rev>] [--strict] |
Before committing or in MR CI: constraints, dead ends, failing checks, contracts, blast radius, missing companions (MR job) |
comindly remember <kind> --on <symbol> --title … |
Record a decision, failed attempt, constraint, gotcha, intent or question |
comindly why <symbol> |
Reasoning blame for a symbol (status, trust, evidence) |
comindly review <id> <confirm|archive|invalidate|supersede|dispute> [--reason "…"] |
Act on a ledger record; comindly erase <id> deletes one |
comindly ledger [--inbox] [--check] [--compact] |
All ledger records, only those needing review, evaluate constraint checks (non-zero exit on a violated must, for CI), or fold the inbox into the Lance snapshot |
comindly erase <id…> | --actor <id|me> [--yes] |
Erase ledger records (and relations about them) for good, including old snapshot versions; dry run without --yes |
comindly doctor |
Check this machine's setup: index and ledger reachable, local mirror, hooks, LLM key, signing, SCIP indexers |
comindly hook <agent> <event> / comindly init-hooks <claude|cursor|gemini|codex|generic> |
Agent hook adapter / config snippet |
comindly eval graph [--scip <dir>] |
Graph quality on the gold fixture (precision/recall per edge kind) |
comindly repos [add <folders or clone URLs…> | remove <names…> | scan <dir>] |
Indexed repositories, and the list comindly link indexes when given no folders |
comindly app [--index-dir <dir>] |
The UI in its own window (macOS) |
comindly team [set k=v… | key] |
Team settings stored with the index (LLM, embedding model, LLM steps); key stores your own API key |
comindly join <index> |
Use a team's index on this machine |
comindly ui [--web [--port 7878] [--host <addr>] [--open]] [--index-dir <dir>] |
Terminal UI (incl. a ledger timeline), or the web UI on 127.0.0.1 (overview, contracts, flows, ledger review, explorer with a neighbourhood graph, conventions); with --host 0.0.0.0 and COMINDLY_PUBLIC_URL, a team server |
comindly cache refresh [--index-dir <dir>] |
Refresh the local mirror of a remote index that hooks read |
comindly config <path|init> |
Show or scaffold the config file |
Run comindly <command> --help for the full flags of any subcommand.
--index-dir is a folder or a bucket location (s3://, gs://, az://); it is optional and defaults to the
configured index location. All build steps default on (embed, enrich, flows, guide);
each has a config.toml default and a --x / --no-x override (CLI wins). Embeddings are local;
enrich/flows/guide call an LLM (cost + send code, need OPENAI_API_KEY) — they skip
automatically with a warning when no key is set, so a keyless index still builds the graph +
search. Cap LLM cost with max_enrich / max_flows in config.toml.
How it works
Build the index once (in CI or locally); every consumer reads the same versioned artifact.
flowchart LR
subgraph SRC["Sources (git)"]
R1["pkg-common"]
R2["service-a / service-b / …"]
end
subgraph IDX["Index — incremental"]
P["parse<br/>tree-sitter"]
RS["resolve<br/>cross-repo SCIP"]
G["git<br/>changed files only"]
end
subgraph ART["Versioned LanceDB artifact (folder or bucket)"]
GR["graph<br/>symbols · edges"]
SE["search<br/>vectors · BM25"]
EN["enrichment<br/>summaries · queries · flows"]
end
subgraph USE["Consume — instant"]
MCP["comindly serve<br/>MCP · 15 tools"]
CLI["comindly search / explore / flow"]
end
SRC --> IDX --> ART --> USE
AGENT(["coding agent"]) -. ripple / context_pack .-> MCP
Single crate, one module per stage — see ARCHITECTURE.md for the design and the
competitive landscape.
src/model.rs SCIP identity, Symbol/Edge model
src/parse.rs tree-sitter walk → symbols, structure, per-file facts
src/lang/ per-language adapters: Python, TypeScript/JS, Go, Java, Kotlin, Rust
src/packages.rs module names from pyproject / package.json / tsconfig / go.mod / Cargo.toml
src/resolve.rs binder: imports, re-exports, type flow, inheritance — within and across repos
src/scip.rs SCIP ingestion (existing index.scip or installed indexers)
src/eval.rs graph-quality eval on a gold fixture (`comindly eval graph`)
src/conventions.rs measured coding conventions + org baseline; src/recipes.rs change recipes from history
src/ledger.rs reasoning ledger: decisions, failed attempts, constraints anchored to symbols (`why`, `remember`)
src/checks.rs compiled constraint checks evaluated on the graph and manifests (`ledger --check`, preflight)
src/web.rs local web UI (`comindly ui --web`): JSON API + the embedded React app from ui/
src/git.rs git change detection (incremental)
src/index.rs versioned LanceDB store: symbols, edges, search, enrichment, flows, style guide
src/graph.rs in-memory petgraph: ripple / thread / zoom / context_pack
src/embed.rs Model2Vec embeddings + code-aware hybrid ranking
src/search.rs hybrid retrieval (BM25 + vector + graph centrality)
src/llm.rs LLM summaries / questions / flow walkthroughs (opt-in, provider-agnostic via Rig)
src/mcp.rs MCP server (15 tools)
src/main.rs the comindly binary (CLI)
For a team
One container runs comindly as a server for a team: members sign in by email or with codes admins
hand out, admins invite people and manage the GitHub, GitLab and LLM tokens it uses, and the index
and the accounts live in your own storage (a folder, S3, Google Cloud Storage or Azure), so the
container keeps nothing on its own disk. See
Self-hosting; scripts/docker-local.sh and
docker compose up try it locally. Agents connect to it over HTTP with a personal token.
The crate is also a library: read an index, follow flows and serve the MCP tools from your own service (Using comindly as a library).
CI
.github/workflows/comindly-index.yml (and
docs/guides/ci.md, with a GitLab variant) builds the shared index on a schedule: it clones
the listed repos and runs comindly link … [--enrich] [--incremental], publishing the result
as a downloadable artifact (or to a bucket). Lance's version manifest is the atomic "latest" pointer every
consumer reads.
Configuration
Persistent, non-secret defaults live in config.toml (comindly config path shows where; comindly config init scaffolds it). Precedence, highest first: CLI flag → environment variable → config
file → built-in default.
= "~/.local/share/comindly" # default --index-dir (folder, s3://, gs:// or az://)
= "gpt-6-luna" # any OpenAI-compatible model id
= "minishlab/potion-base-8M"
= "md" # default when --format is absent (search: md|table, serve: md|json)
= true # index/link step defaults; CLI --x / --no-x override
= true # LLM per-symbol summaries + queries (cost + sends code)
= true # LLM flow walkthroughs (cost + sends code)
= true # evidence-based style guide (cost + sends code)
# llm_base_url = "http://localhost:11434/v1" # Ollama / vLLM / LiteLLM proxy
# max_enrich = 200 # cap --enrich symbols (omit = no cap, whole codebase)
# max_flows = 50 # cap --flows narrations (omit = no cap)
# scip = "auto" # auto | require | off
# cache_ttl_secs = 300 # how often serve/ui check for a new index version; hooks' local mirror
# signing_key = "~/.ssh/id_ed25519.pub" # sign ledger records (default: git user.signingkey)
# allowed_signers = "~/.config/git/allowed_signers" # verify them (default: git config)
Environment overrides: COMINDLY_INDEX_DIR, COMINDLY_LLM_MODEL, COMINDLY_EMBED_MODEL,
COMINDLY_LLM_BASE_URL, COMINDLY_FORMAT.
Secrets stay in the environment, never the file: --enrich/--flows use an LLM via Rig
(default OpenAI, OPENAI_API_KEY; any OpenAI-compatible endpoint via COMINDLY_LLM_BASE_URL). An index in a
bucket (s3://, gs://, az://) is read with the credentials the machine or container already has.
Status
Engine: parse → resolve (tree-sitter + SCIP) → index → graph → embed → enrich → search → serve,
git-incremental at repo and org level. On top: the service-contract graph (HTTP, queues, topics,
buckets, tables, Terraform), conventions and recipes, the reasoning ledger (records, staleness,
self-enforcing checks, signing, erasure), preflight, and terminal and web
UIs. Progress and open items: docs/design/roadmap.md.
Development
Pre-commit hooks (fmt + clippy + basic file checks) live in .pre-commit-config.yaml — install
with pre-commit install, or the Rust-native prek install (both read the same file).
License
MIT.