Try Tools · Dev
Graphify: what happened when we tested it
Turns a codebase into a knowledge graph your AI coding assistant can query instead of grepping files.
Score
10.0/10
claims that held up
Verdict
V2 · Works as claimed41
Access needed
L0 Public web onlyTested 2026-10-21
Rule set before testing: the worst of offline/no-LLM, determinism, cross-file links and query/path/explain. All four were V2. The benchmark claim was not testable (V0) but is not a core claim, so it does not cap the verdict.
Scope. We tested the code graph on a 10-file project we wrote (Python and TypeScript, 16 known links) plus spot checks on the requests library. Large monorepos, the other ~38 languages, the LLM pass over docs/PDFs/media and the benchmark numbers were not tested.
The free local code graph did what the README says on our test project: it built fully offline with no API key and no network calls, gave byte-identical output on every run, found 16 of 16 known imports, calls and inheritance links with no false ones, and query/path/explain gave correct answers and exit codes. Benchmarks not tested.
16/16
known cross-file links found
imports, calls, inheritance; 0 false edges
0
network calls while building
strace, and same graph with no network at all
3/3
builds byte-identical
same sha256 every run
5/5
query / path / explain checks right
incl. exit 3 ambiguous, exit 4 not found
Claim by claim
Code graph is built locally with tree-sitter: no LLM, no API key, fully offline, nothing leaves your machine, no telemetryWorks
0 network system calls under strace; same graph with no network at all; no keys set; only local git child processes. When opened in a browser, graph.html loads its drawing library from unpkg.com (no data is sent).
DeterministicWorks
3 builds of our project gave a byte-identical graph.json; 2 builds of the requests source did too.
Cross-file calls / imports / inherits resolved via tree-sitter, each edge tagged EXTRACTED or INFERREDWorks
16 of 16 known links in Python and TypeScript, 0 false edges, every edge tagged. We tested 2 of ~40 languages. On the requests source a call through an adapter chosen at run time was missing, as you would expect from static parsing.
query / path / explain against graph.json; ambiguous names refused with candidates (exit 3), no match exit 4Works
5 of 5 planned questions right, with the documented exit codes. Caveats from the extra run: the plain-language query returns a broad subgraph, and on the requests source one path lookup with a wrong node id guessed on a tie (warning printed, exit 0) instead of refusing. Exact names or path::symbol worked.
Benchmarks: LOCOMO 0.497 recall@10, LongMemEval-S 76%, ERPNext 82.0% vs grep 70.8%Not testable
Needs the vendor harness plus an LLM answerer and judge. Not run; not a core claim.
Open a claim to see what we measured.
The full report
Full result
Works as claimed for the free, local code graph. On a test project with known answers it built offline with no key and no network traffic, gave the same file every time, found all 16 cross-file links without a single false one, and answered path, explain and lookup questions correctly with the documented exit codes. On a real library (requests) it was fast (about 1 s for 573 nodes) and the main call chain was there, but calls decided at run time are missing, as with any static parser. We did not test the memory benchmarks, the LLM pass over docs and media, or the paid Cloud product.
The test task and exact input
Fixed before installing (plan committed 14:03 UTC+8): we wrote a small 2-language project (7 Python files, 3 TypeScript files) with 16 known cross-file links (7 imports, 5 function calls, 2 constructor calls, 2 inheritances) and two unrelated functions both named helper as decoys. Core claims and pass marks: C1 offline/no LLM: build with no API keys under strace and in a network namespace with no network, 0 outside connections. C2 deterministic: 3 builds on fresh copies, identical nodes and edges. C3 cross-file links: 15+/16 found, 0 false edges, every edge tagged. C4 query/path/explain: 5 of 5 fixed questions right (a known 3-hop call path, an inheritance lookup, an ambiguous name refused with exit 3, a missing name exit 4, a plain-language question returning the right functions). Benchmarks: reported, not core, not testable here.
uv tool install graphifyy graphify extract ./corpus graphify cluster-only ./corpus graphify path "checkout" "round_money" graphify explain "AdminUser" graphify explain "helper" graphify explain "nonexistent_zzz" graphify query "how is tax applied to the cart total?"
What happened, step by step7 steps
- Captured the README claims and the pricing page, wrote the test project, ground truth and pass marks, committed them (14:02-14:03)
Observed: Repo: 130,555 stars, Apache-2.0, pushed the same day. PyPI latest 0.9.93. - Installed with uv tool install graphifyy (14:03)
Observed: 30 packages (tree-sitter plus 20+ language grammars, networkx, numpy) in under 1 second. - C1: graphify extract with no keys, traced with strace; then again inside a network namespace with no network; then cluster-only for the report (14:03-14:05)
Observed: 32 nodes, 48 edges in both runs. 0 connect/send system calls of any kind. The only child processes were 3 local git commands (gitignore list, current commit). With no network at all it still built the same graph in 0.4 s. cluster-only said 'no LLM backend configured' and kept going offline. - C2: 3 builds on 3 fresh copies (14:05)
Observed: graph.json byte-identical (same sha256) all 3 times; the report differed only in the folder path it prints. - C3: compared every edge with our ground truth (14:05)
Observed: 16 of 16 links found, all tagged EXTRACTED. 0 false edges; nothing linked to the helper decoys. It also found checkout() -> Cart.add() (marked INFERRED, correct). It missed final_price() -> Cart.subtotal(), which needs type information (optional, not counted). - C4: ran the 5 fixed questions (14:06)
Observed: path: checkout() -> final_price() -> apply_tax() -> round_money(), exactly the expected 3 hops. explain AdminUser: inherits User, imported by api.ts, called by makeAdmin(). explain helper: refused, both files listed, exit 3. Unknown name: exit 4. Plain-language question: subgraph with apply_tax() and final_price(), but it was broad (23 of 32 nodes, started from Cart, tax.py and renderTotal()). - Extra, not scored: the requests 2.32.3 library source (18 files) (14:05-14:06)
Observed: 573 nodes, 1,070 edges in about 1 s; identical on a second run. Known chain get() -> request() -> Session.request() -> Session.send() was all there (one hop marked INFERRED). Session.send() -> HTTPAdapter.send() was missing: the adapter is picked at run time, which static parsing cannot see. One lookup guessed: a path query with a node id that does not exist matched the Session class on a tie, printed a warning and still answered (exit 0).
Failure modes seen4 items
- Static parsing misses calls decided at run time (requests: Session.send() -> HTTPAdapter.send() through get_adapter()).
- A path lookup with a wrong node id guessed a node on a tie (warning printed, exit 0) instead of refusing; explain with the same kind of name said 'no node' (exit 4).
- The plain-language query returned 23 of 32 nodes for a narrow question: useful context, not a pinpoint answer.
- README is out of date in two places: it says every query is logged to ~/.cache/graphify-queries.log (in 0.9.93 that is opt-in; nothing was written), and 'graphify extract' alone gives only graph.json; run 'graphify cluster-only' for the report and graph.html.
Evidence files13 files
- File: Test plan, ground truth and pass marks, committed before installing
- File: Vendor claims and pricing as captured
- File: Our test project (10 files)
- Log: Install log
- Log: C1: strace and no-network runs
- Log: C2: 3 builds, sha256 compare
- File: C3: every ground-truth link and extra edge
- File: C3: scoring script
- File: The graph Graphify built for our project
- File: Graphify's report for our project
- Log: C4: path / explain / query outputs and exit codes
- Log: Extra: requests library, timing and spot checks
- File: Not tested, README vs code notes
Vendor claims, as quoted
- "Code is parsed with tree-sitter AST: deterministic, no LLM, nothing leaves your machine." ... "A code-only corpus requires no API key: graphify extract runs fully offline." ... "No telemetry, no usage tracking, no analytics." (source)
- "Cross-file links: calls / imports / inherits / mixes_in resolved across ~40 languages via tree-sitter AST"; "Each connection is tagged EXTRACTED (explicit in the source) or INFERRED (resolved by graphify)" (source)
- "Query, path, explain: Ask a question, trace the path between two things, or explain one concept, all against graph.json"; "A name that matches several nodes is refused with the candidates listed rather than guessed" (exit code 0 answer, 3 ambiguous, 4 no match) (source)
- Benchmarks: LOCOMO recall@10 0.497 (QA 45.3%), LongMemEval-S QA 76%, ERPNext key-fact coverage 82.0% vs grep/read 70.8% (source)
Lowest-access way to try it
L0 for code. uv tool install graphifyy, then graphify extract ./your-repo (no key needed for code; add --code-only on mixed repos so docs are skipped) and graphify cluster-only ./your-repo for the report and graph.html. Query with graphify path / explain / query. Day to day you point it at your own code (L1); docs, PDFs and media are sent to an LLM backend only if you configure one.
Details: vendor, pricing, environment, time, cost
Not sponsored. No affiliate links. Vendors do not see results before they are published.
How to cite
TriedAgents, "Graphify: tool test", works as claimed, tested 2026-10-21, https://triedagents.com/tools/graphify/
Get one re-run case every weekday
One agent use case we actually re-ran, every weekday. Free.
We only store your email address. Every issue has a one-click unsubscribe link. Privacy