# sgx A live code knowledge graph that lets an agent ask in symbols instead of reading files: a location, a signature, an outline, a blast radius, a context pack sized to a budget you set — and, after every edit, what that edit broke elsewhere. ## Most of a session is spent locating code, not changing it An agent without an index greps, gets every mention back — definition, import, comment — and reads whole files to tell them apart. It pays for that again after every compaction. `find`, `outline` and `show --level` are the replacement, and each one prints what it cost. ```text $ sgx find login --limit 3 @twtp1 fn login(user: User, opts: LoginOpts = {}): Session src/auth/login.ts:17 @89nj2 iface interface LoginOpts src/auth/types.ts:6 @jwcqd fn testLogin(): void tests/login.ts:3 ``` ## Index once. Then ask in symbols, not files One pass builds `.sgx/graph.db`, a SQLite graph of symbols, edges, git history and notes. Everything after it — the CLI, the MCP server, the Claude Code hooks and the web UI — reads that one graph. ```text $ sgx init --claude initialised .sgx/ in /var/folders/k3/bvwcdygn053bktwwbzm9c8vc0000gn/T/sgx-mini-HIiPLr · indexed 23 of 23 files (+23 ~0 -0) · 23 files · 44 symbols · 68 edges · epoch 1 · 66 ms · history mined .mcp.json: added mcpServers.sgx → /Users/tim/workspace/sgx/dist/sgx mcp .claude/settings.json: added hooks.SessionStart → /Users/tim/workspace/sgx/dist/sgx hook session-start .claude/settings.json: added hooks.PostToolUse (Edit|Write|MultiEdit) → /Users/tim/workspace/sgx/dist/sgx hook post-edit ``` ## A token budget, not a pile of files The expensive part of an agent is not finding code, it is sending too much of it. `context` takes a task and a budget and returns the code worth paying for, in a form that is stable enough to cache. ```text $ sgx map --budget 200 repo map · ~193/200 tok · 25 files · 12 symbols · epoch 2 entry: go/cmd/main.go · py/app/service.py · src/cli.ts go/greeter/ (1 file) @bpayd type Greeter struct greeter.go:4 @b32tr fn New() *Greeter greeter.go:14 ``` ## It tells you before the tests do Three findings an agent cannot see from the file it is editing. All three are real output, and all three are what the `PostToolUse` hook prints when it is not silent. ```text $ sgx check --all warn cycle src/core/a.ts import cycle src/core/a.ts -> src/core/b.ts -> src/core/a.ts ``` ## The prose goes stale silently. Now it does not A repository is not only code. A document declares what it governs in its front matter, the graph carries an edge from it to every file it covers, and `check` reports the ones your change has left behind — in the same hook that reads the code. ```text $ sgx docs --stale docs/auth.md 2 commits behind src/auth/login.ts owner platform 1 stale document ``` ## Read a change as its consequences `impact` combines three kinds of evidence for one target or a whole working diff, and labels which is which rather than merging them into a single confident answer. ```text $ sgx impact login --depth 1 impact @twtp1 login · src/auth/login.ts:17 2 callers in 3 files · 1 test · 1 co-change partner direct: @jb7pz module src/cli.ts:1 imports @eqdyv function main src/cli.ts:3 calls @2pnq2 module src/index.ts:1 imports @kd19m module tests/login.ts:1 imports @jwcqd function testLogin tests/login.ts:3 calls tests: tests/login.ts co-change: src/auth/store.ts support 1.00 (4 commits) ``` ## Find the code whose names never say it The graph is syntactic, so `sgx find auth` misses `SessionStore` and `validateCredentials`. `sgx enrich` judges every eligible symbol into a concept — one request per symbol, three questions each, every answer carrying the model's own confidence. ```text $ sgx where "caching" cache (10) · 4 symbols @h8kcy 100% cache perEpoch src/ui/api.ts:155 @frevc 99% cache getCsr src/context/csr.ts:39 @hkymv 88% cache ensureSynced src/github/sync.ts:88 @m0s0e 87% cache REFRESH_MS src/github/sync.ts:14 ``` ## Deep where it can be, structural everywhere else Nine languages get full symbol extraction with `calls`, `imports` and `tests` edges. Nine more get a compact structural outline, and their local imports, document links, resources and schema references still become edges where the target resolves. ## One graph, four ways in The same answers reach a person and an agent: `sgx `, `sgx mcp`, `sgx hook` and `sgx ui`. Nothing is a wrapper around the CLI — every surface opens the graph directly. ```text $ sgx mcp --schema-cost sgx mcp schema · 15 tools · 6,049 bytes · ~1,513 tok (est.) lookup_candidates 532 B ~133 tok lookup_materialize 697 B ~175 tok find 360 B ~90 tok flavors 301 B ~76 tok outline 291 B ~73 tok show 403 B ~101 tok context 422 B ~106 tok impact 404 B ~101 tok docs 389 B ~98 tok changes 224 B ~56 tok check 310 B ~78 tok where 488 B ~122 tok git 425 B ~107 tok pr 434 B ~109 tok note 353 B ~89 tok ``` ## Mirror what the repository depends on A vendor's API reference or a sibling checkout is not in your tree, so nothing checks your code against it. `sgx source add --as --covers ''` mirrors it into `.sgx/sources/`, indexes it with the ordinary pipeline, and gives it the same `covers:` edge a local document gets. ```text $ sgx source add ../vendor-docs --as vendor --covers 'src/billing/**' --ttl 7d vendor: fetched · 1 file · 131 B $ sgx source list 1 source vendor ../vendor-docs 1 file · 131 B · synced 0s ago · trusted · ttl 1w covers src/billing/** ``` ## See how the agent actually used it Every tool call is recorded in the repository's own `.sgx/graph.db` — which tool, with what arguments, how long it took, how many tokens came back, and what the agent called next. `SGX_USAGE=0` turns it off; nothing is ever sent anywhere. ```text $ sgx usage sgx usage · 8 calls · 2 sessions · 0s ago → 0s ago ~371 tok returned · 87 tok saved by the ledger · 25.0% errors · 1 finding · p50 15ms · p95 75ms tool calls err find p50 p95 tok share saved last find 2 — — 17ms 18ms 212 57% — 0s ago show 2 — — 0ms 1ms 114 31% 87 0s ago impact 1 1 — 15ms 15ms 0 0% — 0s ago index 1 — — 75ms 75ms 23 6% — 0s ago outline 1 1 — 0ms 0ms 11 3% — 0s ago where 1 — 1 15ms 15ms 11 3% — 0s ago what follows what: find → where ×1 find → show ×1 index → find ×1 show → show ×1 show → outline ×1 where → impact ×1 most repeated arguments: 2× show {"handles":["@twtp1"],"fresh":false} 1× outline {"path":"nope/nope.ts"} 1× find {"query":"login","limit":20} 1× where how do we log in 1× find login errors: 1× outline: nothing indexed at 'nope/nope.ts' 1× impact: sgx impact: needs a target (handle, path#name, name or file) or --diff sessions: session client calls err find tok last tools e4132ffc mcp/claude-code 4 1 — 232 0s ago show outline find cli:3420 cli 4 1 1 139 0s ago where index impact find ``` ## Then change the instruction that allowed it `sgx usage` cannot see what the agent did *instead* — an agent that never calls sgx looks perfect there. `sgx improve` reads the agent's own transcript beside the telemetry, ranks the workarounds by what they cost, and with `--apply` rewrites the guidance the next session is given. ```text $ sgx improve sgx improve · 52 sgx calls · 948 agent tool calls across 10 sessions 361 of them were questions sgx answers, costing ~195k tok of the agent's context ! displaced: the agent read a whole file 196× here, costing ~152k tok (~774 a call) · `show` cost ~1.4k tok a call here → route it to `show` / `outline` cat docs/telemetry.md && ls src/telemetry/ git diff --stat && sed -n '1,80p' src/telemetry/record.ts ! displaced: the agent searched with grep 145× here, costing ~36k tok (~251 a call) · `where` cost ~145 tok a call here → route it to `where` / `find` ! stale: `where` was called 5× with no semantic layer built (1,532 symbols eligible) → `sgx enrich` · costly: `check` returned 62% of every token sgx gave the agent (~37k tok over 14 calls) → tune its defaults, or give it a smaller budget when the agent calls it ``` ## Ask one repository, or everything you work on Repositories group into projects and projects into workspaces, and `--repo`, `--project`, `--workspace` or `--all` widens any command across them. Each repository still keeps its own graph and still works entirely on its own — the registry above them is one SQLite file holding no symbols. Delete it and nothing breaks. ```text $ sgx index --all app indexed 2 of 2 files (+2 ~0 -0) · 2 files · 1 symbols · 0 edges · epoch 1 · 58 ms · history mined ui indexed 2 of 2 files (+2 ~0 -0) · 2 files · 1 symbols · 0 edges · epoch 1 · 57 ms · history mined $ sgx repo link 2 repositories · 2 published packages · 1 cross-repo links $ sgx workspace show workspace acme · 1 project · 2 repositories · 4 files · 2 symbols · 0 edges platform/ app 2 files 1 symbols main epoch 1 publishes @acme/app ui 2 files 1 symbols main epoch 1 publishes @acme/ui cross-repo imports app → ui @acme/ui 1 file ``` ## Fast enough for the edit loop, cheap enough to keep asking A deterministic corpus of 2,000 source files and 100,000 lines, TypeScript, Python and Go, with cross-file calls and 160 test files. `bun run bench --check` exits nonzero if any latency reaches twice its target. ```text machine: Tims-MacBook-Pro-2.local · Apple M5 Pro · darwin/arm64 · Bun 1.4.2 corpus: 2,000 source files · 100,000 lines · TS 1,600 / Python 200 / Go 200 · 160 TS test files · cross-file calls and classes timings: core library over one graph handle; cold includes parsing, inserts, resolution and git; hook includes binary startup; no warmup samples discarded cold index: 522.45 ms · target 4000 ms · check < 8000 ms PASS graph: 2001 files · 5200 symbols · 5500 edges no-op refresh: 40.64 ms p50 (n=21) · target 150 ms · check < 300 ms PASS one-file edit → committed epoch: 28.20 ms p50 (n=21) · target 25 ms · check < 50 ms PASS find: 0.16 ms p50 (n=21) · target 5 ms · check < 10 ms PASS outline: 0.05 ms p50 (n=21) · target 5 ms · check < 10 ms PASS show: 0.03 ms p50 (n=21) · target 5 ms · check < 10 ms PASS impact depth 3: 0.10 ms p50 (n=21) · target 20 ms · check < 40 ms PASS context 4k: 1.66 ms p50 (n=21) · target 60 ms · check < 120 ms PASS full files vs outlines (entire corpus): 3637333 → 398650 bytes · saved 3238683 bytes (89.0%) · estimated tokens 910381 → 97890 (~4 chars/token) naive target + callers vs context (20 targets, depth 3, 4k budget): 145331 → 150653 bytes · saved -5322 bytes (-3.7%) · estimated tokens 36337 → 37393 (~4 chars/token) 30-call show replay (10 targets, one body edit), without vs with ledger: 18933 → 7945 bytes · saved 10988 bytes (58.0%) · estimated tokens 4749 → 1988 (~4 chars/token) post-edit hook process start → exit: 140.20 ms p50 (n=9) · target 150 ms · check < 300 ms PASS ``` ## What holds, what is a judgement, what is not here Two things leave the machine and nothing else does: the GitHub sync, and `sgx enrich` with `where --route`. Both are explicit, both stop at `SGX_OFFLINE=1`, and both replay from recorded files in the test suite. The columns below are the same list the boundaries section keeps. ## Before you index anything ## Install it, index something, ask it a question From a checkout: `bun link` registers `sgx`, and `sgx init --claude` indexes and wires the agent up. The package is private and installed from source, so there is no registry release to pull. ```sh bun install bun run build # standalone binary: dist/sgx, with WASM, workers and UI embedded bun link # registers sgx -> src/cli.ts; requires this checkout and Bun cd /path/to/your/repository sgx init --claude # index and merge repository-local Claude Code configuration sgx init --codex # the same, for Codex (.codex/config.toml) sgx init --fx # the same, for fx (.mcp.json and AGENTS.md) sgx find login sgx source add https://docs.example.com/api.md --covers 'src/api/**' sgx ui ``` ## Links - Reference (the full README): https://sgx.sh/reference - Repository: https://github.com/TimMikeladze/sgx - Agent guide: https://sgx.sh/AGENTS.md