Skip to content

CLI

xmemcli is the xmemory command-line client — the fastest way to onboard (authenticate, design a schema, create an instance) and to read, write, and evolve memory from a terminal or a script. It talks to the HTTP API at https://api.xmemory.ai.

For agents that call xmemory as tools during a task, use the MCP server. xmemcli is the onboarding / control plane; MCP is the runtime data plane — they complement each other.

API key: To use xmemory APIs or integrations, you need an API key. Get one from the xmemory console, or run xmemcli auth login (below). Never share your API key publicly.


Install it as a persistent tool (recommended for regular use — the examples below call xmemcli directly):

Terminal window
uv tool install xmemcli # or: pip install xmemcli
xmemcli help

Or run it with no install — handy for a quick try, CI, or letting an agent invoke it — via uv’s uvx (prefix any command with uvx):

Terminal window
uvx xmemcli help

xmemcli ships an agent skill that teaches AI coding agents to use xmemory. Install it into your agents (Claude Code, Cursor, Codex, Gemini CLI, and more) with the skills installer:

Terminal window
npx skills add xmemory-ai/xmemory-skill

The agent then uses xmemory on its own — listing available instances, checking what’s already stored before redoing work, and writing down what it learns for next time.


The easiest path is the browser login (PKCE) — best run while you’re onboarding xmemory in the Console, so the handoff lands in .xmemrc.json with almost no extra steps:

Terminal window
xmemcli auth login # opens the browser; --no-browser for headless
xmemcli auth status

Alternatively, create an API key in the Console. Prefer keeping it in a .xmemrc.json (which auth login writes for you) over the environment — a $XMEM_API_KEY env var also works and is handy for CI. xmemcli resolves credentials --api-key$XMEM_API_KEY → the nearest .xmemrc.json (walking up from the current directory). Add .xmemrc.json to .gitignore — it holds secrets.


Onboard: create an instance from a description

Section titled “Onboard: create an instance from a description”

xmemory stores data in typed instances governed by XMD. You can author XMD directly and pass the validated file to instance create. For an easier description-first path, give the xmemory-instance-creation skill a plain-language account of what to remember and the questions you expect to ask; it handles generation, validation, approval, and creation.

Using the CLI directly, describe the domain, let xmemcli synthesize XMD, validate it, then create the instance:

Terminal window
xmemcli xmd generate "Track contacts with name, email, company, and notes." -o schema.yml
xmemcli xmd validate schema.yml
xmemcli instance create --name contacts --description "People we talk to" --schema-file schema.yml
# → save the returned UUID:
export XMEM_INSTANCE_ID="<uuid from output>"

See the XMD schema format for the complete object, field, enum, key, relation, and description reference before reviewing or deliberately editing schema.yml. Note that instance create --description is instance metadata; the generation prompt belongs to xmd generate.

List the memory stores available to you any time:

Terminal window
xmemcli org list instances

Creating an instance does not connect anything to it. instance setup prints how to connect this one, ordered by where it is likely to be used:

Terminal window
xmemcli instance setup "$XMEM_INSTANCE_ID"

The instance id is optional — it falls back to --instance-id or XMEM_INSTANCE_ID. The steps are computed from the instance’s current settings, so they keep up as it changes, and they carry no credential: each connection signs in separately.

instance create already returns these instructions alongside the new id, so the common path needs no second call.

For a whole team, --format project additionally prints the shared setup files to commit once. Each teammate still approves the install and signs in themselves:

Terminal window
xmemcli instance setup "$XMEM_INSTANCE_ID" --format project

xmemcli mcp is a stdio transport, and it arrived in 0.0.7. An MCP client starts it, and it forwards each frame to that instance with the credential read from .xmemrc.json per connection. Nothing is captured when the entry is registered, so a client configured today still works in a session opened next week on a machine whose environment carries nothing:

Terminal window
claude mcp add xmemory-<FIRST8> -- xmemcli mcp <INSTANCE_ID>
codex mcp add xmemory-<FIRST8> -- xmemcli mcp <INSTANCE_ID>

Name each entry xmemory- plus the first eight characters of the instance id — what instance setup prints for it. Two instances registered under one name leave one entry, the second having quietly replaced the first.

Check the client before registering, because an older one accepts the command and then cannot run it, leaving a server that fails to start:

Terminal window
xmemcli --json status # reports `version` and `authenticated`, contacts nothing
uv tool install --upgrade xmemcli # if version is below 0.0.7

Signed out, the client is told which command fixes it rather than being left with a server that failed to start for no stated reason.


An instance can carry standing instructions: the owner’s own words about how agents should use that memory. They are authoritative rather than advisory — rendered verbatim wherever they are shown — and they reach every agent that connects the instance.

Reading is the default, so it is always safe to look:

Terminal window
xmemcli instance instructions "$XMEM_INSTANCE_ID"

Set them by passing the text, and remove them with --clear:

Terminal window
xmemcli instance instructions "$XMEM_INSTANCE_ID" "Prefer short answers. Always cite the record you used."
xmemcli instance instructions "$XMEM_INSTANCE_ID" --clear

The id is optional — pin it with --instance-id or $XMEM_INSTANCE_ID and give the text alone. Clearing is its own flag rather than an empty string, because "" is what a shell substitutes for a variable that was never set, and that should not delete a standing rule.

The same field is editable from the console and from the instance chat, so a write composed against text someone has since replaced is refused rather than applied. Read them again and reapply; retrying would overwrite whatever the other editor just wrote.

instance instructions arrived in 0.0.8.


A binding records which instances an agent working in this directory should know about, and how eagerly to engage each one. It is local bookkeeping — no network, no credential — and it grants no access by itself.

