AI-NATIVE SEARCH ENGINE · ONE RUST BINARY · APACHE-2.0

SEARCH BUILT
FOR AI AGENTS.

XERJ indexes your code, documents and data, then answers an agent's questions from the index instead of its context window. It speaks the Elasticsearch API, so the clients you already have connect unchanged.

INSTALL · ONE LINE · STATIC BINARY · SHA-256 VERIFIED, FAIL-CLOSED

curl -fsSL https://xerj.org/get | sh

Linux, macOS and Windows, on x86_64 and arm64. Static musl by default, so any distro including Alpine. Windows, glibc and all eight targets →

OR HAND THIS TO YOUR CODING AGENT 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.

Agents that query an index instead of re-reading files finished the same tasks on 2.7× fewer output tokens. Every number on this site names the run behind it, wins and losses alike, on the benchmarks page.

01·REFERENCE CODING · INDEX THE REPOS YOU LEARN FROM

CODE YOUR AGENT
HASN'T MEMORISED.

A coding agent that hits an API it has not memorised invents method names, fails to compile, and loops. Every lap spends output tokens, which are the expensive kind. Grep does not save it, because grep only says where to look and the agent still has to read the source into context.

Reference coding flips that loop. Clone the open-source repos closest to what you are building, index them once with xerj autoindex, and the agent retrieves the exact definition, with its contract, before it writes a line.

We measured it over eight tasks in four languages, sixteen runs per arm, counting the tokens each run actually billed. Retrieval used 2.7× fewer output tokens than a grep-driven agent at the same solve rate, and cost roughly half as much. On a Rust library the model had never seen, retrieval solved nine of nine and memory solved none. The loop is four commands, and llms.txt walks your agent through all of them.

$ xerj --insecure --data-dir ./.xerj-data &      # a node, running
$ git clone --depth 1 https://github.com/spacejam/sled ref/sled
$ xerj autoindex ref/sled                        # index once — tree-sitter AST fields
$ xerj search "fsync the WAL segment on rotation"
→ the exact function, its file:line and contract — one plain-English line in, a passage to read out
$ xerj def "euler_to_rotationmatrix"
→ where it is defined: file:line + signature — go-to-definition, one call

One binary, no wrapper scripts. xerj search is a client: it finds the running node and asks a definition-first query, pairing an exact-symbol clause with a phrase match on the AST defs field, so what comes back is the function rather than a list of line matches. On an eighty-task cross-file benchmark that puts the right file first 94% of the time, against 38% for ordinary body-text search.

When you already know the name, xerj def answers the sharper question in one call: where is this defined, and what is its signature. For a whole team, xerj corpus add records a corpus definition of pinned commit SHAs and licences under tools/xerj-code/, a few hundred bytes and no source, so another machine rebuilds exactly the same commits.

THE FULL CASE STUDY — EVERY NUMBER, EVERY TASK, THE EXACT PROMPT →·THE FIELD REPORTS BEHIND THE TOKEN SAVINGS →

02·POINT XERJ AT A FOLDER · ZERO CONFIG

ONE COMMAND.
ANY FOLDER.

The fastest way to make data useful to an agent is to skip the pipeline entirely. xerj autoindex <folder> is a subcommand of the same binary. It walks the tree and identifies every file by its content, because extensions lie.

It covers thirteen format families, from JSONL and dialect-sniffed CSV through SQL dumps, SQLite, PDF, DOCX, HTML, XML, YAML and gzip. It infers field types and date encodings from the data itself, writes explicit mappings, and streams everything in with idempotent IDs. Junk files are recorded rather than fatal.

It finishes by writing a catalog index, so the agent's first question, "what is even in here?", is answered by the engine instead of by another script. Here is a real captured run:

$ xerj autoindex ./sample
autoindex: 4 files (0 MB) under /tmp/xerj-pubpass/sample
phase A: sniffing + sampling 4 files…
phase A: 3 datasets inferred, 1 junk/skipped files
phase B: indexing 3 files with 8 workers → http://localhost:9280

done in 0.2s — 3 datasets, 5801 records live, 0 junk records, 1 junk/skipped files
  ax-logs                                        5000 docs
  ax-exports                                      800 docs
  ax-docs                                           1 docs

next: `xerj autoindex map --url http://localhost:9280` for the data map; search via GET /ax-*/_search

CAPTURE NOTE · THAT RUN'S NODE WAS STARTED ON A NON-DEFAULT PORT, SO THE OUTPUT ECHOES :9280. THE DEFAULT ES-COMPAT PORT IS :9200 — USE http://localhost:9200 UNLESS YOU CHANGED IT. THE TRANSCRIPT ABOVE IS REPRODUCED UNEDITED.

