mrkeyoor.com_
Sat 17 Oct 13:32 UTC
Self-Hostedevaluationupdated 08 Oct 2026

xerj review

XERJ is a Rust search server that indexes code, documents, logs, and structured files, then exposes them through an Elasticsearch-shaped API. It is aimed at local search, RAG, and agent memory, with an MCP server in the same binary so coding tools can retrieve passages instead of reading whole files.

+3,319stars / 7d
Verdict

Our XERJ build took 752 seconds, and its tests were still compiling when our 900-second limit expired, so the prebuilt binary is the sensible evaluation path. Use it for single-node local search or MCP retrieval when an Elasticsearch-shaped API saves integration work. Do not treat the current cluster switch as replicated storage, and test every API behavior your application depends on.

We ran it

Lab card: what happened when we ran xerjScreenshot of xerj (xerj.org)
Install✓ · 20s741 packages
Build✓ · 752s
Tests✗ timed out · 900sran, no count parsed
Repo2741 files~529,359 lines of source · 203.6 MB · 8 CI workflows · Dockerfile · tests dir

Answers from our run

Does xerj build from source?

Dependencies installed in 20 seconds (741 packages), and the build succeeded in 752 seconds. We cloned commit 626d132 into a clean Debian container with 3 CPUs and no project-specific setup.

Do xerj's tests pass?

We could not finish them: the suite was still running after 15 minutes in our container.

Who should not use xerj?

Operators who need replicated writes today: open issue 1170 says the Raft ring exchanges heartbeats but production writes do not cross nodes.

What are the alternatives to xerj?

Elasticsearch, OpenSearch, Quickwit. Our XERJ build took 752 seconds, and its tests were still compiling when our 900-second limit expired, so the prebuilt binary is the sensible evaluation path.

Setup3/5Prebuilt binary is simple; source build took 752 seconds
Docs5/5Security boundaries, API limits, recipes, and source steps are explicit
Community4/53,113 stars, an October 7 push, and active issue triage
Maturity3/5rc.89 is active, but clustering lacks write replication

Who it’s for

Developers who want local code and document retrieval for an MCP-capable coding agent.
Teams that already use Elasticsearch clients and can validate XERJ's supported API subset.
Single-node self-hosters who want full-text, vector, and hybrid search in one binary.
Rust contributors prepared for a large workspace and long compile cycles.

Who it’s NOT for

Operators who need replicated writes today: open issue 1170 says the Raft ring exchanges heartbeats but production writes do not cross nodes.
Teams requiring exact Elasticsearch behavior for every endpoint: the README documents a bounded scroll snapshot and tells large result sets to use search_after.
Shared hosts that plan to copy the quick-start --insecure command: it disables TLS and API-key checks, making every reachable caller a superuser.
Source contributors expecting a quick full check: our build took 752 seconds, and tests were still compiling when the 900-second limit expired.
Autoindex users who need a source-file cap below 1 GB: open issue 1233 says the current option accepts only integer gigabytes.

Setup reality

Our sandbox installed 741 Rust packages in 20 seconds at commit 626d132. Building from ./engine/ succeeded in 752 seconds. The test command timed out after 900 seconds; its final lines were still compiling crates including xerj-server, xerj-mcp, and the Elasticsearch compatibility runner, so the log contains no completed test result.

The prebuilt route is much shorter: the README provides one binary for Linux, macOS, and Windows. Secure startup generates an admin key in the data directory. Autoindex then needs that key through --api-key or XERJ_API_KEY; the MCP process needs the node URL and, when auth is enabled, XERJ_AUTH.

The 203.6 MB checkout held 2,741 files and about 529,359 source lines. It includes 8 CI workflow files, a Dockerfile, a compose file, and a tests directory. Neural embedding is optional and downloads model files, while the default lexical embedder stays offline. The --insecure shortcut belongs only on a loopback-bound development machine.

One binary covers local search and agent retrieval

XERJ accepts code, PDFs, office files, logs, mail, SQLite databases, and common structured formats through autoindex. Source code is parsed with tree-sitter so records keep symbols and line numbers. Search clients can use full-text queries, aggregations, mappings, kNN, hybrid search, and familiar _cat endpoints. The practical appeal is consolidation: one local process can index a repository, answer Elasticsearch-style requests, and serve retrieval tools to an agent.

The same binary exposes 10 MCP tools for text, semantic, vector, and hybrid search, along with agent memory and graph operations. xerj init can configure Claude Code or Cursor, while xerj mcp runs a stdio server that forwards requests to an existing node. It does not launch that node. Desktop clients also need an absolute executable path because they may not inherit the shell's PATH. With authentication enabled, the MCP configuration must carry XERJ_AUTH.

The secure default and the quick start have different trust boundaries

Starting XERJ normally enables authentication and creates a 64-character admin key on first boot, according to the security model. The file is written inside the data directory with mode 0600. autoindex does not read the key from xerj.toml; you pass it explicitly or set XERJ_API_KEY. Scoped keys can limit access by index and privilege, though the security document says field-level and document-level rules are not enforced. Do not map an Elasticsearch security design across without checking those differences.

