deterministic · offline · $0 to index
Stop your coding agent reading whole files.
seonix turns a repository into a typed code graph your agent can ask directly — paired with a short guidance note, it edits from turn 1 instead of fishing through the repo. Built offline, $0.
Status, 2026-07-28. The shipped default pairs the live seonix_ask
MCP tool with a token-discipline guidance file, measured against an
out-of-the-box agent given the same guidance. No cell clears the ≥50% bar
yet (ts-hono·response-time Haiku 13%, Sonnet 28%;
eshoponweb·order-service Haiku 6%, Sonnet 12%), but every cell
is a real, positive reduction with no solve-rate regression. Full grid,
traces, and method in
BENCHMARK_0.11.10 ↗.
Paired-arm benchmark: same model pin, N≥3 runs, mean input tokens over the tasks both arms solved, index cost counted separately, no drop in solve rate. Any win depends on the model and the codebase. A leaner agent, or a repo small enough to hold in context, has less to displace. Full method: BENCHMARKS ↗.
How it works
seonix reads your repository into a typed graph: the modules, classes, functions, methods and attributes a change touches, and how they connect. It follows the published seonix schema.
-
1 · Build the graph
Point seonix at a repository and it derives that typed graph offline. Same commit → the same graph every time. Nothing leaves your machine.
-
2 · Find the change site
From your task description, seonix ranks the parts of the graph the change touches, with no human-chosen target. Already know the file? Hand it in directly.
-
3 · Hand over the digest
seonix renders a bounded edit digest (the signatures, call sites and insertion regions your agent needs) and hands it over at the start of the session. The agent edits from turn 1 instead of exploring; the render is deterministic and costs $0.
See it run
One real task, run twice on the same rig that produces every number here. It shows the mechanism on one cell. The grid below is the evidence.
=== proof-demo: otb vs seonix, one real task, one cheap model, n=3 (mean) ===
suite=eshoponweb task=order-service-total model=claude-haiku-4-5
$ node bench/run.mjs --suite eshoponweb --arms otb --models claude-haiku-4-5 --runs 3 --instance order-service-total
mean turns=9.0 mean input_tokens=288,796 mean cost=$0.0660 errors=0/3
run 1 actions (representative):
· Agent()
· TaskOutput()
· Bash("find <repo> -type f -name "*.cs" | grep …")
· Read(Interfaces/IOrderService.cs)
· Read(Services/OrderService.cs)
· Read(Specifications/OrderWithItemsByIdSpec.cs)
· Read(Interfaces/IOrderService.cs)
· Read(Services/OrderService.cs)
· Edit(Interfaces/IOrderService.cs)
· Edit(Services/OrderService.cs)
$ node bench/run.mjs --suite eshoponweb --arms seonix --models claude-haiku-4-5 --runs 3 --instance order-service-total
mean turns=6.0 mean input_tokens=263,790 mean cost=$0.0659 errors=0/3
run 1 actions (representative):
· Edit(Interfaces/IOrderService.cs)
· Read(Interfaces/IOrderService.cs)
· Edit(Interfaces/IOrderService.cs)
· Read(Services/OrderService.cs)
· Edit(Services/OrderService.cs)
--- headline (mean of 3 runs per arm) ---
input tokens: otb 288,796 → seonix 263,790 (-8.7% fewer)
turns: otb 9.0 → seonix 6.0
billed cost: otb $0.0660 → seonix $0.0659
(one task, n=3 per arm, one cheap model — illustrative, not the full benchmark grid; solve-status is graded by the real pipeline, not this quick script — see the results table above for the measured, paired-arm numbers this site actually cites.)
Repeatable: npm run proof reruns both arms for real and regenerates this
capture. Nothing here is staged or hand-edited.
Ask the graph a question, from a terminal, with no model in the loop:
$ node packages/seonix/bin/cli.mjs cli seonix_ask '{"query":"which modules import walk.mjs"}' | jq -r '.matches[].label'
packages/seonix/src/cs_treesitter.mjs
packages/seonix/src/extract.mjs
packages/seonix/src/java_treesitter.mjs
packages/seonix/src/jsts_tsc.mjs
packages/seonix/src/manifest.mjs
scripts/verify-counts.mjs
seonix_ask runs tmct's deterministic, no-LLM engine over the graph. It returns
JSON, so it pipes straight into jq, a script, or another tool.
Or hold a conversation. A real seonix chat transcript against this repo's own index:
tmct> which modules import walk.mjs
packages/seonix/src/cs_treesitter.mjs and packages/seonix/src/extract.mjs and packages/seonix/src/java_treesitter.mjs and packages/seonix/src/jsts_tsc.mjs and packages/seonix/src/manifest.mjs and scripts/verify-counts.mjs.
tmct> where is buildContextBundle defined
function buildContextBundle() is defined in packages/seonix/src/server.mjs at lines 139-261.
tmct> when did walk.mjs change
packages/seonix/src/walk.mjs was last touched by commit 541d91db47f3 on 2026-07-04 ("feat(seonix): seonix.toml config loader […]"); 2 earlier commits recorded.
seonix chat runs tmct (@polycode-projects/the-mechanical-code-talker),
a deterministic no-LLM chatbot, over seonix's graph. Every answer is grounded in the graph or
an honest miss — no model in the loop.
Benchmarks
Current cycle — Benchmark 0.11.10
The shipped default pairs the live seonix_ask MCP tool with a
token-discipline guidance file (seonix-ask-guidance), measured
against an out-of-the-box agent given the same guidance
(otb-guidance), environment-isolated so a host's own global
config can't leak into either side. No cell clears the ≥50% bar yet, but
every cell is a genuine, positive reduction with no solve-rate regression —
and the tool actually gets used now: seonix_ask fired in 75% of
runs, up from 5% the cycle before pairing it with guidance. Full method,
traces, and negative results in
BENCHMARK_0.11.10 ↗.
| Task | Haiku 4.5 | Sonnet 4.6 | ||
|---|---|---|---|---|
| otb | ask | otb | ask | |
| TypeScript — hono | ||||
| ts-hono-response-time-middleware | 1598k | 13%1383k | 1000k | 28%720k |
| C# — eShopOnWeb | ||||
| cs-eshoponweb-order-service-total | 585k | 6%549k | 326k | 12%288k |
All four cells solved 5/5 both arms — no solve-rate regression anywhere.
seonix_ask calls per run (mean of 5): ts-hono Haiku 1.8, Sonnet
0.6; eshoponweb Haiku 1.8, Sonnet 4.0. 15 of 20 runs called it at least once,
up from 1 of 20 the cycle before pairing it with guidance — the tool is used
now; the remaining gap is that using it once doesn't reliably keep the rest
of the run cheap. Trace appendix in
BENCHMARK_0.11.10_TRACES ↗.
Quickstart with Claude Code
seonix is a Node package (ESM, Node ≥ 24) that shells out to Python 3
and git, both on PATH. Four steps take Claude
Code from grepping the tree to editing from turn 1.
-
Install the
seonixCLI:npm i -g @polycode-projects/seonix -
Build the graph (deterministic, offline, $0):
seonix cli index_repository '{"repo_path":"/abs/path/to/repo"}'This writes the typed code graph to
.seonix/graph.json(plus a.seonix/TOOLS.mdtool catalog). Same commit → byte-for-byte identical graph. -
Render a bounded edit-digest for the modules a task touches and save it where the agent can read it:
# which modules does the change touch? (ranked, no LLM) seonix cli seonix_locate '{"repo_path":"/abs/path/to/repo","query":"<your task>"}' # render the digest for those modules → save it under .seonix/ seonix cli digest '{"repo_path":"/abs/path/to/repo","modules":["src/pkg/module.py"]}' > /abs/path/to/repo/.seonix/digest.txt -
Put the digest in front of the agent at session start. Wire a Claude Code
SessionStarthook that adds the rendered digest to the session context (or paste it at the top of aclaudesession):# .claude/settings.json — inject the digest once, at session start { "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "cat .seonix/digest.txt" } ] } ] } }The digest is in context from turn 1, so the agent edits without exploring first. No MCP server, no tool loop: the saving comes from the digest arriving up front rather than from an interactive round-trip.
Copy-paste setup
The same four steps as one block per tool, with the permission rules that let the agent run seonix without prompts.
Claude Code
# install + index (offline, $0)
npm i -g @polycode-projects/seonix
cd /path/to/your/repo
seonix cli index_repository "{\"repo_path\":\"$PWD\"}"
# locate the change site, render the digest
seonix cli seonix_locate "{\"repo_path\":\"$PWD\",\"query\":\"<your task>\"}"
seonix cli digest "{\"repo_path\":\"$PWD\",\"modules\":[\"src/pkg/module.py\"]}" \
> .seonix/digest.txt
# .claude/settings.json — inject at session start; allow seonix
# to run un-prompted via the permissions framework
cat > .claude/settings.json <<'JSON'
{
"permissions": {
"allow": ["Bash(seonix:*)", "Read(.seonix/**)"]
},
"hooks": {
"SessionStart": [
{ "hooks": [ { "type": "command",
"command": "cat \"$CLAUDE_PROJECT_DIR/.seonix/digest.txt\" 2>/dev/null || true" } ] }
]
}
}
JSON
The hook puts the digest in context from turn 1; the
permissions.allow rule lets the agent re-run
seonix (re-index, re-locate, re-render) without an
approval prompt.
GitHub Copilot (VS Code agent mode)
# install + index + digest — same commands
npm i -g @polycode-projects/seonix
cd /path/to/your/repo
seonix cli index_repository "{\"repo_path\":\"$PWD\"}"
seonix cli digest "{\"repo_path\":\"$PWD\",\"modules\":[\"src/pkg/module.py\"]}" \
> .seonix/digest.txt
# .github/copilot-instructions.md — Copilot reads this file
# automatically at the start of every chat/agent task
cat >> .github/copilot-instructions.md <<'MD'
Before exploring the codebase, read `.seonix/digest.txt` — it is a
pre-built edit digest (signatures, call sites, insertion regions) for
this repository. Re-render it with:
`seonix cli digest '{"repo_path":"<abs repo path>","modules":[...]}'`
MD
# VS Code settings.json — allow seonix in the terminal
# tool without a confirmation prompt
"chat.tools.terminal.autoApprove": { "seonix": true }
Copilot has no session-start hook, so injection is by reference:
the instructions file (read automatically) points the agent at the
digest, and the terminal auto-approve setting lets it run
seonix itself without a prompt. Check the setting name
against your VS Code version; the terminal allow-list has been
renamed between releases.
Or paste one prompt into chat. It works for Claude Code, Copilot, or any tool-calling agent; the agent reads its own capabilities and skips whatever doesn't apply:
Install seonix globally (`npm i -g @polycode-projects/seonix`), then index
this repository by running `seonix cli index_repository` with
`repo_path` set to this repo's absolute path. Render its edit digest to
`.seonix/digest.txt` with `seonix cli digest`.
Then configure yourself to load that digest automatically, using
whichever of these applies to you — check your own docs/settings and
skip what doesn't exist:
- If you support a session-start hook (e.g. Claude Code's
`.claude/settings.json` → `hooks.SessionStart`), add one that `cat`s
`.seonix/digest.txt` into context (no-op if the file is missing), and
add `"Bash(seonix:*)"` + `"Read(.seonix/**)"` to `permissions.allow`
so you can re-index/re-locate/re-render yourself without a prompt.
- If you don't have a hook but read a standing instructions file (e.g.
Copilot's `.github/copilot-instructions.md`), append a note there
telling yourself to read `.seonix/digest.txt` before exploring the
codebase, and enable running `seonix` in your terminal/tool-call
allow-list without a confirmation prompt (e.g. VS Code's
`chat.tools.terminal.autoApprove`).
Verify by starting a fresh session and confirming the digest text is
present in context or referenced correctly.
Prefer an interactive tool? seonix also runs as a local server. The digest path above is the recommended one, and the one the benchmarks measure. Everything runs against your local checkout with no network calls. The graph rebuilds from source, so keep it out of version control.
Configure & tune
No server to run
The recommended path hands the agent one pre-rendered digest and runs it with no server attached. That is the shape the benchmarks measure and the one that deploys cleanly. An interactive mode is there if you want it.
Automatic, or point it yourself
seonix picks the change site straight from your task description, with no human in the loop. Already know the file? Name it directly and skip the search.
Deterministic & cache-stable
The same commit always produces the same graph, so rebuilds are reproducible and the digest stays cache-stable; prompt caching keeps repeat turns cheap.
Cost & privacy
Building the graph and querying it cost $0 beyond CPU and disk: no model calls, no API keys, no cloud. seonix runs entirely on your machine and never phones home.
seonix, indexing itself
The graph below is a live seonix viz render of seonix's
own code graph, the same typed-edge structure it builds for any repo
you point it at.
Visualisation loads here. If it doesn't, open the graph directly ↗ or view the commit timeline.
Chronograph — read the codebase as it moves
The same typed graph, scrubbable through time. Drag the timeline and the
architecture grows commit by commit. Click a symbol for its biography.
Compare pins two cursors and shows what the range added, changed
and rewired, with a per-commit narration and no model calls. The whole
view lives in the URL, so any state is a shareable link. Run
seonix viz --serve to serve this page against your own repo
at /code-browser.html.