Lean KG

LeanKG : Arrêtez de brûler des tokens. Commencez à coder Lean.

Documentation

LeanKG

LeanKG

⚡ Implementation: 100% Go. The Rust engine was removed at the parity cutover; the whole engine is the root Go module github.com/FreePeak/LeanKG. See docs/prd.md for the parity ledger. Build: make go-build · Test: make go-test · Bench: make go-bench.

Enterprise-ready code knowledge graph for AI coding agents
Multi-repo · env governance · incidents & services · req↔code · −65% tokens / −85% tool calls

Live Demo · Docs · pkg.go.dev · Changelog

Latest release Go module reference CI License: Apache 2.0

Go 1.25+ SQLite default PostgreSQL opt-in MCP surface

macOS Linux Docker Deployed on Render

Claude Code Cursor Codex Gemini CLI OpenCode omp

LeanKG


Installation

Prerequisites

None — sqlite is the default storage engine. No Postgres, no Docker.

Postgres remains available as an explicit opt-in (LEANKG_DB_ENGINE=postgres + LEANKG_PG_URL) for server-scale deployments, but nothing in the default flow touches it.

Install

Published module — the engine is a Go module, so the toolchain installs both binaries from pkg.go.dev straight into $(go env GOPATH)/bin:

go install github.com/FreePeak/LeanKG/cmd/leankg@latest         # server + CLI
go install github.com/FreePeak/LeanKG/cmd/leankg-embed@latest   # embedding pipeline

Prebuilt archives — releases carry leankg-<os>-<arch>.tgz for linux/darwin × amd64/arm64, both binaries at the archive root plus a .sha256. leankg update follows the same channel.

From a checkout — requires Go 1.25+ and git; installs to ~/.local/bin (pass a PREFIX to change it):

git clone https://github.com/FreePeak/LeanKG.git && cd LeanKG
scripts/install-go.sh                # or: make install-go

# Or fetch and run the installer directly (clones over HTTPS, same behavior):
curl -fsSL https://raw.githubusercontent.com/FreePeak/LeanKG/main/scripts/install-go.sh | bash

Container

Dockerfile is a three-stage CGO-free build: engine binaries, then a demo graph baked from a slice of this repo (the language examples/, the engine, the dashboard source), then an unprivileged runtime that serves that store read-only. The dashboard build is already embedded in the binary (internal/web/embed), so there is no Node stage.

docker build -t leankg .
docker run --rm -p 8080:10000 -e PORT=10000 leankg   # dashboard + its /api on :8080

This is the image leankg.onrender.com runs: one container, one port, leankg serve --read-only --ui :$PORT.


Get Started

# 1. Per project: one-shot index (sqlite default — zero config, store at .leankg/leankg.db)
cd your-project
leankg index .

# 2. Wire up an AI client — one command (claude-code | cursor | codex | gemini | opencode | omp)
leankg connect claude-code           # stdio entry; --http --url http://host:9699/mcp to reuse a shared server

# 3. ...or serve MCP over HTTP yourself (endpoint /mcp; GET /health returns 200 when ready)
leankg serve --http 127.0.0.1:9699 --rest 127.0.0.1:8080

Self-check any deployment: leankg doctor — prints the store path, element and file counts and the write watermark (exit 0 pass / 2 fail).

MCP over HTTP: the server resolves the project from its process cwd — run it from the checkout or pass --project DIR to pin one.

Measured timings

  • Go cold time-to-first-value (build → index → serve bind → first REST + MCP query): CI budget 300s, gate Cold TTFV, per-run numbers in the ttfv-go-cold artifact — local cold-cache measurement 17.8s (macOS arm64); replaces the Rust-era quickstart_smoke.sh.

Web UI

The embedded dashboard is served by leankg serve --ui ADDR (a ui-v2 build compiled into the binary). The dashboard's /api/* data endpoints are served on the same address; serve --rest exposes the /api/v1/* tool endpoints separately.