The README's first local command uses --insecure. That turns off TLS and authentication, and every caller that reaches the port becomes a superuser with read and delete access to all indices and memory namespaces. A fresh node binds to 127.0.0.1, and XERJ refuses a cleartext non-loopback bind unless the operator explicitly permits it. The guard is sensible. Copying the command into a shared container network without understanding the bind would erase it.

What happened when we ran it

Our sandbox cloned commit 626d132 into an unprivileged Debian container with 3 CPUs, 12 GB of RAM, Rust, and no secrets. Installing 741 packages took 20 seconds. The release build from ./engine/ succeeded in 752 seconds. That is a substantial compile cycle for a project whose user-facing story is a downloaded static binary, and it makes the published binary the faster route for an initial product evaluation.

The test command reached our 900-second limit and was terminated. Its final output was compilation, including xerj-autoindex, xerj-api, xerj-console-api, xerj-mcp, es-yaml-runner, and xerj-server. No completed test summary appeared in the supplied tail, so we cannot report passes, failures, or a failing case. The accurate result is a timeout during compilation, not a failed assertion and not proof that the suite itself needs 900 seconds once built.

The checkout contained 2,741 files, roughly 529,359 lines of source, and occupied 203.6 MB before the Cargo work. We found 8 CI workflow files, a Dockerfile, a compose file, and a tests directory. Those are good repository signals, but they do not change the local cost we measured. Contributors should cache build artifacts and budget for the workspace rather than judging source work by the one-line binary installer.

Elasticsearch compatibility has stated edges

XERJ implements the Elasticsearch REST shape rather than Elasticsearch internals. The README names indices, documents, bulk operations, search, mappings, aggregations, kNN, scroll, reindex, and _cat routes. Official clients and Kibana can connect. One important difference is documented: scroll uses a bounded snapshot prepared up front. If an exact result total exceeds that window, XERJ returns 400 and directs the caller to search_after instead of walking segments like Elasticsearch.

That is the right kind of disclosure, but application compatibility still needs a fixture built from your own queries. Test mappings, analyzers, pagination, bulk errors, aggregations, and client startup probes before replacing a node. The release is tagged v1.0.0-rc.89, which is useful context for the rate of change. An API that accepts a request can still differ in limits or response details your connector assumes.

The cluster ring does not replicate writes yet

Open issue 1170 is decisive for production architecture. It says cluster mode starts a real Raft ring with elections and heartbeats, but no production path proposes a data command. Index creation, mappings, documents, and deletes stay on the node that receives them. The issue reports that another node returns an index-not-found response after writes to its peer. Until that work lands, a green cluster health signal does not provide replicated data or failover.

Treat XERJ as a single-node engine and plan backups accordingly. That can be perfectly reasonable for a developer workstation, a rebuildable code index, or a local agent memory store whose risk is understood. It is a poor fit for a service whose durability story depends on multi-node quorum writes. Elasticsearch and OpenSearch are more suitable comparisons for that requirement; Quickwit is worth a look when object-backed log search is the target.

rc.89 is moving quickly, with limits recorded in public

GitHub showed 3,113 stars and 20 open issues and pull requests combined, with the repository pushed on October 7, 2026. Release v1.0.0-rc.89 arrived the same day and included fixes around autoindex read-back, resumable corpus indexing, vector scanning, and version-map reads. The rapid sequence is evidence of active work. It also means operators should pin a release and read each change before upgrading stored data or indexing jobs.

Open issue 1233 gives a smaller example of the remaining edges: autoindex accepts a positive non-streamable file cap only in integer gigabytes, so a 10 MB or 50 MB ceiling cannot be expressed through that option. The project's roadmap and security material are unusually candid about shipped behavior and gaps. That candor makes evaluation easier. It does not turn a release candidate into replicated production storage, which remains the line that should decide the purchase.

Alternatives

ProjectWhat it isPick it when
Elasticsearch gh↗The original distributed search and analytics server behind the API XERJ follows.pick this instead when broad API coverage, established clustering, and Elastic's operating model matter more than a small local binary.
OpenSearchA distributed search and analytics engine with its own dashboards and plugin ecosystem.pick this instead when replicated multi-node search is a firm requirement.
Quickwit gh↗A Rust search engine designed around object storage and log-style datasets.pick this instead when cloud object storage and distributed log search are the main job.

What people are saying

  1. [github-trending] xerj-org/xerj

Sources

  1. XERJ README
  2. XERJ security model
  3. XERJ v1.0.0-rc.89 release
  4. XERJ cluster replication issue 1170
  5. XERJ autoindex file cap issue 1233
  6. XERJ repository metadata

More self-hosted reviews

playport · edge-smart-doh · Comma · ProsperoEden · zulu · node_exporter · the whole board →