# LeanKG — Agent Context
**Tech stack:** Rust + CozoDB + tree-sitter + MCP
## Build & Test
```bash
cargo build --release # always --release; debug profile has debug=false
cargo test --lib # quick unit tests only (CI does this)
cargo test # full suite including integration/e2e
make lint # = cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --all -- --check # formatting check
```
`.opencode.json` auto-loads `instructions/leankg-tools.md` — detailed MCP tool reference.
## CLI Quick Reference
| `cargo run --release -- init` | Init project |
| `cargo run --release -- index ./src` | Index codebase |
| `cargo run --release -- mcp-stdio --watch` | MCP stdio (local AI tools) |
| `cargo run --release -- mcp-http --port 9699` | MCP HTTP (remote clients) |
| `cargo run --release -- embed` | Build embedding vectors (after index) |
| `cargo run --release -- serve` | REST API + embedded UI v2 on :8080 |
| `cargo run --release -- impact <file> <depth>` | Blast radius calc |
Embeddings require `--features embeddings` build flag (off by default). Without them, `semantic_search` / `kg_semantic_context` return "no vectors".
## MANDATORY: Docker MCP project paths
When MCP talks to Docker HTTP on `:9699`, **always** pass container mount paths as `project=`. Host paths return "not initialized".
```rust
mcp_status(project="/workspace") // OK
search_code(query="fn main", project="/workspace") // OK
mcp_status(project="/Users/.../leankg") // FAILS
```
| This repo | `/workspace` |
| Side repo | `/workspace-other` (per local `.dockerfile`) |
Health check: `curl http://localhost:9699/health`. If healthy → use Docker MCP. Else → fall back to stdio + host-path `mcp_init`.
## Tool discovery prefer-order
Do **not** open with `query_graph`. Discover first:
`concept_search` → `semantic_search` → `search_code` / `find_function` → connection verbs (impact, deps, context).
| Fuzzy / NL / domain | `concept_search` → `semantic_search` → `search_code` |
| Exact symbol / file | `find_function` / `search_code` / `query_file` |
| How A↔B? | `shortest_path` |
| What is symbol? | `explain_node` |
| Expand subgraph | `query_graph` (after seeds known) |
**Dynamic ontology**: `add_ontology_concept` / `add_ontology_workflow` persist insights across sessions. `add_knowledge` for free-form notes. After YAML edits in `ontology/`, use `kg_trace_workflow` (auto-synced; no manual `leankg ontology sync` needed).
## Development workflow
1. Update `docs/prd.md` (narrative + ACs) + `docs/prd-task-tracker.md` (task list)
2. Implement per `docs/workflow-opencode-agent.md`
3. `cargo build --release && cargo test`
4. `git commit -m "feat: description"` (one feature per commit; **no** `Co-Authored-By` or AI attribution)
5. `git pull --rebase && git push`
6. Bump `version` in `Cargo.toml`
7. `git tag -a v<version> -m "Release v<version>" && git push origin v<version>`
## Key source files
| `src/main.rs` | CLI entrypoint |
| `src/lib.rs` | Module exports |
| `src/cli/mod.rs` | Subcommand definitions |
| `src/mcp/tools.rs` | MCP tool definitions |
| `src/mcp/handler.rs` | MCP tool handlers |
| `src/db/models.rs` | Data models |
| `src/graph/query.rs` | Graph query engine |
| `src/indexer/extractor.rs` | tree-sitter code parsing |
| `src/embed.rs` | Embedding pipeline CLI |
## Multi-project setup (side-by-side repos)
Gitignored local files:
- `.dockerfile` — copy from `.dockerfile.example`; set `LEANKG_PROJECT_DIRS=/workspace,/workspace-other`
- `docker-compose.override.yml` — add bind mounts for side repos
Never paste personal host paths into commits.
## Parallel subagent workflow
For 3+ independent tasks: dispatch to `.worktree/<feature>/` worktrees with feature branches. Verify isolation (`.gitignore` covers `.worktrees/`). Merge all feature branches after completion.
---
*Last updated: 2026-07-27*