Inspect · Verify · Approve

The evidence layer for AI coding agents

Your agent can change forty files in a minute. Nothing on your machine can tell it what those changes reach — so it reads, guesses, and sounds certain either way. Euthynos answers structurally, and names the boundary of every answer.

npm install -g euthynos
See what it answers

agentI'm about to change serialize. What reaches it?

9 transitive callers of serialize:

  d1 fetch — src/client/client.ts:58
  d1 generateCookie — src/helper/cookie/index.ts:78
  d2 hc — src/client/client.ts:137
  d2 setCookie — src/helper/cookie/index.ts:99
  d3 testClient — src/helper/testing/index.ts:21
  d3 deleteCookie — src/helper/cookie/index.ts:141
  d3 cacheLanguage — src/middleware/language/language.ts:221
  d4 detectLanguage — src/middleware/language/language.ts:238
  d5 languageDetector — src/middleware/language/language.ts:292

For the exact call-site lines with their source: find_references({ symbol: "serialize" }).

Watch it run

One command, on a repository you can check.

A recording of real output, not a mock-up. Clone hono at 26de7313, run the same command, and the numbers should match.

hono — 382 files
$

        

Health 68 is not a grade to fix — it is five measured signals with their inputs named. Leverage 36 says most exported surface has few callers. Locality 88 says related changes already land together. These 382 files scan once; the index is content-addressed, so the next scan only re-reads what changed.

The shift

Writing code stopped being the bottleneck. Verifying it started.

An agent that can produce a refactor in seconds still has no structural picture of the repository it is editing. It compensates the only way it can — by reading files until the context window fills.

01

Reading is not understanding

Opening forty files tells an agent what the code says, not what depends on it. Inbound edges are invisible from the file you are looking at.

02

Confidence is not calibrated

A model that missed a caller sounds exactly like a model that found them all. Nothing in the transcript distinguishes the two.

03

The reviewer is now the human

When generation is cheap, the scarce resource is a person deciding whether a change is safe to ship — with whatever evidence they were handed.

The evidence model

It refuses to tell you your change is safe.

Euthynos is a static analyser. It sees imports, declarations and call edges — not reflection, not dynamic dispatch, not production. So it never claims otherwise. Every answer carries the boundary of the method that produced it, and every empty answer says what was not examined rather than implying nothing exists.

Claims the engine will not make

this change is safe all references no other consumers fully tested unused — safe to delete no impact mathematically proven

These are enforced by the test suite, not by style guide. A change that lets any of them reach a user is a failing build.

Tiered, and labelled

Structural resolution establishes facts. Name conventions and text matches discover candidates. The two are never presented as the same thing.

Exclusions are stated

Files skipped for size, ignore rules or parse failure are counted and reported. A narrowed answer says it was narrowed.

Capabilities

Twenty-three read-only tools, over MCP.

Your agent calls them the way it calls any other tool. Nothing is written to your repository except a gitignored index that is safe to delete at any time.

QuestionToolEvidence it returns
What reaches this function?callers_ofTransitive callers with depth and location
What does my edit touch?check_my_changesChanged symbols, blast radius, tests, stated scope
Which tests relate to this?tests_forRoute-labelled test files — never a coverage claim
Does this already exist?similar_logic_existsNear-duplicate implementations with both spans
What is this repository?repo_mapModules, sizes, structural signals, health
Did I cross a boundary?boundary_checkDeep-import violations introduced by the diff

Plus symbol and reference lookup, callees, module dependencies and dependents, path-between, context bundles, and span-accurate source reads. 16 languages parse — call-graph resolution is strongest in TypeScript.

Measured, not asserted

We preregistered the benchmark before running it.

Answer keys frozen by commit. Sessions gated. Recall hand-graded against those keys before anyone looked at the transcripts. Here is what it showed — and what it did not.

42 / 42
Required answer-key items recalled — identical with and without Euthynos, on the three fully-measured tasks.
13–31% fewer
Fresh input tokens on those same tasks, per-task medians, for the same graded answers.
21 / 42
Sessions that survived the preregistered validity rules. The other 21 are reported, not hidden.
Grouped bar chart of median fresh input tokens per task. callers: baseline 70,878 versus euthynos 49,476, 30 percent fewer. similar-logic: 33,429 versus 29,120, 13 percent fewer. blast-radius: 56,481 versus 39,242, 31 percent fewer. Recall was identical and complete in both arms on all three tasks.
Median fresh input tokens, n=3 valid sessions per cell, on the three fully-measured tasks. Recall under each bar pair is the answer-key slot count — the same in both arms, which is what makes the token gap a saving rather than a trade.

What this does not show. Two of the seven tasks were never measured — an external session limit consumed them, and they stay unmeasured rather than being quietly dropped. One repository, one model, one permission environment. No causal isolation of individual tools. The benchmark also found a real defect in our own call graph, which the released engine ships fixed. Full preregistration, results and caveats are in the repository.

Runs where your code is

Local, read-only, and offline by default.

Your source never leaves

There is no upload path in the query loop. No account, no network dependency, no telemetry sent anywhere.

Hostile-repo hardened

Symlinks are never followed, paths are containment-checked, and git runs with hooks, filters and exotic transports disabled.

Derived state is disposable

The index verifies itself against the repository it describes. If integrity cannot be established it is rebuilt, and it says so.

Honest envelope. Validated to roughly 10,000 files, comfortable well below that. Memory is the binding constraint above it. The measured numbers, including where it stops, ship with the package.

Give your agent something better than a guess.

One command to install, one to register it with your agent. Apache 2.0 licensed.

npm install -g euthynos
claude mcp add euthynos -- euthynos mcp