When a coding agent meets an API it does not know, it guesses, fails, and guesses again — each lap burning the expensive kind of token. Reference-coding fixes that: clone the libraries that already solved your problem, index them with XERJ, and retrieve the real implementation before writing code. We measured it across 13 purpose-built libraries in 5 languages against the same Claude Code. Below is the one prompt that turns it on — and every number behind it.
Install XERJ (docs: https://xerj.org/llms.txt), index this project's sources, and set up reference coding: clone and index the open-source repos closest to what we're building, and search how they solved a problem before writing code.
Set me up for reference-coding with XERJ and then use it automatically for the rest of our work, so I stop burning output tokens re-deriving APIs I could just look up. 1. Make sure a local XERJ instance is running and the `xerj-code` skill is available. If XERJ isn't installed, get it from https://xerj.org/get (curl -fsSL https://xerj.org/get | sh) and start it. 2. Look at this project — its dependencies, the domains its code touches — and decide which well-known open-source libraries already solve those problems. Clone them into a reference corpus with the skill's xc-corpus.sh, grouped by problem domain, not by language. 3. Index that corpus with xc-index.sh (it runs `xerj autoindex`). 4. From now on, for every coding task this session: before writing non-trivial code against an unfamiliar or external API, first run xc.py <corpus> "<what you need>" to retrieve the real implementation, read the returned definition, and adapt it — cite file:line, check the licence. If retrieval returns nothing relevant, say so and fall back to normal work. 5. Re-index whenever the references change. Do this proactively for the rest of the session without me asking again.
bare = Claude Code with tools off (memory only) · native CC = Claude Code as-is, greps the source · XERJ = the SAME agent, reference retrieved and injected · cost $11.18 / $3.27 / $1.58 · NOT A LATENCY BENCHMARK
xc-corpus.sh shallow-clones the reference repos, grouped by problem domain.xc-index.sh runs xerj autoindex; retrieval is O(1) regardless of tree size.xc.py <corpus> "…" returns the exact definition with its contract; the model reads a passage instead of re-deriving.xc-corpus.sh shallow-clones them into a named corpus. Each repository's licence
is recorded in corpus.json; GPL/AGPL entries are approach-only — read the design,
never copy the code.xc-index.sh runs
xerj autoindex: every file is sniffed by content, and source files go through
tree-sitter grammars (13 languages) that emit the language, every symbol with its kind and line number, a
searchable defs field, and the full body. One index per dataset, incremental on
re-runs — re-index when the references change.xc.py runs
BM25 multi_match over body,
defs and title — with a measured (not hand-picked)
boost on defs so exact symbol names outrank prose — RRF-fused with a vector arm
where an index supports it. When no index does, it degrades to BM25-only and says so; a silently
lexical-only "hybrid" would be a lie. The default embedder is lexical feature-hashing — vocabulary overlap,
not neural understanding.file:line, adapts it,
cites the source, and checks the licence. If nothing relevant comes back it says so and falls back to normal
work — forcing a bad match in is worse than not retrieving.You cannot measure retrieval on code the model has memorised — it reproduces even a 256-value table from memory. So the unfamiliar corpus is 13 real libraries written for this study (each compiles and passes its own tests), each carrying a runtime contract the compiler cannot warn about. Each task returns the library's own type, so a hand-rolled workaround cannot pass. bare = from memory; XERJ = same model, reference retrieved.
| Library | Lang | Domain | The contract you can't guess | bare | XERJ | tokens bare→XERJ |
|---|---|---|---|---|---|---|
| sift | Rust | streaming sketch | conservative-update count-min; seal before any read | 0/9 | 9/9 | 17,350 → 796 |
| grove | Rust | arena allocator | generational handles — freed handle stays stale after reuse | 0/2 | 2/2 | 15,233 → 1,236 |
| weft | Rust | lexer | builder → weave → scanner; maximal munch | 1/2 | 2/2 | 16,112 → 610 |
| tally | Rust | fixed-point decimal | banker's rounding (round half to even) | 0/2 | 2/2 | 15,599 → 892 |
| spool | Rust | ring buffer | push returns the evicted item; power-of-two capacity via shift | 2/2* | 2/2 | 15,974 → 656 |
| cadence | Rust | rate limiter | token bucket, lazy refill only on advance | 0/2 | 2/2 | 18,162 → 744 |
| quill | Rust | varint codec | zig-zag + LEB128 (a memorised convention) | 2/2 | 2/2 | 1,355 → 999 |
| trellis | Rust | topological sort | smallest-index tie-break; exact cycle-node set on failure | 0/2 | 2/2 | 21,317 → 782 |
| sieve | Rust | bloom filter | Kirsch–Mitzenmacher double hashing; settle before sense | 0/2 | 2/2 | 13,817 → 669 |
| warden | Python | LRU cache | fetch promotes to most-recent; overflow evicts LRU | 3/4* | 4/4 | 15,370 → 240 |
| garner | JavaScript | prefix trie | stored word vs bare prefix (a known structure) | 4/4 | 4/4 | 4,360 → 667 |
| arena | C | generational allocator | opaque handle; stale after slot reuse | 2/4* | 4/4 | 18,730 → 1,489 |
| ledger | Java | append-only log | must seal before replay; checkpoint truncation | 2/4 | 4/4 | 26,767 → 97 |
* bare "passes" some cases by recovering an API name from a compiler/runtime error at 20–150× XERJ's tokens, or because the task spec necessarily stated the one non-obvious rule — never by recalling a genuine runtime contract. On the two memorised cases (quill varint, garner trie) the model already knows the algorithm and retrieval saves nothing — which is the point of including them. Source for every library: docs/case-studies/reference-coding →
Two controls on real, public code the model has trained on — valkey + memcached (a KV server), and tantivy (a search engine) — pin down exactly where retrieval stops paying. The value is gated by memorization.
RETRIEVAL WINS: correct where memory fails, 6.5× cheaper than bare, 1.3× cheaper than native.
RETRIEVAL LOSES: the model knows the protocol, so pure memory is cheapest; searching or injecting a reference is overhead.
Median output tokens to solve, XERJ vs answering from memory. Verdict is the real toolchain in each language (python3, node, cc, javac).
One Java task: build an append-only ledger that must be sealed before replay, truncated to a checkpoint. bare cannot read the library, so it reinvents the whole thing — 503 lines — and still fails the seal contract. XERJ, handed the reference, writes it in four lines and cites the rule it learned:
// reinvented an entire append-log + checkpoint + seal // state machine from memory, guessing the API surface … // 503 lines … wrong truncation semantics // → hidden test FAILED.
public static Ledger upTo(long[] vals, long seq) {
Ledger l = Ledger.open();
for (long v : vals) l.append(v);
l.checkpoint(seq); // keep 0..seq
l.seal(); // required before replay
return l;
}
CAPTURED VERBATIM · docs/case-studies/reference-coding/generated →
We ran the opener above verbatim on a fresh task — implement a top-3 heavy-hitters function using the unfamiliar sift crate (whose API is not new()/push()/top_k()). Following the prompt, Claude Code indexed the reference, retrieved sift's real API, and wrote code that compiles and passes a hidden test — using furnish / absorb / seal / crest, the seal-before-read contract a from-memory attempt cannot recover. The full transcript and the generated program are in the repo.
REPRODUCE THE VERIFICATION ITSELF · docs/case-studies/reference-coding →
The whole study reproduces from the repo. The method works on any repository — including your own private code, which is the real use case.
xerj -d ./.xerj-data --insecure — the ES-compatible API comes up on :9200.xc-corpus.sh async-rust https://github.com/tokio-rs/tokio https://github.com/hyperium/hyper — group by problem domain, not language.xc-index.sh async-rust — runs xerj autoindex; a 100k-record tree indexes in ~10 s.xc.py async-rust "graceful shutdown with a broadcast channel" — returns the matching definition with file:line.csrun.py, csmulti.py) runs bare / native / XERJ, one hidden-test verdict, real tokens from claude -p --output-format json — no API key. Full recipe in MEASURE / CASE_STUDY.md.