Metadata-Version: 2.5
Name: cortexdb-cli
Version: 0.7.0
Summary: Command-line interface for CortexDB — the long-term memory layer for AI.
Project-URL: Homepage, https://cortexdb.ai
Project-URL: Documentation, https://cortexdb.ai/docs
Project-URL: Repository, https://github.com/cortexdb/cortexdb
Project-URL: Issues, https://github.com/cortexdb/cortexdb/issues
Author-email: CortexDB Team <team@cortexdb.ai>
License-Expression: Apache-2.0
Keywords: agents,ai,cli,cortexdb,llm,memory
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: httpx>=0.27
Requires-Dist: prompt-toolkit>=3.0
Requires-Dist: rich-click>=1.7
Requires-Dist: rich>=13.0
Requires-Dist: tomli-w>=1.0
Requires-Dist: tomli>=2.0; python_version < '3.11'
Description-Content-Type: text/markdown

# cortexdb-cli

Command-line interface for [CortexDB](https://cortexdb.ai) — the long-term memory layer for AI systems.

Wraps the v1 HTTP API in a small, fast Click + Rich CLI. Anonymous signup
in one command, no email or card; works against the public SaaS or any
self-hosted CortexDB deployment. Version 0.7.0 covers CortexDB 0.14.0,
shared memory included: the access API, change sets, the directory,
applications, rollups, publishing and the new erasures.

## Install

```bash
pip install cortexdb-cli
```

Requires Python 3.10+.

## Quickstart

```bash
# 1. One-time setup — anonymous signup, writes ~/.cortexdb/state.json
cortexdb init

# 2. Store a memory
cortexdb experience "Q3 revenue: $2.4M. We're on track for $10M ARR by year-end."

# 3. Recall it
cortexdb recall "Q3 revenue?"

# 4. Or just type — drops into a REPL
cortexdb
```

The signup token has a 7-day TTL on the free tier.

**Re-running `cortexdb init` does not refresh it.** `init` reuses an existing
identity and changes nothing; against an expired one it refuses and exits 3.
That is deliberate: a new identity is a new *brain*, and memories written
under the old actor stay where they are, unreachable from the new config.

When a token expires you have two safe options:

- `cortexdb init --api-key <token> --actor <actor>` — keep the same brain
  with a token you already hold (e.g. from your IdP).
- `cortexdb init --force` — deliberately start a NEW brain. The previous
  identity is backed up to `state.json.replaced` first.

For a second brain alongside the first, isolate instead of replacing:
`cortexdb --config-dir <dir> init`, or set `CORTEXDB_HOME`.

## What's new for CortexDB 0.14.0 (cortexdb-cli 0.7.0)

CortexDB 0.14.0 is the breaking release of shared memory. What changes for a
CLI user:

- **Break-glass.** On `cloud_shared_saas` the operator key's data reads are
  denied by default (`CORTEX_OPERATOR_DATA_READS=deny`): they answer 403
  `BREAK_GLASS_REQUIRED` without `X-Cortex-Break-Glass`. Every command that
  calls the server takes `--break-glass REASON --break-glass-ticket TICKET
  [--break-glass-note TEXT]` (`--ticket` for short; also before the
  subcommand, or as `CORTEXDB_BREAK_GLASS`, `CORTEXDB_BREAK_GLASS_TICKET`,
  `CORTEXDB_BREAK_GLASS_NOTE`). The reason is one of `incident`, `legal`,
  `support`, `security`, `migration`, `restore` or `other`.
- **Typed errors.** Every refusal prints its code, its `details`, a one-line
  hint and whether it is retriable; `--json` prints `{"error": {...}}` on
  stderr. `BREAK_GLASS_REQUIRED`, a confinement denial, `ACCESS_RESTORE_PENDING`,
  `NOTICE_UNAVAILABLE`, the `CHANGESET_*` codes, `ACCESS_LIMIT_REACHED`,
  `SUBJECT_UNMAPPED`, `PUBLISH_PERSON_REQUIRED`, `FRESH_AUTH_REQUIRED`,
  `CONSISTENCY_TOKEN_INVALID`, `WAIT_TIMEOUT`, `SCOPE_MOVING` and
  `FORMAT_UPGRADE_PENDING` each say what to do.
- **Strict forget selectors.** The server refuses a selector field it does not
  know (422 `unknown_selector_field`). The REPL's `/forget QUERY` sent one: it
  now lists the events a recall of QUERY returns and forgets the ones you
  pick, by id. `cortexdb forget --query` does the same (a script passes
  `--yes` or `--preview`). `--cascade none` is gone: the cascades are
  `derived_only` and `redact_events`.
- **Views at org-tree scopes.** `recall`, `answer` and `compose` send a view
  only when you choose one, so a read at a team, an org, a group or a
  compartment gets the server's default (granular there) instead of 422
  `VIEW_NOT_ALLOWED_AT_SCOPE`.
- **Tokens.** A token that carries `scopes` holds only the families its
  entries name, lifetimes are capped (7 days for a person or an agent, 30 for
  a service, 24 hours with chain claims), and `act` must name a delegable
  agent. Every mint names its tenant root (`--scope`, `--tenant` or its
  `--confine` entries); only the operator mints deployment-wide, for a
  service. A minted token holds no more than its minter. `cortexdb tokens
  mint` mints with every field: `--confine`, `--exact` (the `CAP:PATH!`
  form), `--cap`, `--tenant` and the chain claims.
- **Names live in the directory.** A scope record's `tree.display_name` is
  refused; use `cortexdb directory put`.
- **A read's purpose, a record's texts, legal holds.** `--purpose ID` declares
  what a read is for (`recall`, `search`, `answer`, `compose`, `access check`,
  `access explain`, `access authzen evaluate`); `cortexdb access texts erase
  PATH` erases the free text a registry record names on every replica; `forget`
  and its preview show what a legal hold kept. `beliefs create` takes
  `--idempotency-key`, `beliefs why` and `conflicts show` take `--scope`,
  `facts timeline --as-of` is applied, `scopes list` pages (`--cursor`,
  `--all`), and `publish` and `access records` return consistency tokens.
- **Fixed against 0.14.0** (`COVERAGE.md` has the whole audit): `experience
  "text" --wait ...` and `experience bulk FILE` (the group swallowed both),
  `search` (sent a budget key the server refuses), `facts timeline`
  (`--predicate` is required), `verify` and `apply` (wrote to a scope type no
  preset registers), the forget receipt, and `code import-scip` /
  `import-index`. `scopes register --owner` sends the Owner as a roster
  entry, which every server honours (servers before the final 0.14.0 dropped
  the `owner` field 0.6.0 sent).

## Commands

```
cortexdb init                                 anonymous signup; persist token + actor
cortexdb preflight | plan | apply | resume | status | doctor | verify | cleanup
cortexdb experience "..."                     store a memory (POST /v1/experience)
cortexdb experience bulk file.jsonl           bulk ingest (POST /v1/experience/bulk)
cortexdb recall   "..."                       recall a stratified context pack
cortexdb search   "..."                       granular event-level search
cortexdb answer   "..."                       recall + LLM answer
cortexdb compose  "..."                       a markdown document from memory
cortexdb forget   --memory-id | --idempotency-key | --capture-key ...
cortexdb episodes {list,get,delete}
cortexdb entities {list,get,link}
cortexdb facts    {list,timeline}
cortexdb beliefs  {list,why,build,create}
cortexdb conflicts {list,show,resolve}
cortexdb claims   {history}
cortexdb concepts {list,coverage,synthesize}
cortexdb scopes   {list,register,members}
cortexdb access   {check,explain,lookup,limits,enrich,records,restore-ack,rehome,watermarks,accounts,authzen}
cortexdb changes  {stage,parts,preview,activate,get,discard}
cortexdb watch    [ROOT] [--follow]
cortexdb notices  {list,ack}
cortexdb apps     {put,get}
cortexdb directory {put,get,delete,search}
cortexdb rollups  {list,get,totals}
cortexdb publish  --target ... --event | --rollup ...
cortexdb erase    {person,tenant,party,status,receipt,verify}
cortexdb tokens   {mint}
cortexdb auth     {whoami,signup,tokens,revoke}
cortexdb policy   {effective,deployment}
cortexdb admin    {health,usage,layers,retention,wal,access,auth,rollups}
cortexdb audit    {chain,verify}
cortexdb import   data.json | backup.jsonl --server
cortexdb export   -o backup.json
cortexdb code     {add,remove,status,import-scip,import-coverage,export-index,import-index,pin,gc,matrix,watch}
cortexdb config   {show,set}
cortexdb wire     --harness ...
cortexdb                                      interactive REPL
```

Every command that calls the server takes `--json` and the break-glass
options. A command whose scope is optional uses your default scope; one that
takes a tenant root uses the first segment of it.

### Reads: consistency, read sets, coverage

`recall`, `search`, `answer` and `compose` take `--extra-scope SCOPE` (up to
40), `--coverage` (what was searched, authorized, and the gaps),
`--beliefs merged` (beliefs rebuilt across the read set for you), `--mounts`
(your application's admitted mounts), `--consistency`, `--at-least TOKEN` and
`--purpose ID` (the purpose the read is for: a grant whose `when` names a
purpose holds only for that one; `access check`, `access explain` and
`access authzen evaluate` decide a chain for one too). A write returns a consistency token with `--consistency`; a read that passes it
to `--at-least` sees that write:

```bash
TOKEN=$(cortexdb experience "ship on Friday" --consistency --json | jq -r .consistency_token)
cortexdb recall "ship" --at-least "$TOKEN"
```

`experience write` also takes `--provenance EVENT_ID` (erasing the source
erases the write), `--intent` and `--idempotency-key`.

### access

```bash
cortexdb access check org:acme/team:eng --role writer
cortexdb access check org:acme/team:eng --for user:bob         # another chain: Owners and the operator
cortexdb access explain org:acme/team:eng --memory evt_01...
cortexdb access lookup scopes org:acme --include-private --all
cortexdb access lookup principals org:acme/team:eng
cortexdb access limits org:acme
cortexdb access enrich org:acme/team:eng
cortexdb access records org:acme --all                         # a restore's registry listing
cortexdb access restore-ack org:acme                           # acknowledge a restored root
cortexdb access rehome org:acme/source:slack/container:launch evt_01...
cortexdb access watermarks put org:acme/source:slack --at 2026-10-26T00:00:00Z
cortexdb access accounts org:acme --account slack:T1=U123
cortexdb access texts erase org:acme/team:eng --yes             # a record's reasons, matter and notes, everywhere
cortexdb access authzen evaluate --subject user:alice --action read --resource org:acme/team:eng
```

A chain is given with `--for SUB` and `--act`, `--app`, `--client`, `--run`,
`--auth-time`, `--cap`, `--confine`, or whole with `--chain JSON`.

### changes

Change sets write registry records all at once. Stage them, preview the access
diff, activate with the preview's hash:

```bash
cortexdb changes stage org-compile --file records.json --reason "first compile"
cortexdb changes preview org-compile --people
cortexdb changes activate org-compile          # previews, shows the diff, asks, activates
cortexdb changes get org-compile
cortexdb changes discard org-compile
```

`--file` holds a list of records (each a put), operations
(`{"path", "op": "put" | "delete", "record"}`), `{"records": [...]}` or
`{"parts": [...]}`; `--delete PATH` adds deletes; `changes parts` stages more.

### watch and notices

```bash
cortexdb watch org:acme                         # the current position
cortexdb watch org:acme --after wp1.... --follow
cortexdb notices list org:acme                  # who read what of yours
cortexdb notices ack org:acme --seq 3           # or --through POSITION, or --all
```

`--follow` long-polls from each page's position (one JSON line per page with
`--json`) and prints the last position when stopped.

### apps

```bash
cortexdb apps put notes --kind note --kind decision --mount-prefix org:acme/source:slack
cortexdb apps get notes
```

### directory

```bash
cortexdb directory put user:alice --display-name "Alice Moreau" --email alice@acme.example \
    --account slack:T1=UALICE
cortexdb directory put user:alice --merge --title "Staff engineer"   # read, change, write on its version
cortexdb directory put org:acme/team:eng --display-name "Engineering"  # a scope's name entry
cortexdb directory get user:alice
cortexdb directory search ali
cortexdb directory delete user:temp
```

### rollups and publish

```bash
cortexdb rollups list --scope org:acme/team:eng/aud:roll
cortexdb rollups get roll_01... --scope org:acme/team:eng/aud:roll
cortexdb rollups totals --scope org:acme/team:eng/aud:roll --from 2026-09 --to 2026-10
cortexdb publish --target org:acme/team:eng --from org:acme/user:alice --event evt_01...
```

Only a person publishes: a `user:` token with no `act` or `run`, your own or
one through an admitted application whose client says `client: person`. An
agent, a run, a service, an application token with no `client` and the
operator key get 403 `PUBLISH_PERSON_REQUIRED`.

### forget and erase

```bash
cortexdb forget --memory-id evt_01... --reason "user request"
cortexdb forget --idempotency-key note-42 --key-caller user:alice --reason "deleted"   # reads nothing
cortexdb forget --capture-key cap:upload-7 --reason "withdrawn"
cortexdb erase person user:dev --scope org:acme --yes          # no server dry run: asks, or --yes
cortexdb erase tenant --scope org:acme                         # a dry run
cortexdb erase tenant --scope org:acme --apply --yes
cortexdb erase party pat@example.com --scope org:acme          # a preview
cortexdb erase party pat@example.com --scope org:acme --apply --yes
cortexdb erase status erasure_01... --wait 120
cortexdb erase receipt erasure_01...
cortexdb erase verify erasure_01...
```

A forget needs Owner at its scope. The erasures are the trusted operator's.

### tokens

```bash
cortexdb tokens mint --subject user:bob --confine scope.read.local:org:acme/team:eng
cortexdb tokens mint --subject user:bob --exact scope.read.local:org:acme/team:eng   # sent as ...eng!
cortexdb tokens mint --subject user:alice --act agent:helper --run run-7 --client agent \
    --confine scope.write:org:acme/user:alice
cortexdb tokens mint --subject user:carol --scope org:acme --cap scope.read
```

Every mint names its tenant root: `--scope` (a scope of it, where your
`auth.mint` is checked; it never confines the token), `--tenant` (hosted; it
takes no `--scope`) or its `--confine` / `--exact` entries, all in one root.
A mint naming none is the operator's, for a `service:` or `system:` subject
(403 `deployment_mint_requires_operator` otherwise). `auth tokens` takes the
same flags and prints the raw JSON.

### admin

```bash
cortexdb admin access report org:acme
cortexdb admin access tenant-settings org:acme --operator-data-reads deny
cortexdb admin access tenant-settings org:acme --operator-data-reads allow \
    --break-glass support --break-glass-ticket SUP-1            # lowering from deny
cortexdb admin access tenant-binding org:acme --from default   # a dry run; --apply rebinds
cortexdb admin access restore --scope org:acme --reason "nothing changed since the backup"
cortexdb admin auth reload
cortexdb admin rollups status org:acme
```

## Configuration

Three layers, in precedence order:

1. **CLI flags** — `--api-key`, `--endpoint`, `--actor`, `--scope`, `--profile`
2. **Environment** — `CORTEXDB_API_KEY`, `CORTEXDB_URL`, `CORTEXDB_ACTOR`, `CORTEXDB_SCOPE`
3. **Persisted state**:
   - `~/.cortexdb/config.toml` — endpoint, profile names (human-editable)
   - `~/.cortexdb/state.json` — token, actor, scope, expiry (managed by `init`, 0600 on POSIX)

The state.json format matches the cortexdb-mcp 0.3.0 server's, so you can
copy state across to use both tools from the same anonymous identity.

## Pipe-friendly

Auto-detects when stdout isn't a TTY and emits JSON:

```bash
cortexdb recall "Q3 revenue" | jq .context_block
cortexdb entities list      | jq '.[].subject'
echo "remember this"        | cortexdb experience -
```

Force JSON mode any time with `--json`, before or after the subcommand.

## Auth notes

- The v1 API requires both `Authorization: Bearer <PASETO>` and `X-Cortex-Actor`.
  The CLI stamps both on every request — you never need to pass them by hand.
- 401s show the specific error code (`EXPIRED_TOKEN`, `ACTOR_MISMATCH`, …)
  and the remediation. Note that an expired token is **not** fixed by re-running
  `cortexdb init` — see the identity note above; that would mint a different
  brain rather than restore access to yours.
- 403s cite the missing capability and the policy tier that denied, or the
  `--confine` entry a confined token lacks. If a recall returns
  `diagnostics.read denied`, pass `--diagnostics none` — free-tier tokens don't
  carry the `diagnostics.read` capability.

## License

Apache-2.0
