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
Section titled “Install”Install it as a persistent tool (recommended for regular use — the examples below call xmemcli directly):
uv tool install xmemcli # or: pip install xmemclixmemcli helpOr 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):
uvx xmemcli helpAdd the agent skill (optional)
Section titled “Add the agent skill (optional)”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:
npx skills add xmemory-ai/xmemory-skillThe 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.
Authenticate
Section titled “Authenticate”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:
xmemcli auth login # opens the browser; --no-browser for headlessxmemcli auth statusAlternatively, 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:
xmemcli xmd generate "Track contacts with name, email, company, and notes." -o schema.ymlxmemcli xmd validate schema.ymlxmemcli 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:
xmemcli org list instancesConnect an agent to an instance
Section titled “Connect an agent to an instance”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:
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:
xmemcli instance setup "$XMEM_INSTANCE_ID" --format projectServe one instance to an MCP client
Section titled “Serve one instance to an MCP client”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:
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:
xmemcli --json status # reports `version` and `authenticated`, contacts nothinguv tool install --upgrade xmemcli # if version is below 0.0.7Signed out, the client is told which command fixes it rather than being left with a server that failed to start for no stated reason.
Standing instructions for an instance
Section titled “Standing instructions for an instance”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:
xmemcli instance instructions "$XMEM_INSTANCE_ID"Set them by passing the text, and remove them with --clear:
xmemcli instance instructions "$XMEM_INSTANCE_ID" "Prefer short answers. Always cite the record you used."xmemcli instance instructions "$XMEM_INSTANCE_ID" --clearThe 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.
Bind instances to a project
Section titled “Bind instances to a project”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.
xmemcli binding add "$XMEM_INSTANCE_ID" --tier autoload --purpose "Team decisions"xmemcli binding listxmemcli 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:
xmemcli context --textThis is the only binding command that needs a credential. Where nothing is tiered autoload, it
makes no request at all.
Read and write
Section titled “Read and write”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).
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_idxmemcli write-status <write_id>Writes take plain language — xmemory maps the text onto the instance’s schema.
Evolve the schema
Section titled “Evolve the schema”There are two paths. Both end in a versioned migration — see the schema evolution post for the product story.
Suggestion engine from read traffic
Section titled “Suggestion engine from read traffic”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 review → decide → apply.
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:
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.
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):
xmemcli schema suggestions apply "$XMEM_INSTANCE_ID" \ --proposal-version "<next_proposal_version from decide>" \ --confirm-destructiveEnd-to-end sketch:
# 1. Notice pending work (optional — also on read responses)xmemcli read "What is the due date for task X?"
# 2. Review the proposalxmemcli schema suggestions review "$XMEM_INSTANCE_ID"# → note proposal_version and fingerprints
# 3. Decide with a humanxmemcli schema suggestions decide "$XMEM_INSTANCE_ID" \ --proposal-version "<from review>" \ --accept "<fingerprint>"
# 4. Applyxmemcli schema suggestions apply "$XMEM_INSTANCE_ID" \ --proposal-version "<next_proposal_version from decide>" \ --confirm-destructiveBoundaries. 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.
Hand-driven redesign
Section titled “Hand-driven redesign”When you describe a change yourself (not traffic-driven gaps):
xmemcli schema get "$XMEM_INSTANCE_ID" -o schema.ymlxmemcli xmd enhance schema.yml "Add a Contact.phone field." -o schema-v2.ymlxmemcli xmd validate schema-v2.ymlxmemcli schema dry-run "$XMEM_INSTANCE_ID" --schema-file schema-v2.yml # preview the migrationxmemcli schema update "$XMEM_INSTANCE_ID" --schema-file schema-v2.yml # apply itxmemcli help and xmemcli help <topic> document every command.