Terminal window
xmemcli binding add "$XMEM_INSTANCE_ID" --tier autoload --purpose "Team decisions"
xmemcli binding list
xmemcli binding remove "$XMEM_INSTANCE_ID"

Three tiers: autoload pulls that instance’s context into every session, available (the default) engages on demand, and off keeps the binding dormant.

Bindings live in .xmemory.json, found by walking up from the working directory. Scopes merge, git-config style: ~/.xmemory.json supplies your personal instances, a repository’s committed .xmemory.json adds the team’s, and the nearer file wins field by field. --scope user writes the personal file; the default writes the committable one.

.xmemory.json holds no secrets and is meant to be committed — an instance id is an identifier, not a credential. A teammate who opens a session there fetches those instances with their own credential, so they see only what their access already reaches. .xmemrc.json sits in the same directory and holds a plaintext API key; that one is never committed.

To see what a session-start hook would inject for the autoload bindings here:

Terminal window
xmemcli context --text

This is the only binding command that needs a credential. Where nothing is tiered autoload, it makes no request at all.


write and read act on the active instance — the XMEM_INSTANCE_ID you exported above (they take no instance argument, unlike control-plane commands such as schema/instance, which name the instance explicitly).

Terminal window
xmemcli write "Alice Johnson works at Acme Corp. Her email is alice@acme.com."
xmemcli read "What is Alice's email?"
# bulk / non-blocking:
xmemcli write --no-wait "..." # returns a write_id
xmemcli write-status <write_id>

Writes take plain language — xmemory maps the text onto the instance’s schema.


There are two paths. Both end in a versioned migration — see the schema evolution post for the product story.

When agents ask questions the schema cannot answer, those misses become signal. xmemory consolidates recurring gaps into a proposal: concrete ops (add a field, introduce an object, wire a relation), each with a fingerprint, evidence queries, and a proposal_version token. Until recently that loop lived in the Console and MCP; from xmemcli 0.0.6 it is also a CLI path: schema suggestions reviewdecideapply.

When to use it. Prefer this path when read responses show a non-zero pending_suggestions count, or when you know agents keep asking for fields the schema does not hold. In pretty mode that count also prints as a one-line hint on single-answer reads (for example (2 pending schema suggestion(s) — xmemcli schema suggestions review)); structured / raw / xresponse reads still carry the count in JSON only. Prefer hand-driven redesign (below) when you want to describe a change yourself in plain language.

Review is read-only — it fetches the current consolidated proposal without changing the schema:

Terminal window
xmemcli schema suggestions review "$XMEM_INSTANCE_ID"
# optional: --session-id <id> (forwarded on review, decide, and apply for tracing)

Curated output includes each item’s fingerprint, a short op_summary (for example add_field Task due_date), frequency, rationale, and sample queries. Copy the proposal_version from this response and pass it to decide. After decide, apply with next_proposal_version from the decide response (not the review token). If the engine is busy, review returns status: evolution_in_progress with exit 0 (and often retry_after_seconds); wait and review again — that is a status, not an error stage.

Decide records accept / reject / defer for items in that proposal. Always pass --proposal-version from the review you just ran. There is no silent version swap: if the server has moved on, you get a clear stale-version error (stage: stale_proposal) and re-review.

Terminal window
xmemcli schema suggestions decide "$XMEM_INSTANCE_ID" \
--proposal-version "<from review>" \
--accept "<fingerprint>" \
--reject "<fingerprint>"

Pass exactly one input mode per invocation: the repeatable --accept / --reject / --defer flags, or a JSON decisions file via --file ([{item_fingerprint, decision}, ...] or {decisions: [...]}). Do not combine --file with the fingerprint flags. Conflicting decisions for the same fingerprint are a usage error.

Other suggestion-specific failure stages to watch for: invalid_decision (bad fingerprint or decision), dependency (accept the dangling dependencies first), not_initialised (write once to initialize the instance), and apply (apply-time failure).

Apply commits the accepted items as a single versioned migration. After decide, pass next_proposal_version from the decide response (not the review token). You can apply with the review proposal_version only when you skip decide and the proposal is already decided. --confirm-destructive is required (preview removals in the Console first if the proposal may drop data):

Terminal window
xmemcli schema suggestions apply "$XMEM_INSTANCE_ID" \
--proposal-version "<next_proposal_version from decide>" \
--confirm-destructive

End-to-end sketch:

Terminal window
# 1. Notice pending work (optional — also on read responses)
xmemcli read "What is the due date for task X?"
# 2. Review the proposal
xmemcli schema suggestions review "$XMEM_INSTANCE_ID"
# → note proposal_version and fingerprints
# 3. Decide with a human
xmemcli schema suggestions decide "$XMEM_INSTANCE_ID" \
--proposal-version "<from review>" \
--accept "<fingerprint>"
# 4. Apply
xmemcli schema suggestions apply "$XMEM_INSTANCE_ID" \
--proposal-version "<next_proposal_version from decide>" \
--confirm-destructive

Boundaries. Before/after YAML preview for a proposal remains Console-only (API-key callers cannot use /suggestions/preview). Hand-driven schema work stays on the commands below. Full help: xmemcli help, xmemcli help schema, and xmemcli help schema suggestions.

When you describe a change yourself (not traffic-driven gaps):

Terminal window
xmemcli schema get "$XMEM_INSTANCE_ID" -o schema.yml
xmemcli xmd enhance schema.yml "Add a Contact.phone field." -o schema-v2.yml
xmemcli xmd validate schema-v2.yml
xmemcli schema dry-run "$XMEM_INSTANCE_ID" --schema-file schema-v2.yml # preview the migration
xmemcli schema update "$XMEM_INSTANCE_ID" --schema-file schema-v2.yml # apply it

xmemcli help and xmemcli help <topic> document every command.