CLI reference
Bare xerj starts the server, and everything the engine itself does is controlled by the TOML config and driven through the HTTP API. The subcommands — autoindex, index, brain, mcp — are clients of a running node, not other ways to run one.
USAGE:
xerj [OPTIONS]
xerj <SUBCOMMAND> [ARGS]
OPTIONS:
-c, --config <PATH> Path to the TOML config file
[default: ./xerj.toml]
-d, --data-dir <PATH> Override [server] data_dir
-b, --bind <ADDR> Override [server] bind_address
[default: 127.0.0.1 — loopback only]
-k, --insecure Disable TLS and API-key auth (dev only)
-h, --help Print help
-V, --version Print version and build commit
SUBCOMMANDS:
index <opts> direct NDJSON → engine ingest
autoindex <folder> [opts] zero-config folder discovery + indexing
brain <folder> index a folder into a browsable second brain
mcp [opts] Model Context Protocol stdio server
--config / -c
Path to the TOML config. Defaults to ./xerj.toml. The XERJ_CONFIG environment variable is consulted only if this flag is absent.
--data-dir / -d
Convenience override for [server] data_dir. Useful for ephemeral dev runs and for pointing XERJ at a tmpfs when you just want to burn something down after.
--bind / -b
Interface to bind every listener to; overrides [server] bind_address. Env: XERJ_BIND_ADDRESS. The default is 127.0.0.1 — loopback only. Pass 0.0.0.0 (or a specific address) to expose the node; with TLS off that also needs server.allow_insecure_network_bind = true (env XERJ_ALLOW_INSECURE_NETWORK_BIND), because every request, API key included, would cross the network in cleartext. The value must be an IPv4 or IPv6 literal; host names are not resolved, and one is refused at startup before the data directory is created.
--insecure / -k
Disables TLS and API-key auth. Dev only. It does not unlock a network bind: clearing tls.enabled is exactly what makes a non-loopback bind_address refuse to start, so --insecure on 0.0.0.0 exits non-zero unless the exposure is declared.
--help / -h
Prints the synopsis above and exits.
--version / -V
Prints the version, git SHA, and build date. Useful in oncall pages: xerj -V | head -1.
xerj autoindex <folder>
Point it at a folder and it discovers, infers and indexes the contents — no mapping to write, no pipeline to configure. It is a client of a node that is already running, and it never reads the TOML config, so the endpoint and the credential are its own flags.
USAGE:
xerj autoindex <folder> [OPTIONS] discover + index a folder
xerj autoindex map [OPTIONS] print the discovered data map
xerj autoindex status [OPTIONS] resume-journal + index progress view
OPTIONS (abridged — `xerj autoindex --help` prints all of them):
--url <U> ES-compat endpoint
[default: http://localhost:9200]
--api-key <K> API key for that endpoint (or env XERJ_API_KEY)
--workers <N> workers for both phases [default: every core]
--prefix <P> index prefix [default: ax]
--no-semantic skip semantic_text on body fields (pure BM25+keyword)
--dry-run walk+sniff+infer, print the plan, index nothing
--json machine-readable RESULT on stdout
--progress <MODE> liveness on stderr: auto|plain|json|none
autoindex --api-key
The key the target node expects, or env XERJ_API_KEY (the flag wins). autoindex never takes it from xerj.toml — the config file belongs to the server, not to its clients. A node running with [auth] enabled = true (the default, and what happens on any start without --insecure) refuses an unauthenticated run with HTTP 401 Unauthorized. That node wrote its key to <data_dir>/admin.key on first boot:
$ export XERJ_API_KEY="$(cat ./data/admin.key)" $ xerj autoindex ~/my-project # or per-run: $ xerj autoindex ~/my-project --api-key "$(cat ./data/admin.key)"
Against a node started with --insecure no key is needed, because that flag clears auth.enabled too.
Source · engine/crates/xerj-server/src/main.rs · engine/crates/xerj-autoindex/src/cli.rs
xerj mcp
Starts a Model Context Protocol server on stdio — newline-delimited JSON-RPC 2.0 on stdin/stdout — so any MCP client (desktop assistants, IDE agents, function-calling hosts) can query XERJ without a shell. It is part of the single installed binary: if you ran the installer, you already have it.
It does not start a node. Start one first; xerj mcp proxies every tool call to the URL in XERJ_URL.
xerj --insecure --data-dir ./data & # 1. the node
xerj mcp # 2. the MCP server (your client runs this)
OPTIONS:
--url <URL> Base URL of the ES-compatible listener. Overrides XERJ_URL.
[default: http://localhost:9200]
--auth <VALUE> Authorization header sent verbatim on every proxied request,
e.g. 'ApiKey <token>'. Overrides XERJ_AUTH.
-h, --help Print help (includes the client config block below)
-V, --version Print version and exit
Client configuration — the standard mcpServers shape:
{
"mcpServers": {
"xerj": {
"command": "/home/you/.local/bin/xerj",
"args": ["mcp"],
"env": { "XERJ_URL": "http://localhost:9200" }
}
}
}
Use an absolute path — the installer puts xerj in ~/.local/bin by default (command -v xerj confirms), and an MCP host launched from a desktop icon does not inherit your shell's PATH. When the node is not running --insecure, add "XERJ_AUTH": "ApiKey <key>" next to XERJ_URL; the key lives in <data-dir>/admin.key.
Ten tools are served, each a thin proxy over an endpoint the engine already exposes — nothing is added, and engine errors come back verbatim: xerj_search, xerj_semantic_search, xerj_vector_search, xerj_hybrid_search, xerj_memory_store, xerj_memory_recall, xerj_brain_overview, xerj_brain_ego, xerj_brain_link, xerj_brain_unlink. Two caveats the tool descriptions carry themselves: xerj_semantic_search embeds server-side with the lexical feature-hashing embedder unless the node runs --embed-mode neural, and the xerj_brain_* tools work a deterministic link index, not a graph database.
Machine-readable schemas for all ten: /docs/agents/schemas/mcp-tools.json, generated from a live tools/list and gated against the binary in CI.
Source · engine/crates/xerj-server/src/main.rs · engine/crates/xerj-mcp/src/lib.rs