For UI development, run the Vite dev server against a REST address (it proxies /api to BACKEND_TARGET, default http://127.0.0.1:8080):

# Terminal A — REST API
leankg serve --rest 127.0.0.1:8080

# Terminal B — hot-reload dev server
cd ui-v2
npm install
npm run dev
# open http://127.0.0.1:5173

Details: ui-v2/README.md · docs/archive/web-ui.md


Enterprise Ready

Peers in this space are mostly personal / single-repo. LeanKG is the company platform: shared index, ops graph, and measured agent economics.

PillarShips as
Multi-repo serverMCP HTTP :9699; LEANKG_PROJECT_DIRS serves many projects with per-request ?project= (REST) / project arg (MCP); sqlite default, PG opt-in
Env governancequery --action env_conflicts, per-env snapshots, leankg obsidian
Ops & ownershipquery --action service_context / incidents, leankg incident / note / team-map
Req ↔ codeleankg prd / prd-trace, query --action prd, ontology traceability matrix
Mega-graphFrontier-local queries; 100k–700k+ elements
Agent surface3 MCP tools (import / query / status) serving 30 actions (22 query + 8 import); peers typically ~1–17 raw tools
CostA/B −65% tokens, −85% tool calls, 2.5× vs grep/cat
CapabilityLeanKGGitNexusGraphifyCodannaContext7
Multi-repo team deployYesPartialLimitedLimitedn/a
Env / incidents / team mapYesNoNoNoNo
PRD traceabilityYesNoPartialNoNo
Mega-graph (100k+)YesPartialViz cappedVariesn/a
MCP surface3 tools / 30 actions~17~10~5docs only

Deep dives (archived): ROI vs Graphify · Competitive one-pager · Research matrix


Why LeanKG?

Agents normally rebuild structure with grep → open files → huge context. LeanKG returns a targeted subgraph (callers, dependents, blast radius, tests, docs) plus the team layer (env, services, incidents, requirements) over MCP.

WithoutWith LeanKG
Many tool calls, large contextSurgical subgraph + TOON (~40% smaller payloads)
No blast radiusSeverity-graded impact
Keyword onlyKeyword + HNSW semantic + ontology
Single-repo guessworkMulti-repo index + ops tools

Key Features

  • MCP-native — search, impact, call graphs, ontology, architecture, team knowledge
  • SQLite default (zero-config — no Postgres, no Docker required) with an opt-in Postgres/pgvector backend (LEANKG_DB_ENGINE=postgres + LEANKG_PG_URL)
  • Ontology — concept catalog + procedural layer (workflows, steps, decision points, failure modes), query --action ontology, POST /api/v1/ontology/match, and req↔code traceability via leankg prd / prd-trace
  • Impact & deps — contains, calls, imports edges; BFS blast radius (leankg impact)
  • Web UI v2 — Force / Tree / Circles explorer (cd ui-v2 && npm run dev; the embedded build is served by leankg serve --ui)
  • Deploy — single CGO-free binary, no runtime deps: Dockerfile builds a read-only demo image for Render, /health answers container probes, and --ui / --http / --rest / --rpc each bind their own address
  • Languages — 40 profiles: Go, Rust, TypeScript/TSX, JavaScript/JSX, Python, Markdown, Java, Kotlin, Swift, Objective-C, Dart, C/C++, C#, PHP, Ruby, Scala, Perl, Lua, Haskell, Elixir, Crystal, CUDA, Cypher, Elm, Erlang, F#, GLSL, HLSL, Nim, OCaml, SQL, PowerShell, Q#, Solidity, SystemVerilog, Verilog, Zig

MCP prefer-order

Discover with query — it routes down the ladder by default (L1 exact → L2 fuzzy → L3 semantic), degrades instead of erroring, and every answer carries retrieval{rung,reason} + freshness.

QuestionHow
Any identifier (default)query "Alpha" (exact, then fuzzy fallback)
Blast radiusleankg impact <file> or query --action impact --to <qn>
Who calls X?query --action callers --to <qn>
How A↔B?query --action path --to <qn>
Element detailsquery --action explain --to <qn>
Pattern searchquery --action pattern --pattern "func $_(...)"
PRD traceabilityleankg prd-trace FR-3T-01
File (compressed)query --action read --path src/main.go

3 tools: import (index/PRD/memory/session/ontology/read) · query (ladder + graph verbs + actions) · status (inventory/freshness/config).


CLI

leankg index .                          # one-shot index -> .leankg/leankg.db
leankg writer                           # index once, then watch + re-index
leankg query "parseConfig"              # name lookup (exact, then fuzzy) — JSON out
leankg query "parseConfig" --compress   # one line per result
leankg impact src/main.go --depth 3     # blast radius of a file or element
leankg status                           # health, inventory, freshness, embed state
leankg doctor                           # store path, element/file counts, watermark
leankg connect claude-code              # MCP entry: claude-code|cursor|codex|gemini|opencode|omp
leankg install --target cursor          # same wiring, flag form (--register-cwd: claude-code hook)
leankg serve --stdio                    # MCP over stdio (what harnesses spawn)
leankg serve --http 127.0.0.1:9699      # MCP over streamable HTTP (/mcp, /health)
leankg serve --rest 127.0.0.1:8080      # REST API (/health, /api/v1/*)
leankg serve --ui 127.0.0.1:8081        # embedded dashboard (/api/* data API served here)
leankg serve --rpc 127.0.0.1:9090       # ConnectRPC (gRPC + gRPC-Web + JSON)
leankg version

UI hot-reload: cd ui-v2 && npm install && npm run dev → http://127.0.0.1:5173

Full usage: leankg help and leankg <command> --help. The archived Rust-era CLI reference: docs/archive/cli-reference.md


Go module

The engine is the root module github.com/FreePeak/LeanKG, versioned by the root vX.Y.Z release tags — so the proxy and pkg.go.dev resolve real versions and go install github.com/FreePeak/LeanKG/cmd/leankg@latest builds the server + CLI straight from source.

Surfaceexactly 3 MCP tools — import / query / status (pinned by internal/mcp/server_test.go). query routes the ladder (L1 exact → L2 keyword/FTS → L3 semantic) and degrades instead of erroring, so every answer carries retrieval{rung,reason} + freshness
StorageSQLite (WAL, FTS5, float32-BLOB vectors, DB-resident watermark) by default; PostgreSQL + pgvector opt-in (LEANKG_DB_ENGINE=postgres + LEANKG_PG_URL) with schema-per-project and per-model HNSW — both behind store.Backend
TransportsMCP stdio · MCP streamable HTTP (--http, /mcp + /health) · REST (--rest, /health + /api/v1/*) · ConnectRPC (--rpc) · embedded dashboard (--ui)
Indexing40 language profiles (internal/langs.Default), AST tiers regex → ast-grep → tree-sitter (behind the tstree tag), 3-signal change detection, writer role with fsnotify reconcile
Embeddingsleankg-embed binary + provider port (OpenAI-compatible / llama.cpp sidecar / deterministic). Every vector writer is ModelStamp-guarded, so a model change fails loudly instead of mixing vector spaces

Layout

cmd/leankg/         serve (stdio | MCP HTTP | REST | RPC | dashboard) · index · writer
                    query · impact · status · doctor · report · connect · install
                    prd · prd-trace · incident · note · obsidian · push · pull · update
cmd/leankg-embed/   run · full · export · import · status
internal/store/     Backend interface + SQLite (WAL/FTS5/watermark) + PGStore (pgvector)
internal/core/      3-tool envelope + L0–L3 ladder + memory/graph routing
internal/index/     extractors, 3-signal detection, call-edge resolution
internal/langs/     the 40 profiles, AST tiers, per-language LSP specs
internal/graph/     impact · path · callers/callees · context · explain · clusters
internal/ontology/  concept catalog + procedural workflows/traceability
internal/mcp/       modelcontextprotocol/go-sdk adapters (stdio + streamable HTTP)
internal/rest/      stdlib net/http REST surface
internal/web/       ui-v2 dashboard via //go:embed (checked-in build) + its /api/*
internal/embed/     provider port, ModelStamp guards, NDJSON export/import
internal/memory/    full-markdown memory + mnemopi bank adapter
internal/watch/     fsnotify reconcile (writer role)
internal/golden/    Rust-vs-Go parity fixtures

Build

go build ./... && go vet ./... && go test ./... -count=1   # CGO-free shape
go build -tags tstree ./...                                # tree-sitter tier (CGO)

The dashboard build under internal/web/embed is checked in and re-synced by make go-ui-assets; its provenance marker is embed/ui-build.json. scripts/test-dual-engine.sh is the SQLite + live-PostgreSQL gate (LEANKG_TEST_PG_URL gates the PG half).

Known limits

  • Call edges are package-scoped. No import/type resolution, so a same-name call in the same package resolves and cross-package dispatch is best-effort; the upgrade path is tree-sitter symbol tables.
  • Heuristic guards, documented in internal/index/relations.go: files ≥ 1 MiB are skipped as vendored/minified bundles, call targets shorter than 4 characters are dropped as noise, and outgoing calls are capped per element and per file.
  • The unit of scope is a repository. A portfolio root (tens of thousands of nested files) is not a project; register its children one at a time.
  • --ui binds an unauthenticated data API (query/read/import routes). Bind it loopback or front it with a proxy — the public demo container serves it --read-only against a disposable baked graph.

Docs

The documentation set lives in docs/ — a single unified PRD (docs/prd.md) + task tracker (docs/prd-task-tracker.md). All historical design docs, analyses, reports, and plans are preserved under docs/archive/.

Doc
PRDUnified product requirements + HLD (single SoT)
Task trackerDone / in-progress / todo
Architecture (archived)Design & data model (historical)
MCP tools (archived)Tool catalog (historical)
CLI (archived)All commands (historical)
Benchmarks (archived)Methodology (historical)
Postgres migration (archived)Engine notes (historical)
AGENTS.mdAgent notes

Troubleshooting

IssueFix
Wrong project servedStart the server with --project DIR (query/impact also honor LEANKG_PROJECT)
Embeddings / cold embedleankg-embed status, then leankg-embed full (provider env: LEANKG_EMBED_*)

Requirements: macOS or Linux · Go 1.25+ only when building from source. No Docker, no Postgres — sqlite is the default store.


Contributing

  1. Fork + feature branch (prefer a worktree)
  2. Update docs when behavior changes
  3. go build ./... && go vet ./... && go test ./...
  4. Open a PR with summary + test plan

License

Apache License 2.0