# 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 <command>`, `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 <uri> --as <name> --covers '<glob>'` 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