GROUND-TRUTH EXAM · 1,995 FILES / 518 MB
80/81 CHECKS
secret-manifest corpus, 25 formats · the one miss: a Shift-JIS file indexed as mojibake
518 MB → LIVE, TYPED INDICES
38.1 s
31 datasets · 2,018,398 records · ~38–51 s across runs · 33.7k rec/s end-to-end on 923 MB
RESUMABLE · IDEMPOTENT
KILL -9 SAFE
journal resume converges to identical final counts · client memory flat ~250 MB at 5× input growth

Honesty first. In a controlled ten-question exam on that 518 MB corpus, a XERJ-backed agent scored nine correct and one partial against a fair grep-and-python baseline's ten out of ten. That is a tie on accuracy, not a rout.

What XERJ wins is structural. A full corpus inventory takes four API calls, aggregations over millions of rows come back in under a second, and SQLite, DOCX, gzip and decimal-comma CSV all arrive through one API. Those are the advantages that matter at scale and under repeated querying. The pipeline streams and resumes, verified on multi-gigabyte corpora.

THE FULL RECIPE, EVERY NUMBER TRACED TO A RUN →

03·AGENTS ARE THE CUSTOMER · MEMORY · RECIPES

ONE HTTP API.
NO SDK.

Every operation an agent needs is a plain HTTP call on :9200. No SDK, no signup, no external embedding key. Store what an agent learns, then recall it later by meaning.

We should be precise about what that means. The built-in embedder is lexical hash-based, so this is honest hybrid lexical and vector retrieval rather than neural understanding. Each namespace is physically isolated, so agents never read one another's memories. Here is a real run against an empty XERJ:

$ curl -sXPOST localhost:9200/_memory/agent-demo \
    -H 'content-type: application/json' \
    -d '{"text":"The user prefers metric units and a dark UI theme.","metadata":{"kind":"preference"}}'
{"created":true,"id":"77eff57b-e432-431c-8b49-8a16b33ab551","namespace":"agent-demo"}

$ curl -sXPOST localhost:9200/_memory/agent-demo/_recall \
    -H 'content-type: application/json' \
    -d '{"query":"what display settings does the user like?","semantic":true,"k":1}'
{"hits":[{"id":"77eff57b-e432-431c-8b49-8a16b33ab551",
          "score":0.655571460723877,
          "text":"The user prefers metric units and a dark UI theme."}],  // metadata trimmed
 "namespace":"agent-demo"}

THE FULL AGENT SURFACE — SEVEN OPERATIONS + LLMS.TXT →

04·WHY XERJ · WHAT YOU ACTUALLY GET

FEATURE
BY FEATURE.

Every feature exists to cut the thing agents actually spend: context. Reading a file costs a context window; asking an index costs kilobytes. XERJ puts everything an agent needs to ask, from code and documents to vectors and memory, behind one query surface.

AST code search
Source is parsed with tree-sitter (34 languages) into symbols with kind and line number plus a searchable definitions field — the agent retrieves a function with its contract, not a grep line that needs the whole file opened to judge
Token economics
In the WordPress security audit, an agent worked across 1,492 PHP files on roughly 26,000 tokens — about half a percent of the tree read into context. That is the product; the speed is a side effect
Hybrid in one pass
50 query types, machine-checked against the parser dispatch table, including native BM25 + kNN fusion (RRF) in a single query tree — no bolt-on vector database, no fusion glue between two systems
Semantic without setup
Auto-embed on ingest, fully offline. Honest by default: the built-in embedder is lexical feature-hashing (vocabulary overlap, not neural understanding); the in-binary neural encoder and the external-proxy mode are drop-in upgrades when you want them
Agent memory + graph
A namespaced /_memory REST API — store, recall by meaning / keyword / vector, filter, forget, physically isolated per agent — and a /_graph knowledge layer with evidence on every link
Zero-config ingest
One command sniffs 13 format families by content — code, CSV, JSON, PDF, DOCX, SQLite, logs — honours .gitignore, records junk instead of crashing on it, and resumes incrementally
Speaks Elasticsearch
1,366 / 1,369 wire-conformance cases green on every commit — existing clients, dashboards and tooling connect unchanged. A migration bridge, not a clone: the engine underneath is designed for agents
One static binary
Rust, no JVM, sub-second start, Apache-2.0 — laptop to server with the same artifact. Benchmarks with wins and losses published at xerj.org/benchmarks
THE ENGINEERING LOG · NEWEST FIRST

FROM THE BLOG

We write up the measurements as they happen and leave the losing rows in the tables. Every post names the runs behind it, so you can check a number instead of taking it.

All posts →

GET XERJ
Looking for a CEO
A developer-evangelist type — 100k+ followers on X, laser-focused on AI reshaping how machines write code. If that is you: git@xerj.org, subject CEO for Xerj / [Your Name]