CLI reference
Every aimem command — mount, Memory Bucket, secret, search, and the agent biography (bio).
The aimem binary is how an agent reaches its memory. Every command works
against one customer-owned MinIO AIStor Memory Bucket. Each
subcommand touches a different form of that memory: the workspace the agent
works in, the long-term memory it remembers through, and the Vault of secrets
it needs to act. Five surfaces, one Memory Bucket:
- mount —
aimem <bucket> <mountpoint>mounts a Memory Bucket as the agent's workspace: the filesystem it both works in and remembers through. This is the default form, with no subcommand. A--configYAML file is the canonical way to configure the mount — see Mounting a Memory Bucket below. Mount a sub-prefix with thebucket/prefix/positional. Mounting only works against a Memory Bucket: it needs an explicit endpoint and real signing credentials, and the target bucket must already be a Memory Bucket on a paid-tier AIStor deployment. aimem bucket— create and manage the Memory Buckets that hold every form of memory.aimem secret— the Vault: deployment-side secret provisioning for launchers.aimem search— long-term-memory search: regex over a Memory Bucket's data at rest.aimem bio— the biography: an OpenTelemetry collector that records what an agent did into queryable tables in the same Memory Bucket.
The management verbs share one set of connection flags. bucket, search,
and bucket-backed secret operations use the AIStor Memory API. bio
also uses the Iceberg REST catalog. secret provision can instead target a
generic HTTP secret store (--store-endpoint).
--config applies only to the mount command. The management verbs take
their settings as flags, or as the connection env vars below, never from a
config file.
Mounting a Memory Bucket
aimem <bucket> <mountpoint> mounts a Memory Bucket as a workspace. The
canonical way to configure a mount is a --config YAML file: point --config
at it, supply credentials in the environment, and pass the Memory Bucket and
mountpoint as positionals.
export AIMEM_ACCESS_KEY=... AIMEM_SECRET_KEY=...
aimem my-memory-bucket /workspace --config /etc/aimem/mount.yamlThe --config YAML must declare version: "1.0". It carries every mount
setting — the advanced tunables that have no CLI flag, and the mandatory
staging directory (via the local: key here, or the --local flag /
AIMEM_LOCAL env var — at least one is required). See
Configuration for the full key reference.
Credentials are environment-only: AIMEM_ACCESS_KEY, AIMEM_SECRET_KEY,
and the optional AIMEM_SESSION_TOKEN. They are never mount flags and never
--config YAML keys, so the signing secret stays out of config files and
process arguments.
Mount flags
The everyday mount settings are also available as CLI flags. Each flag is
equivalent to the --config YAML key of the same name (dashes become
underscores), and --config is the preferred way to set them — the flags
exist for quick, one-off mounts. An explicit flag always overrides the YAML
value.
| Flag | Config key | Description |
|---|---|---|
--local <DIR> | local | Mandatory local staging + read-cache directory. Also AIMEM_LOCAL; one of the three is required. |
--endpoint-url <URL> | endpoint_url | AIStor endpoint; repeatable, or a {1...N} brace range, for failover. |
--region <REGION> | region | SigV4 signing region (default us-east-1). |
--request-timeout <SECONDS> | request_timeout | Per-request deadline; retries the next endpoint. Only valid with two or more endpoints. |
--health-path <PATH> | health_path | HTTP path polled per endpoint for liveness; unhealthy endpoints leave the round-robin pool. |
--tls-ca-file <FILE> | tls_ca_file | Extra PEM CA bundle for endpoint TLS. Also AIMEM_TLS_CA_FILE. |
--tls-server-name <NAME> | tls_server_name | Name to verify the endpoint's certificate against, when --endpoint-url is an IP. Also AIMEM_TLS_SERVER_NAME. |
--read-only | read_only | Mount the filesystem read-only. |
--agent <TYPE> | agent | Warm vendor memory files on mount (claude, codex, cursor, auto). |
--metadata-ttl <TTL> | metadata_ttl | Kernel metadata cache TTL: indefinite, minimal, or seconds. |
-f, --foreground | foreground | Run in the foreground instead of daemonizing. |
-l, --log-directory <DIR> | log_directory | Write logs to files under this directory instead of syslog. |
-d, --debug | debug | Enable debug logging. |
--no-log | no_log | Disable logging entirely. |
Of these, only --local (AIMEM_LOCAL), --tls-ca-file
(AIMEM_TLS_CA_FILE), --tls-server-name (AIMEM_TLS_SERVER_NAME), and
--region (AIMEM_REGION) also read an environment variable. The rest are flag-or---config only, and credentials
remain environment-only (above).
Every other mount setting — the FUSE, transfer, memory, observability, and
health-check tunables — is --config-only and listed in the
Configuration key reference.
Connection flags
Every management verb reaches the Memory API with the same endpoint and credentials. Pass them as flags or — preferably — as environment variables.
| Flag | Environment variable | Description |
|---|---|---|
--endpoint-url <URL> | AIMEM_ENDPOINT_URL | AIStor / Memory API endpoint (e.g. https://aistor.example.com:9000) |
--access-key <KEY> | AIMEM_ACCESS_KEY | Access key |
--secret-key <KEY> | AIMEM_SECRET_KEY | Secret key |
--region <REGION> | AIMEM_REGION | SigV4 region (default us-east-1) |
--session-token <TOK> | AIMEM_SESSION_TOKEN | Optional STS session token |
export AIMEM_ENDPOINT_URL=https://aistor.example.com:9000
export AIMEM_ACCESS_KEY=your-access-key
export AIMEM_SECRET_KEY=your-secret-keyThe Memory API is a paid-tier AIStor feature. Creating and mounting a Memory Bucket requires a licensed AIStor deployment.
aimem bucket — manage Memory Buckets
A Memory Bucket is a first-class AIStor bucket built for agents: compressed, encrypted, KMS-backed, version-tracked, and stamped with memory metadata. AIStor Memory mounts only a Memory Bucket, so this is where every workspace begins.
bucket create <name>
Create a Memory Bucket.
| Flag | Description |
|---|---|
--kms-key-id <ID> | Pin a specific KMS key for encryption (defaults to the server key). |
--upgrade-existing | Convert an existing regular bucket instead of failing if it exists. |
aimem bucket create my-projectbucket convert <name>
Convert an existing regular bucket into a Memory Bucket in place. Idempotent — converting an existing Memory Bucket is a no-op. Objects written before the conversion are not retro-actively compressed, encrypted, or metadata-stamped; only writes after it honor the Memory Bucket contract. Warehouse buckets cannot be converted.
Any bucket you convert becomes a full Memory Bucket: besides the workspace and the
Memory API, the resulting Memory Bucket also serves as an Iceberg warehouse, so
structured memory (aimem bio tables, below) works on the same bucket
immediately — no separate warehouse to stand up.
| Flag | Description |
|---|---|
--note <NOTE> | Record a free-form migration note (stored as upgrade-note). |
--kms-key-id <ID> | Pin a KMS key, applied only when the bucket has no encryption of its own. |
aimem bucket convert legacy-bucket --note "migrated 2026-07"bucket list
List Memory Buckets.
| Flag | Description |
|---|---|
--search <SUBSTR> | Filter Memory Buckets whose name contains this substring. |
--json | Emit JSON instead of a table. |
bucket get <name>
Show a single Memory Bucket — bucket, uuid, created timestamp, encryption,
compression, KMS key (when pinned), memory format, and the upgraded flag.
Add --json for the full detail object (which also includes any operator
metadata).
aimem bucket get my-project --jsonbucket delete <name>
Delete a Memory Bucket and all its data.
| Flag | Description |
|---|---|
--force | Delete even when the Memory Bucket is non-empty. |
bucket credentials <name>
Mint STS credentials scoped to a single Memory Bucket (AssumeRole with an inline session policy). The temporary credentials can mount the bucket and use the Memory API on it — and nothing else. This is how a launcher hands a sandbox least-privilege access to exactly one workspace.
| Flag | Description |
|---|---|
--duration <SECS> | Requested credential lifetime. |
--json | Emit JSON instead of shell export lines. |
# inject scoped, time-boxed credentials into a sandbox
eval "$(aimem bucket credentials my-project --duration 3600)"aimem secret — deployment-side secret provisioning
aimem secret is a launcher / deployment helper, not a skill and not a
command the agent runs. The process that launches the agent — a sandbox
controller, a CI job, an orchestrator — runs it outside the sandbox.
Secrets never touch the mount, and the agent inside the workspace has no
reason to call aimem secret at all.
secret provision --grant VAR=name [-- cmd …]
Fetch the granted secrets and inject them as environment variables. With a
trailing -- <command>, the agent inherits the ambient environment with
the store and connection credentials scrubbed and the leased secrets
injected on top. Scrubbing removes the AIMEM_SECRET_STORE_* variables and
AIMEM_ACCESS_KEY / AIMEM_SECRET_KEY / AIMEM_SESSION_TOKEN /
AIMEM_ENDPOINT_URL / AIMEM_REGION. The agent therefore keeps
PATH/HOME and receives its API keys as ordinary environment variables,
but can neither read the store credential nor re-fetch.
provision launches the command as a child process, waits for it, and exits
with the child's status; it does not exec. With no command, it prints
KEY=VALUE lines for the caller to consume.
| Flag | Description |
|---|---|
--grant VAR=name | Bind an environment variable to a secret name. Repeatable. |
--bucket <BUCKET> | Resolve secrets from a Memory Bucket over the Memory API. |
--store-endpoint <URL> | Resolve from a generic HTTP store (HashiCorp Vault/OpenBao, a cloud manager). Mutually exclusive with --bucket. Also AIMEM_SECRET_STORE_ENDPOINT. |
--store-token <TOK> | Bearer token for the HTTP store; held launcher-side, never injected. Also AIMEM_SECRET_STORE_TOKEN. |
The --bucket path additionally requires the Memory-API connection
credentials, given either as flags or environment variables:
| Flag | Description |
|---|---|
--endpoint-url <URL> | Memory-API endpoint URL. Required with --bucket. Also AIMEM_ENDPOINT_URL. |
--access-key <KEY> | Access key. Required with --bucket. Also AIMEM_ACCESS_KEY. |
--secret-key <KEY> | Secret key. Required with --bucket. Also AIMEM_SECRET_KEY. |
--region <REGION> | Region for SigV4 signing. Optional (defaults to us-east-1). Also AIMEM_REGION. |
--session-token <TOK> | Session token for temporary credentials. Optional. Also AIMEM_SESSION_TOKEN. |
provision errors if the endpoint, access key, or secret key is unset when
--bucket is used.
# launch the agent with OPENAI_API_KEY leased in, store creds scrubbed
aimem secret provision --bucket my-project \
--grant OPENAI_API_KEY=openai -- claudesecret put / get / list / delete
Manage secrets stored in a Memory Bucket over the Memory API. These, too, are launcher/operator-side administration — not something the sandboxed agent invokes.
| Command | Description |
|---|---|
secret put <bucket> <name> | Store a secret. Prefer piping the value on stdin over --value, which is visible in the process list and shell history. |
secret get <bucket> <name> | Print a secret's plaintext value. |
secret list <bucket> | List secret names in a Memory Bucket. |
secret delete <bucket> <name> | Delete a secret. |
printf '%s' "$OPENAI_KEY" | aimem secret put my-project openai
aimem secret list my-projectaimem search — regex over data at rest
aimem search runs a server-side regex search over a Memory Bucket's objects, which
stay compressed and encrypted at rest. It returns the names of matching
objects, or with --content, the matching lines in grep style
(name:line:text).
aimem search my-project --pattern 'TODO|FIXME' --ext md --ext rs --ignore-case| Flag | Description |
|---|---|
-e, --pattern <REGEX> | RE2 pattern to match; repeatable, 1–16 patterns, all must match (AND). |
--prefix <PREFIX> | Restrict the search to keys under a prefix. |
--ext <EXT> | Restrict to these extensions, with or without the dot (md or .md); repeatable. |
--ignore-case | Case-insensitive matching. |
-U, --multiline | Let a pattern span line boundaries (ripgrep -U); off by default. |
--content | Print matching lines (name:line:text), not just object names. |
aimem bio — the agent's biography
An agent's memory also has a structured form: what it did, kept as queryable
tables in the same Memory Bucket that holds its files. aimem bio runs an
OpenTelemetry collector beside the agent, writes what the agent's harness
emits into that Memory Bucket, and reads it back — so a run's activity becomes
durable memory alongside the files it produced.
The collector speaks standard OTLP/HTTP, so nothing has to be written against a proprietary API. Any harness or SDK that can export OpenTelemetry — a coding agent's telemetry plugin, an application's own instrumentation — points at it and its traces, logs and metrics land in the Memory Bucket.
bio ships as a sibling aimem-bio binary that aimem bio dispatches to
(resolved next to aimem first, then on PATH). It is included in the deb
and rpm packages and the standalone archive, so aimem bio … works from a
normal install; aimem bio --help lists its own options.
bio serve <bucket> --agent <ID> --endpoint-file <FILE> [--session-key <ATTRIBUTE>]
Run the collector. It binds a loopback port, writes the base URL it chose to
--endpoint-file, and accepts OTLP/HTTP on the standard /v1/traces,
/v1/logs and /v1/metrics paths — JSON or protobuf, gzipped or not.
aimem bio serve my-project --agent checkout-bot \
--session-key session.id \
--endpoint-file /run/agent/otlp-endpointRun one per agent. Every payload the collector accepts is stored under the
agent named by --agent. A payload's own aimem.agent.id attribute is kept
like any other field but does not route the write. There is no provisioning
step: before it publishes its endpoint, the collector creates the agent's
namespace and tables if they do not exist yet.
--session-key names the attribute that carries the agent's session id, as the
agent record's capture_descriptors declare it. Pass it when the collector runs
under the agent's own credential, which is not granted the agent record.
Without it the collector reads the key from the record. See
Scoping a collector to one agent
for the credential.
Point the agent's exporter at the published endpoint:
export OTEL_EXPORTER_OTLP_ENDPOINT="$(cat /run/agent/otlp-endpoint)"If the collector cannot write what it has taken in — a wrong Memory Bucket name, a credential without the table permissions it needs — it says so on every attempt and then stops with a non-zero exit rather than going on accepting data it cannot store. Run it under a supervisor that restarts it and surfaces that exit.
Each agent's telemetry is written to six tables — otel_spans,
otel_span_events, otel_span_links, otel_logs, otel_metric_points and
otel_metric_exemplars — plus the otel_quarantine table. bio serve creates
any that are missing before it publishes its endpoint, and bio ingest creates
them on its first write to an agent.
In otel_metric_points, a histogram point also fills count, sum, min,
max, bucket_counts and explicit_bounds, so SQL can aggregate token usage
and durations without parsing JSON. Other point types leave these columns
empty. value_json still holds every point in full.
Spans, span events and logs also carry the structured GenAI attributes as JSON:
gen_ai_input_messages, gen_ai_output_messages, gen_ai_system_instructions
and gen_ai_tool_definitions. A key-value list becomes a JSON object, with its
keys sorted, and an array becomes an array. A string attribute that holds a JSON
object or array is stored as that JSON. Any other value is stored as its JSON
scalar, so a plain string keeps its quotes ("gpt-5"). JSON has no NaN or
infinity, so a non-finite double reads as null, and as a column value on its
own it leaves the column empty. The attribute map is unchanged.
A table created before any of these columns existed gains them in place the next time the collector starts. Its earlier rows read them as null. If the credential may not change the table's schema, the collector says so and keeps writing the table as it is.
bio query <bucket> --agent <ID> [--table <TABLE>] [--where <EXPR>] [--limit N]
Read an agent's telemetry back, as JSON lines. --table defaults to
otel_spans and --limit to 100. --where takes one filter,
session_id = <value>, which narrows the read to a single agent session. The
session is whatever identifier the harness itself emits — nothing to configure —
so a harness that names it something the reader does not recognise leaves the
column empty and the filter matches nothing.
aimem bio query my-project --agent checkout-bot --limit 20
aimem bio query my-project --agent checkout-bot --table otel_logs \
--where "session_id = 2f9c1b04"bio ls <bucket>[.<agent>]
List a Memory Bucket's namespaces — one per agent that has telemetry, plus any you
made yourself with bio create — or the tables in one of them.
aimem bio ls my-project # namespaces
aimem bio ls my-project.checkout-bot # that agent's tablesbio export <bucket> --agent <ID> --output <FILE> [--table <TABLE>] [--where <EXPR>]
Write every row of an agent's table to a Parquet file, for engines that cannot
read the tables directly, such as DuckDB and Spark. Unlike bio query it has no
row limit. Each timestamp is written in microseconds, the unit those engines
map, and the exact value is kept beside it as an integer <column>_unix_nano.
--table defaults to otel_spans, and --where takes the same
session_id = <value> filter as bio query.
aimem bio export my-project --agent checkout-bot --output spans.parquetbio ingest <bucket> <path> [--session-key <ATTRIBUTE>]
Load OTLP/JSON from a file or directory — for backfilling telemetry captured before the collector was running, or for replaying a capture. Routed the same way as live telemetry, and idempotent per payload: re-ingesting a file adds no duplicate rows while its record is still held, which covers replaying a capture or re-running a backfill. The record is bounded, so a replay is not deduplicated indefinitely against a table that has been written many times since.
--session-key names the attribute that carries the session id, as the agents'
records declare it. It defaults to session.id.
aimem bio ingest my-project ./otel-traces.jsonbio create <bucket>.<namespace>.<table> --schema <FILE>
Create a table of your own in the Memory Bucket, alongside the telemetry ones.
--schema accepts a raw Iceberg struct schema or a friendly ordered field
list ([{"name":"id","type":"string"}, …]); --schema - reads from stdin.
Idempotent — an existing table with a matching schema is a no-op, and a create
against an incompatible existing schema (a missing field, or a
type/requiredness mismatch) is rejected.
aimem bio create my-project.app.events --schema schema.jsonWhat's next
- Configuration — the full mount-flag / YAML reference.
aimemreference — workspace mode, memory warmup, SKILLS.- Operations — per-sandbox recipes, logging, metrics.
AIStor Memory — the agent's memory, in three forms
The full feature surface across the three forms of one memory — Workspace, Long-term memory (warmup, annotations, metadata, search, structured memory, skills), and the secrets Vault — with all the operator reference.
Configuration
YAML-key reference for the AIStor Memory mount — how you point an agent at its memory on a MinIO AIStor Memory Bucket. Covers the local staging store, multi-endpoint, health checks, request timeout, metadata TTL, FUSE / S3 client tunables.