xmemcli 0.0.1__tar.gz → 0.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
xmemcli-0.0.3/PKG-INFO ADDED
@@ -0,0 +1,376 @@
1
+ Metadata-Version: 2.4
2
+ Name: xmemcli
3
+ Version: 0.0.3
4
+ Summary: Command-line client for the xmemory HTTP API: PKCE auth, instances, read/write, schema and XMD tools.
5
+ Keywords: api,cli,llm,memory,xmemory
6
+ Requires-Python: <4,>=3.12
7
+ Description-Content-Type: text/markdown
8
+
9
+ # `xmemcli` — xmemory command-line client
10
+
11
+ Single-command CLI for reading from, writing to, and managing xmemory instances over the HTTP API at `$XMEM_API_URL` (default `https://api.xmemory.ai`), using an API key from the Console UI or `xmemcli auth login`.
12
+
13
+ Full command reference is included below.
14
+
15
+ ## Usage
16
+
17
+ ```text
18
+ xmemcli auth login [--no-browser] [--timeout S] [--console-url URL]
19
+ xmemcli auth logout
20
+ xmemcli auth status
21
+ xmemcli read <query>
22
+ xmemcli write <text>
23
+ xmemcli write-status <write_id> [<id> …]
24
+ xmemcli quota
25
+ ```
26
+
27
+ Global flags / env: `--api-key` / `$XMEM_API_KEY`, `--instance-id` / `$XMEM_INSTANCE_ID`, `--api-url` / `$XMEM_API_URL`, `--rc-dir` / `$XMEM_RC_DIR`, `--json`, `--verbose`. See `xmemcli help options`.
28
+
29
+ Credential resolution: `--api-key` → `$XMEM_API_KEY` → nearest `.xmemrc.json` (walk up from `--rc-dir` toward `$HOME`). Origin: `--api-url` → `$XMEM_API_URL` → rc `api_url` → default.
30
+
31
+ ## Read / write modes
32
+
33
+ | CLI | API field |
34
+ |-----|-----------|
35
+ | `xmemcli write --extraction fast` (default) | `extraction_logic: "fast"` |
36
+ | `xmemcli write --extraction deep` | `extraction_logic: "deep"` |
37
+ | `xmemcli write --no-wait` | async write; poll with `write-status` |
38
+ | `xmemcli read --read-mode single` (default) | `mode: "single-answer"` |
39
+ | `xmemcli read --read-mode raw` | `mode: "raw-tables"` |
40
+ | `xmemcli read --read-mode xresponse` | `mode: "xresponse"` |
41
+
42
+ `--read-mode` selects the **server-side answer shape**; `--json` and the TTY rule govern stdout format.
43
+
44
+ ## Curated output
45
+
46
+ The CLI does not echo raw API payloads. Server internals (`sql`, `diff_plan`, extraction trees) are never emitted. `--verbose` adds `trace_id` and `console_url` when present.
47
+
48
+ ## Output personality — JSON vs pretty
49
+
50
+ - **Non-TTY stdout** or **`--json`**: exactly one JSON document.
51
+ - **Interactive TTY** without `--json`: short one-line summaries per command.
52
+
53
+ Scripts can rely on `xmemcli … | jq` without `--json`.
54
+
55
+ ## Example session
56
+
57
+ ```bash
58
+ export XMEM_API_KEY="xmem_..."
59
+ export XMEM_INSTANCE_ID="<uuid>"
60
+
61
+ xmemcli write "John likes orange"
62
+ xmemcli read "what colour does John like?"
63
+
64
+ ID1=$(xmemcli write --no-wait "Ivy likes amber" | jq -r .write_id)
65
+ ID2=$(xmemcli write --no-wait "Lev likes indigo" | jq -r .write_id)
66
+ xmemcli write-status "$ID1" "$ID2"
67
+ ```
68
+
69
+ ## Install
70
+
71
+ Requires **Python 3.12+**. Stdlib only — no runtime dependencies.
72
+
73
+ ```bash
74
+ uv tool install xmemcli
75
+ # or
76
+ pip install xmemcli
77
+ ```
78
+
79
+ Then:
80
+
81
+ ```bash
82
+ xmemcli version
83
+ xmemcli auth login
84
+ ```
85
+
86
+ Version: **0.0.3**.
87
+
88
+
89
+ ---
90
+
91
+ # `xmemcli` auth flow — PKCE handoff and credentials
92
+
93
+ The CLI is **human-governed for key acquisition**: an AI-assisted IDE may run reads, writes, and inventory, but **acquiring an API key** stays under human control in the browser. A key must **never enter the AI transcript** — it is handed to the CLI out-of-band via `xmemcli auth login` or environment / `.xmemrc.json`.
94
+
95
+ **Model:** the CLI sends the human to **`/xmemcli/<challenge>`** on the Console, listens on **`127.0.0.1:9636/callback`**, and the Console redirects a signed short-lived **code** (not the key) to that callback.
96
+
97
+ > **Scope.** Shipped in this package: `.xmemrc.json` discovery, PKCE `auth login` / `logout` / `status`, `/whoami` consumption, and `quota`. Server endpoints: `POST /cli/handoff`, `POST /cli/token`.
98
+
99
+ ## Acquiring a key
100
+
101
+ The human either:
102
+
103
+ - **Provides a key they already hold** (`$XMEM_API_KEY`, `.xmemrc.json`, or paste at login), or
104
+ - **Creates a key** in the Console and clicks **"Use this key in the CLI"** (when the page was opened via `/xmemcli/<challenge>`).
105
+
106
+ During **onboarding**, the Console may auto-handoff an onboarding key while a short-lived cookie bridge is active.
107
+
108
+ ### Why a code, not the key
109
+
110
+ Plaintext keys in URLs leak to history and proxies. Handoff uses **PKCE + signed code + localhost callback**:
111
+
112
+ 1. CLI mints **`verifier`**, derives **`challenge`** = `base64url(SHA256(verifier))`, opens **`/xmemcli/<challenge>`**.
113
+ 2. Human clicks **"Use this key in the CLI"** → Console **`POST`s the key** to `/cli/handoff` bound to the challenge → receives a short-lived **`code`**.
114
+ 3. Browser navigates to **`http://127.0.0.1:9636/callback?code=…&state=<challenge>`** — key never in the URL.
115
+ 4. CLI **`POST /cli/token`** with `{ code, verifier }` → receives key → writes `0600` `.xmemrc.json`.
116
+
117
+ ### Sequence
118
+
119
+ ```
120
+ AI-assisted IDE ── xmemcli auth login ──► CLI: PKCE verifier + localhost listener
121
+ Human ── opens Console URL ──► creates key → "Use this key in the CLI"
122
+ CLI ◄── localhost redirect ── redeems code + verifier → writes .xmemrc.json
123
+ AI-assisted IDE ── xmemcli read/write ──► CLI resolves key; never handles plaintext key
124
+ ```
125
+
126
+ ## Credential store (`.xmemrc.json`)
127
+
128
+ Project-local **`.xmemrc.json`**: `{email, api_url, api_key}`. Found by walking up from `--rc-dir` / CWD, ceiling `$HOME`.
129
+
130
+ Resolution order: `--api-key` → `$XMEM_API_KEY` → `.xmemrc.json`. Origin: `--api-url` → `$XMEM_API_URL` → rc `api_url` → default. Explicit key + mismatched rc origin is rejected (localhost-key-at-prod guard).
131
+
132
+ ## Identity — `/whoami`
133
+
134
+ `xmemcli auth status` calls **`GET /whoami`** with the active bearer key and reports `{authenticated, email, key_prefix}`. Exit `0` when the key resolves; auth error when it does not.
135
+
136
+ ## Security model
137
+
138
+ | Threat | Mitigation |
139
+ | --- | --- |
140
+ | Key in AI transcript | localhost callback → `0600` store; login stdout shows `key_prefix` only |
141
+ | Key in URL | URL carries code only; key over TLS on handoff/token |
142
+ | Captured code replay | PKCE verifier never leaves CLI; code is TTL-bounded |
143
+ | CSRF on callback | state = PKCE challenge; redeem requires verifier |
144
+ | Wrong Console page | CLI button only on `/xmemcli/<challenge>` |
145
+
146
+ Fixed port **9636** ("xmem" on phone keypad) allows SSH/devcontainer forwarding; security rests on PKCE, not port secrecy.
147
+
148
+ ## Quota (observe vs escalate)
149
+
150
+ **`xmemcli quota`** observes usage freely. **Raising** limits requires human approval in the Console — the CLI must not self-grant quota increases.
151
+
152
+ ---
153
+
154
+ # `xmemcli` — capabilities reference
155
+
156
+ **Version:** `0.0.3` (see `xmemcli version`)
157
+
158
+ `xmemcli` is the command-line client for the **xmemory HTTP API**. It is **human-governed for key acquisition**; an AI-assisted IDE may run reads, writes, and inventory once credentials exist. Humans acquire API keys and change quota limits in the **Console UI**.
159
+
160
+ ```bash
161
+ xmemcli … # installed CLI
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Commands
167
+
168
+ Every command below has dedicated help — see [Help](#help).
169
+
170
+ ### Data
171
+
172
+ | Command | Description |
173
+ |---------|-------------|
174
+ | **`write`** `<text>` | Sync write (`POST …/write`). `--extraction fast\|deep` (default `fast`). `--no-wait` queues async write, returns `write_id`. |
175
+ | **`write-status`** `<write_id>` … | Poll async writes until terminal or `--timeout` (default 60s). Accepts multiple ids. |
176
+ | **`read`** `<query>` | Read from active instance. `--read-mode single\|raw\|xresponse`, `--scope TYPE:ID` (repeatable), `--scope-relations`. |
177
+
178
+ Requires **`--instance-id`** or **`$XMEM_INSTANCE_ID`** for read/write (or auto-pick when exactly one instance is visible — see [Global flags](#global-flags--environment)).
179
+
180
+ ---
181
+
182
+ ### Org inventory
183
+
184
+ Permission-filtered view of what this API key can see.
185
+
186
+ | Command | Description |
187
+ |---------|-------------|
188
+ | **`org list clusters`** | Clusters visible to this credential |
189
+ | **`org list instances`** | Instances visible to this credential |
190
+ | **`org list keys`** | API keys visible to this credential (metadata only; plaintext never returned) |
191
+
192
+ ---
193
+
194
+ ### Instances
195
+
196
+ | Command | Description |
197
+ |---------|-------------|
198
+ | **`instance get`** `<instance_id>` | Fetch one instance |
199
+ | **`instance create`** | Create from XMD/JSON schema. Required `--name`; schema via `--schema-file` or `--schema-stdin`. |
200
+
201
+ ---
202
+
203
+ ### Schema & XMD
204
+
205
+ XMD (xmemory Data) is the typed schema format for instances. These commands mirror the Console schema workflow (read/update/dry-run/migrations, LLM generate/enhance, and validation).
206
+
207
+ #### Command map
208
+
209
+ | User task | CLI command | Notes |
210
+ |----------|-------------|-------|
211
+ | Read live schema | **`schema get`** `[instance_id]` | Live schema for one instance. `-o` writes YAML. |
212
+ | Apply migration | **`schema update`** `[instance_id]` | `--schema-file`, optional `--migration-plan`, `--confirm-destructive`. |
213
+ | Preview migration | **`schema dry-run`** `[instance_id]` | Same flags as `schema update`; returns planned DDL without applying. |
214
+ | List migrations | **`schema migrations list`** `[instance_id]` | Newest first. `--limit`, `--before-id`, `--include-yaml`. |
215
+ | Fetch one migration | **`schema migrations get`** `<migration_id>` | Instance from `--instance-id` / `$XMEM_INSTANCE_ID`. `--include-yaml`. |
216
+ | Enhance bound schema | **`xmd enhance --from-instance`** `<description>` | Uses live schema; requires instance id. |
217
+ | Synthesize schema | **`xmd generate`** `<description>` | Cluster-scoped LLM synthesis. `-o` writes YAML. |
218
+ | Enhance from file | **`xmd enhance`** `[schema_file]` `<description>` | From a file, or `--from-instance` for bound enhance. `-o`, `--plan-output`. |
219
+ | Create instance | **`instance create`** | `--name`, `--schema-file` or `--schema-stdin`. |
220
+ | Validate schema | **`xmd validate`** / **`validate-yaml`** / **`validate-json`** | Cluster-scoped server validation. |
221
+ | Convert JSON Schema | **`xmd convert`** | JSON Schema → XMD YAML via the API (`validate_json_schema`). |
222
+
223
+ **Not exposed in CLI** (Console / suggestion-engine only today): pending schema suggestions review/apply.
224
+
225
+ #### Typical workflow
226
+
227
+ ```text
228
+ # 1. Synthesize or enhance
229
+ xmemcli xmd generate "people and their pets" -o schema.yml
230
+ xmemcli xmd enhance schema.yml "add a Pet.breed field" -o next.yml --plan-output plan.json
231
+
232
+ # 2. Validate before create or update
233
+ xmemcli xmd validate next.yml
234
+
235
+ # 3. Create instance OR migrate existing
236
+ xmemcli instance create --name demo --schema-file schema.yml
237
+ xmemcli schema dry-run INST_ID --schema-file next.yml --migration-plan plan.json
238
+ xmemcli schema update INST_ID --schema-file next.yml --migration-plan plan.json --confirm-destructive
239
+
240
+ # 4. Inspect history
241
+ xmemcli schema migrations list INST_ID
242
+ xmemcli schema migrations get MIGRATION_UUID
243
+ ```
244
+
245
+ #### Commands
246
+
247
+ | Command | Description |
248
+ |---------|-------------|
249
+ | **`schema get`** `[instance_id]` | Live XMD schema. Optional `-o` file. |
250
+ | **`schema update`** `[instance_id]` | Replace schema from `--schema-file`. Optional `--schema-type`, `--migration-plan`, `--confirm-destructive`. |
251
+ | **`schema dry-run`** `[instance_id]` | Preview migration (same schema/plan flags as update). |
252
+ | **`schema migrations list`** `[instance_id]` | Applied migrations, newest first. `--limit` (default 50), `--before-id`, `--include-yaml`. |
253
+ | **`schema migrations get`** `<migration_id>` | One record; instance from global instance flags. `--include-yaml`. |
254
+ | **`xmd generate`** `<description>` | LLM-synthesize XMD. Optional `-o`. Requires cluster resolution. |
255
+ | **`xmd enhance`** `[schema_file]` `<description>` | LLM-augment schema from file, or **`--from-instance`** for live schema. `-o`, `--plan-output`. |
256
+ | **`xmd validate`** `<schema_file>` | Validate; YAML vs JSON inferred from `.json` extension. |
257
+ | **`xmd validate-yaml`** `<schema_file>` | Force YAML validation endpoint. |
258
+ | **`xmd validate-json`** `<schema_file>` | Force JSON Schema validation endpoint. |
259
+ | **`xmd convert`** `<json_schema_file>` | JSON Schema → XMD YAML via the API (`validate_json_schema`). Optional `-o`, `--root-object`. |
260
+
261
+ Instance id for `schema *` commands: positional `[instance_id]`, else **`--instance-id`** / **`$XMEM_INSTANCE_ID`** (except `migrations get`, which takes only `migration_id`).
262
+
263
+ ---
264
+
265
+ ### Auth & meta
266
+
267
+ | Command | Description |
268
+ |---------|-------------|
269
+ | **`auth login`** | PKCE via Console `/xmemcli/<challenge>` → `.xmemrc.json`. `--no-browser`, `--timeout`, `--console-url`. |
270
+ | **`auth logout`** | Remove active `.xmemrc.json` |
271
+ | **`auth status`** | Call `/whoami`. No key → exit 0; bad key → auth error; good key → email + prefix. |
272
+ | **`version`** | CLI release version (no network) |
273
+ | **`status`** | Local health: version + whether `.xmemrc.json` exists (no network) |
274
+
275
+ **Console `/xmemcli` routing:**
276
+
277
+ - **Onboarding** → silent onboarding-key handoff to the CLI (no overlay, no button click).
278
+ - **Post-onboarding** → API Keys create modal → “Use this key in the CLI”.
279
+
280
+ ---
281
+
282
+ ### Quota (read-only)
283
+
284
+ | Command | Description |
285
+ |---------|-------------|
286
+ | **`quota`** | Usage / limit / window start for the key's cluster (derived from instance → cluster). |
287
+
288
+ - **Default:** exit `0` when quota is readable; stderr **warning** when usage is high.
289
+ - **`--fail-if-under THRESHOLD`** — exit non-zero when **remaining** quota is below that share of the limit (`0.1` or `10%`). See `xmemcli help quota`.
290
+
291
+ Quota **increases** are Console-only — see [What `xmemcli` does not do](#what-xmemcli-does-not-do).
292
+
293
+ ---
294
+
295
+ ## Help
296
+
297
+ `xmemcli` supports root `-h` / `--help` (same overview as bare `xmemcli`) and the **`help`** subcommand for nested topics.
298
+
299
+ | Invocation | What you get |
300
+ |------------|--------------|
301
+ | **`xmemcli`** | Full command overview (grouped list of every capability) |
302
+ | **`xmemcli help`** | Same as bare `xmemcli` |
303
+ | **`xmemcli help options`** | Global flags (`--api-url`, `--api-key`, `--json`, …) |
304
+ | **`xmemcli help <topic>`** | Usage, options, and subcommands for that topic |
305
+ | **`xmemcli <cmd> … -h`** / **`--help`** | Same as `help <topic>` for that command path |
306
+
307
+ **Every command in this document has help.** Examples:
308
+
309
+ ```text
310
+ xmemcli help write
311
+ xmemcli help write-status
312
+ xmemcli help read
313
+ xmemcli help org
314
+ xmemcli help org list instances
315
+ xmemcli help instance create
316
+ xmemcli help schema
317
+ xmemcli help schema get
318
+ xmemcli help schema update
319
+ xmemcli help schema dry-run
320
+ xmemcli help schema migrations
321
+ xmemcli help schema migrations list
322
+ xmemcli help schema migrations get
323
+ xmemcli help xmd
324
+ xmemcli help xmd generate
325
+ xmemcli help xmd enhance
326
+ xmemcli help xmd validate
327
+ xmemcli help xmd validate-yaml
328
+ xmemcli help xmd validate-json
329
+ xmemcli help xmd convert
330
+ xmemcli help auth login
331
+ xmemcli help quota
332
+ xmemcli help options
333
+ ```
334
+
335
+ Nested topics work at any level that exists in the parser (`help org`, `help org list`, `help org list keys`, …). Unknown topics print a short error and suggest `xmemcli` or `help options`.
336
+
337
+ ---
338
+
339
+ ## What `xmemcli` does **not** do
340
+
341
+ | Area | Use the Console instead |
342
+ |------|-------------------------|
343
+ | **Quota increases** | No `quota request-increase`. Observe with `xmemcli quota`; **raise limits in Billing / Quotas UX**. |
344
+ | **Routine API key creation** | Post-onboarding: API Keys UI (CLI opens that flow via `/xmemcli`). |
345
+ | **Billing, plans, trial paywall** | Console only |
346
+ | **Users, roles, org admin** | Console only |
347
+ | **Instance chat / trace inspection** | Console only |
348
+ | **Cluster create/delete** | CLI lists clusters; provisioning in Console |
349
+ | **`read --extraction deep`** | Server has no read-depth knob today |
350
+ | **Raw REST proxy** | Curated response fields only |
351
+ | **Instance deletion** | **Not available in the CLI** — explicitly disabled and reserved for manual human use in the Console. |
352
+
353
+ On HTTP **402** (quota exhausted), stop and ask a human to extend quota in the Console.
354
+
355
+ ---
356
+
357
+ ## Global flags & environment
358
+
359
+ These apply **before** any subcommand (`xmemcli help options`).
360
+
361
+ | Flag | Env var | Purpose |
362
+ |------|---------|---------|
363
+ | `--api-url` | `XMEM_API_URL` | API origin (default `https://api.xmemory.ai`) |
364
+ | `--api-key` | `XMEM_API_KEY` | Bearer API key |
365
+ | `--instance-id` | `XMEM_INSTANCE_ID` | Default instance for read/write and cluster derivation |
366
+ | `--rc-dir` | `XMEM_RC_DIR` | Where `auth login` writes `.xmemrc.json`; reads walk **up** toward `$HOME` |
367
+ | `--json` | — | Force one JSON document on stdout |
368
+ | `--verbose` | — | Add `trace_id` / `console_url` when present (never SQL, diff plans, or internals) |
369
+
370
+ **Credential resolution:** `--api-key` → `$XMEM_API_KEY` → nearest `.xmemrc.json` → *Not logged in — run `xmemcli auth login` first.*
371
+
372
+ **Origin resolution:** `--api-url` → `$XMEM_API_URL` → rc `api_url` → default.
373
+
374
+ **Instance resolution (read/write):** `--instance-id` → `$XMEM_INSTANCE_ID` → if exactly **one** instance is visible, auto-select with a **stderr warning** → else error.
375
+
376
+ **Output:** Pipes and non-TTY stdout → JSON. Interactive TTY → one-line summaries unless `--json`.
@@ -0,0 +1,368 @@
1
+ # `xmemcli` — xmemory command-line client
2
+
3
+ Single-command CLI for reading from, writing to, and managing xmemory instances over the HTTP API at `$XMEM_API_URL` (default `https://api.xmemory.ai`), using an API key from the Console UI or `xmemcli auth login`.
4
+
5
+ Full command reference is included below.
6
+
7
+ ## Usage
8
+
9
+ ```text
10
+ xmemcli auth login [--no-browser] [--timeout S] [--console-url URL]
11
+ xmemcli auth logout
12
+ xmemcli auth status
13
+ xmemcli read <query>
14
+ xmemcli write <text>
15
+ xmemcli write-status <write_id> [<id> …]
16
+ xmemcli quota
17
+ ```
18
+
19
+ Global flags / env: `--api-key` / `$XMEM_API_KEY`, `--instance-id` / `$XMEM_INSTANCE_ID`, `--api-url` / `$XMEM_API_URL`, `--rc-dir` / `$XMEM_RC_DIR`, `--json`, `--verbose`. See `xmemcli help options`.
20
+
21
+ Credential resolution: `--api-key` → `$XMEM_API_KEY` → nearest `.xmemrc.json` (walk up from `--rc-dir` toward `$HOME`). Origin: `--api-url` → `$XMEM_API_URL` → rc `api_url` → default.
22
+
23
+ ## Read / write modes
24
+
25
+ | CLI | API field |
26
+ |-----|-----------|
27
+ | `xmemcli write --extraction fast` (default) | `extraction_logic: "fast"` |
28
+ | `xmemcli write --extraction deep` | `extraction_logic: "deep"` |
29
+ | `xmemcli write --no-wait` | async write; poll with `write-status` |
30
+ | `xmemcli read --read-mode single` (default) | `mode: "single-answer"` |
31
+ | `xmemcli read --read-mode raw` | `mode: "raw-tables"` |
32
+ | `xmemcli read --read-mode xresponse` | `mode: "xresponse"` |
33
+
34
+ `--read-mode` selects the **server-side answer shape**; `--json` and the TTY rule govern stdout format.
35
+
36
+ ## Curated output
37
+
38
+ The CLI does not echo raw API payloads. Server internals (`sql`, `diff_plan`, extraction trees) are never emitted. `--verbose` adds `trace_id` and `console_url` when present.
39
+
40
+ ## Output personality — JSON vs pretty
41
+
42
+ - **Non-TTY stdout** or **`--json`**: exactly one JSON document.
43
+ - **Interactive TTY** without `--json`: short one-line summaries per command.
44
+
45
+ Scripts can rely on `xmemcli … | jq` without `--json`.
46
+
47
+ ## Example session
48
+
49
+ ```bash
50
+ export XMEM_API_KEY="xmem_..."
51
+ export XMEM_INSTANCE_ID="<uuid>"
52
+
53
+ xmemcli write "John likes orange"
54
+ xmemcli read "what colour does John like?"
55
+
56
+ ID1=$(xmemcli write --no-wait "Ivy likes amber" | jq -r .write_id)
57
+ ID2=$(xmemcli write --no-wait "Lev likes indigo" | jq -r .write_id)
58
+ xmemcli write-status "$ID1" "$ID2"
59
+ ```
60
+
61
+ ## Install
62
+
63
+ Requires **Python 3.12+**. Stdlib only — no runtime dependencies.
64
+
65
+ ```bash
66
+ uv tool install xmemcli
67
+ # or
68
+ pip install xmemcli
69
+ ```
70
+
71
+ Then:
72
+
73
+ ```bash
74
+ xmemcli version
75
+ xmemcli auth login
76
+ ```
77
+
78
+ Version: **0.0.3**.
79
+
80
+
81
+ ---
82
+
83
+ # `xmemcli` auth flow — PKCE handoff and credentials
84
+
85
+ The CLI is **human-governed for key acquisition**: an AI-assisted IDE may run reads, writes, and inventory, but **acquiring an API key** stays under human control in the browser. A key must **never enter the AI transcript** — it is handed to the CLI out-of-band via `xmemcli auth login` or environment / `.xmemrc.json`.
86
+
87
+ **Model:** the CLI sends the human to **`/xmemcli/<challenge>`** on the Console, listens on **`127.0.0.1:9636/callback`**, and the Console redirects a signed short-lived **code** (not the key) to that callback.
88
+
89
+ > **Scope.** Shipped in this package: `.xmemrc.json` discovery, PKCE `auth login` / `logout` / `status`, `/whoami` consumption, and `quota`. Server endpoints: `POST /cli/handoff`, `POST /cli/token`.
90
+
91
+ ## Acquiring a key
92
+
93
+ The human either:
94
+
95
+ - **Provides a key they already hold** (`$XMEM_API_KEY`, `.xmemrc.json`, or paste at login), or
96
+ - **Creates a key** in the Console and clicks **"Use this key in the CLI"** (when the page was opened via `/xmemcli/<challenge>`).
97
+
98
+ During **onboarding**, the Console may auto-handoff an onboarding key while a short-lived cookie bridge is active.
99
+
100
+ ### Why a code, not the key
101
+
102
+ Plaintext keys in URLs leak to history and proxies. Handoff uses **PKCE + signed code + localhost callback**:
103
+
104
+ 1. CLI mints **`verifier`**, derives **`challenge`** = `base64url(SHA256(verifier))`, opens **`/xmemcli/<challenge>`**.
105
+ 2. Human clicks **"Use this key in the CLI"** → Console **`POST`s the key** to `/cli/handoff` bound to the challenge → receives a short-lived **`code`**.
106
+ 3. Browser navigates to **`http://127.0.0.1:9636/callback?code=…&state=<challenge>`** — key never in the URL.
107
+ 4. CLI **`POST /cli/token`** with `{ code, verifier }` → receives key → writes `0600` `.xmemrc.json`.
108
+
109
+ ### Sequence
110
+
111
+ ```
112
+ AI-assisted IDE ── xmemcli auth login ──► CLI: PKCE verifier + localhost listener
113
+ Human ── opens Console URL ──► creates key → "Use this key in the CLI"
114
+ CLI ◄── localhost redirect ── redeems code + verifier → writes .xmemrc.json
115
+ AI-assisted IDE ── xmemcli read/write ──► CLI resolves key; never handles plaintext key
116
+ ```
117
+
118
+ ## Credential store (`.xmemrc.json`)
119
+
120
+ Project-local **`.xmemrc.json`**: `{email, api_url, api_key}`. Found by walking up from `--rc-dir` / CWD, ceiling `$HOME`.
121
+
122
+ Resolution order: `--api-key` → `$XMEM_API_KEY` → `.xmemrc.json`. Origin: `--api-url` → `$XMEM_API_URL` → rc `api_url` → default. Explicit key + mismatched rc origin is rejected (localhost-key-at-prod guard).
123
+
124
+ ## Identity — `/whoami`
125
+
126
+ `xmemcli auth status` calls **`GET /whoami`** with the active bearer key and reports `{authenticated, email, key_prefix}`. Exit `0` when the key resolves; auth error when it does not.
127
+
128
+ ## Security model
129
+
130
+ | Threat | Mitigation |
131
+ | --- | --- |
132
+ | Key in AI transcript | localhost callback → `0600` store; login stdout shows `key_prefix` only |
133
+ | Key in URL | URL carries code only; key over TLS on handoff/token |
134
+ | Captured code replay | PKCE verifier never leaves CLI; code is TTL-bounded |
135
+ | CSRF on callback | state = PKCE challenge; redeem requires verifier |
136
+ | Wrong Console page | CLI button only on `/xmemcli/<challenge>` |
137
+
138
+ Fixed port **9636** ("xmem" on phone keypad) allows SSH/devcontainer forwarding; security rests on PKCE, not port secrecy.
139
+
140
+ ## Quota (observe vs escalate)
141
+
142
+ **`xmemcli quota`** observes usage freely. **Raising** limits requires human approval in the Console — the CLI must not self-grant quota increases.
143
+
144
+ ---
145
+
146
+ # `xmemcli` — capabilities reference
147
+
148
+ **Version:** `0.0.3` (see `xmemcli version`)
149
+
150
+ `xmemcli` is the command-line client for the **xmemory HTTP API**. It is **human-governed for key acquisition**; an AI-assisted IDE may run reads, writes, and inventory once credentials exist. Humans acquire API keys and change quota limits in the **Console UI**.
151
+
152
+ ```bash
153
+ xmemcli … # installed CLI
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Commands
159
+
160
+ Every command below has dedicated help — see [Help](#help).
161
+
162
+ ### Data
163
+
164
+ | Command | Description |
165
+ |---------|-------------|
166
+ | **`write`** `<text>` | Sync write (`POST …/write`). `--extraction fast\|deep` (default `fast`). `--no-wait` queues async write, returns `write_id`. |
167
+ | **`write-status`** `<write_id>` … | Poll async writes until terminal or `--timeout` (default 60s). Accepts multiple ids. |
168
+ | **`read`** `<query>` | Read from active instance. `--read-mode single\|raw\|xresponse`, `--scope TYPE:ID` (repeatable), `--scope-relations`. |
169
+
170
+ Requires **`--instance-id`** or **`$XMEM_INSTANCE_ID`** for read/write (or auto-pick when exactly one instance is visible — see [Global flags](#global-flags--environment)).
171
+
172
+ ---
173
+
174
+ ### Org inventory
175
+
176
+ Permission-filtered view of what this API key can see.
177
+
178
+ | Command | Description |
179
+ |---------|-------------|
180
+ | **`org list clusters`** | Clusters visible to this credential |
181
+ | **`org list instances`** | Instances visible to this credential |
182
+ | **`org list keys`** | API keys visible to this credential (metadata only; plaintext never returned) |
183
+
184
+ ---
185
+
186
+ ### Instances
187
+
188
+ | Command | Description |
189
+ |---------|-------------|
190
+ | **`instance get`** `<instance_id>` | Fetch one instance |
191
+ | **`instance create`** | Create from XMD/JSON schema. Required `--name`; schema via `--schema-file` or `--schema-stdin`. |
192
+
193
+ ---
194
+
195
+ ### Schema & XMD
196
+
197
+ XMD (xmemory Data) is the typed schema format for instances. These commands mirror the Console schema workflow (read/update/dry-run/migrations, LLM generate/enhance, and validation).
198
+
199
+ #### Command map
200
+
201
+ | User task | CLI command | Notes |
202
+ |----------|-------------|-------|
203
+ | Read live schema | **`schema get`** `[instance_id]` | Live schema for one instance. `-o` writes YAML. |
204
+ | Apply migration | **`schema update`** `[instance_id]` | `--schema-file`, optional `--migration-plan`, `--confirm-destructive`. |
205
+ | Preview migration | **`schema dry-run`** `[instance_id]` | Same flags as `schema update`; returns planned DDL without applying. |
206
+ | List migrations | **`schema migrations list`** `[instance_id]` | Newest first. `--limit`, `--before-id`, `--include-yaml`. |
207
+ | Fetch one migration | **`schema migrations get`** `<migration_id>` | Instance from `--instance-id` / `$XMEM_INSTANCE_ID`. `--include-yaml`. |
208
+ | Enhance bound schema | **`xmd enhance --from-instance`** `<description>` | Uses live schema; requires instance id. |
209
+ | Synthesize schema | **`xmd generate`** `<description>` | Cluster-scoped LLM synthesis. `-o` writes YAML. |
210
+ | Enhance from file | **`xmd enhance`** `[schema_file]` `<description>` | From a file, or `--from-instance` for bound enhance. `-o`, `--plan-output`. |
211
+ | Create instance | **`instance create`** | `--name`, `--schema-file` or `--schema-stdin`. |
212
+ | Validate schema | **`xmd validate`** / **`validate-yaml`** / **`validate-json`** | Cluster-scoped server validation. |
213
+ | Convert JSON Schema | **`xmd convert`** | JSON Schema → XMD YAML via the API (`validate_json_schema`). |
214
+
215
+ **Not exposed in CLI** (Console / suggestion-engine only today): pending schema suggestions review/apply.
216
+
217
+ #### Typical workflow
218
+
219
+ ```text
220
+ # 1. Synthesize or enhance
221
+ xmemcli xmd generate "people and their pets" -o schema.yml
222
+ xmemcli xmd enhance schema.yml "add a Pet.breed field" -o next.yml --plan-output plan.json
223
+
224
+ # 2. Validate before create or update
225
+ xmemcli xmd validate next.yml
226
+
227
+ # 3. Create instance OR migrate existing
228
+ xmemcli instance create --name demo --schema-file schema.yml
229
+ xmemcli schema dry-run INST_ID --schema-file next.yml --migration-plan plan.json
230
+ xmemcli schema update INST_ID --schema-file next.yml --migration-plan plan.json --confirm-destructive
231
+
232
+ # 4. Inspect history
233
+ xmemcli schema migrations list INST_ID
234
+ xmemcli schema migrations get MIGRATION_UUID
235
+ ```
236
+
237
+ #### Commands
238
+
239
+ | Command | Description |
240
+ |---------|-------------|
241
+ | **`schema get`** `[instance_id]` | Live XMD schema. Optional `-o` file. |
242
+ | **`schema update`** `[instance_id]` | Replace schema from `--schema-file`. Optional `--schema-type`, `--migration-plan`, `--confirm-destructive`. |
243
+ | **`schema dry-run`** `[instance_id]` | Preview migration (same schema/plan flags as update). |
244
+ | **`schema migrations list`** `[instance_id]` | Applied migrations, newest first. `--limit` (default 50), `--before-id`, `--include-yaml`. |
245
+ | **`schema migrations get`** `<migration_id>` | One record; instance from global instance flags. `--include-yaml`. |
246
+ | **`xmd generate`** `<description>` | LLM-synthesize XMD. Optional `-o`. Requires cluster resolution. |
247
+ | **`xmd enhance`** `[schema_file]` `<description>` | LLM-augment schema from file, or **`--from-instance`** for live schema. `-o`, `--plan-output`. |
248
+ | **`xmd validate`** `<schema_file>` | Validate; YAML vs JSON inferred from `.json` extension. |
249
+ | **`xmd validate-yaml`** `<schema_file>` | Force YAML validation endpoint. |
250
+ | **`xmd validate-json`** `<schema_file>` | Force JSON Schema validation endpoint. |
251
+ | **`xmd convert`** `<json_schema_file>` | JSON Schema → XMD YAML via the API (`validate_json_schema`). Optional `-o`, `--root-object`. |
252
+
253
+ Instance id for `schema *` commands: positional `[instance_id]`, else **`--instance-id`** / **`$XMEM_INSTANCE_ID`** (except `migrations get`, which takes only `migration_id`).
254
+
255
+ ---
256
+
257
+ ### Auth & meta
258
+
259
+ | Command | Description |
260
+ |---------|-------------|
261
+ | **`auth login`** | PKCE via Console `/xmemcli/<challenge>` → `.xmemrc.json`. `--no-browser`, `--timeout`, `--console-url`. |
262
+ | **`auth logout`** | Remove active `.xmemrc.json` |
263
+ | **`auth status`** | Call `/whoami`. No key → exit 0; bad key → auth error; good key → email + prefix. |
264
+ | **`version`** | CLI release version (no network) |
265
+ | **`status`** | Local health: version + whether `.xmemrc.json` exists (no network) |
266
+
267
+ **Console `/xmemcli` routing:**
268
+
269
+ - **Onboarding** → silent onboarding-key handoff to the CLI (no overlay, no button click).
270
+ - **Post-onboarding** → API Keys create modal → “Use this key in the CLI”.
271
+
272
+ ---
273
+
274
+ ### Quota (read-only)
275
+
276
+ | Command | Description |
277
+ |---------|-------------|
278
+ | **`quota`** | Usage / limit / window start for the key's cluster (derived from instance → cluster). |
279
+
280
+ - **Default:** exit `0` when quota is readable; stderr **warning** when usage is high.
281
+ - **`--fail-if-under THRESHOLD`** — exit non-zero when **remaining** quota is below that share of the limit (`0.1` or `10%`). See `xmemcli help quota`.
282
+
283
+ Quota **increases** are Console-only — see [What `xmemcli` does not do](#what-xmemcli-does-not-do).
284
+
285
+ ---
286
+
287
+ ## Help
288
+
289
+ `xmemcli` supports root `-h` / `--help` (same overview as bare `xmemcli`) and the **`help`** subcommand for nested topics.
290
+
291
+ | Invocation | What you get |
292
+ |------------|--------------|
293
+ | **`xmemcli`** | Full command overview (grouped list of every capability) |
294
+ | **`xmemcli help`** | Same as bare `xmemcli` |
295
+ | **`xmemcli help options`** | Global flags (`--api-url`, `--api-key`, `--json`, …) |
296
+ | **`xmemcli help <topic>`** | Usage, options, and subcommands for that topic |
297
+ | **`xmemcli <cmd> … -h`** / **`--help`** | Same as `help <topic>` for that command path |
298
+
299
+ **Every command in this document has help.** Examples:
300
+
301
+ ```text
302
+ xmemcli help write
303
+ xmemcli help write-status
304
+ xmemcli help read
305
+ xmemcli help org
306
+ xmemcli help org list instances
307
+ xmemcli help instance create
308
+ xmemcli help schema
309
+ xmemcli help schema get
310
+ xmemcli help schema update
311
+ xmemcli help schema dry-run
312
+ xmemcli help schema migrations
313
+ xmemcli help schema migrations list
314
+ xmemcli help schema migrations get
315
+ xmemcli help xmd
316
+ xmemcli help xmd generate
317
+ xmemcli help xmd enhance
318
+ xmemcli help xmd validate
319
+ xmemcli help xmd validate-yaml
320
+ xmemcli help xmd validate-json
321
+ xmemcli help xmd convert
322
+ xmemcli help auth login
323
+ xmemcli help quota
324
+ xmemcli help options
325
+ ```
326
+
327
+ Nested topics work at any level that exists in the parser (`help org`, `help org list`, `help org list keys`, …). Unknown topics print a short error and suggest `xmemcli` or `help options`.
328
+
329
+ ---
330
+
331
+ ## What `xmemcli` does **not** do
332
+
333
+ | Area | Use the Console instead |
334
+ |------|-------------------------|
335
+ | **Quota increases** | No `quota request-increase`. Observe with `xmemcli quota`; **raise limits in Billing / Quotas UX**. |
336
+ | **Routine API key creation** | Post-onboarding: API Keys UI (CLI opens that flow via `/xmemcli`). |
337
+ | **Billing, plans, trial paywall** | Console only |
338
+ | **Users, roles, org admin** | Console only |
339
+ | **Instance chat / trace inspection** | Console only |
340
+ | **Cluster create/delete** | CLI lists clusters; provisioning in Console |
341
+ | **`read --extraction deep`** | Server has no read-depth knob today |
342
+ | **Raw REST proxy** | Curated response fields only |
343
+ | **Instance deletion** | **Not available in the CLI** — explicitly disabled and reserved for manual human use in the Console. |
344
+
345
+ On HTTP **402** (quota exhausted), stop and ask a human to extend quota in the Console.
346
+
347
+ ---
348
+
349
+ ## Global flags & environment
350
+
351
+ These apply **before** any subcommand (`xmemcli help options`).
352
+
353
+ | Flag | Env var | Purpose |
354
+ |------|---------|---------|
355
+ | `--api-url` | `XMEM_API_URL` | API origin (default `https://api.xmemory.ai`) |
356
+ | `--api-key` | `XMEM_API_KEY` | Bearer API key |
357
+ | `--instance-id` | `XMEM_INSTANCE_ID` | Default instance for read/write and cluster derivation |
358
+ | `--rc-dir` | `XMEM_RC_DIR` | Where `auth login` writes `.xmemrc.json`; reads walk **up** toward `$HOME` |
359
+ | `--json` | — | Force one JSON document on stdout |
360
+ | `--verbose` | — | Add `trace_id` / `console_url` when present (never SQL, diff plans, or internals) |
361
+
362
+ **Credential resolution:** `--api-key` → `$XMEM_API_KEY` → nearest `.xmemrc.json` → *Not logged in — run `xmemcli auth login` first.*
363
+
364
+ **Origin resolution:** `--api-url` → `$XMEM_API_URL` → rc `api_url` → default.
365
+
366
+ **Instance resolution (read/write):** `--instance-id` → `$XMEM_INSTANCE_ID` → if exactly **one** instance is visible, auto-select with a **stderr warning** → else error.
367
+
368
+ **Output:** Pipes and non-TTY stdout → JSON. Interactive TTY → one-line summaries unless `--json`.
@@ -1,10 +1,11 @@
1
1
  [project]
2
2
  name = "xmemcli"
3
- version = "0.0.1"
4
- description = "xmemory CLI tool"
3
+ version = "0.0.3"
4
+ description = "Command-line client for the xmemory HTTP API: PKCE auth, instances, read/write, schema and XMD tools."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12,<4"
7
7
  dependencies = []
8
+ keywords = ["xmemory", "cli", "api", "memory", "llm"]
8
9
 
9
10
  [project.scripts]
10
11
  xmemcli = "xmemcli.cli:main"
@@ -4,5 +4,5 @@ requires-python = ">=3.12, <4"
4
4
 
5
5
  [[package]]
6
6
  name = "xmemcli"
7
- version = "0.0.1"
7
+ version = "0.0.3"
8
8
  source = { editable = "." }
@@ -1,3 +1,3 @@
1
1
  """Standalone xmemcli package (``xmemcli`` console script)."""
2
2
 
3
- __version__ = "0.0.1"
3
+ __version__ = "0.0.3"
@@ -37,6 +37,8 @@ _HIDDEN_COMMAND_NAMES = frozenset(
37
37
  "write_status",
38
38
  "writestatus",
39
39
  "async_write_status",
40
+ "asyncwritestatus",
41
+ "async-write-status",
40
42
  }
41
43
  )
42
44
  _RESET = "\x1b[0m"
@@ -96,7 +98,6 @@ _OVERVIEW_SECTIONS: tuple[tuple[str, tuple[tuple[str, str], ...]], ...] = (
96
98
  (
97
99
  "Instances",
98
100
  (
99
- ("instance list", "List instances visible to this credential (alias for org list instances)"),
100
101
  ("instance get", "Get a single instance by id"),
101
102
  ("instance create", "Create a new instance from an XMD/JSON schema"),
102
103
  ),
@@ -1,4 +1,4 @@
1
1
  """Release metadata for the xmemcli CLI (copied into standalone builds)."""
2
2
 
3
3
  CLI_NAME = "xmemcli"
4
- __version__ = "0.0.1"
4
+ __version__ = "0.0.3"
xmemcli-0.0.1/PKG-INFO DELETED
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: xmemcli
3
- Version: 0.0.1
4
- Summary: xmemory CLI tool
5
- Requires-Python: <4,>=3.12
6
- Description-Content-Type: text/markdown
7
-
8
- # xmemcli
9
-
10
- Standalone UV-managed CLI for the xmemory HTTP API (stdlib only). PyPI package
11
- name: **xmemcli**; console command: ``xmemcli``.
12
-
13
- This tree is generated by ``scripts/prepare_xmemcli_release.py`` from the
14
- monorepo ``cli/`` sources. Version: **0.0.1**.
15
-
16
- ## Quick check
17
-
18
- ```bash
19
- uv sync
20
- uv run xmemcli version
21
- uv run xmemcli status
22
- ```
xmemcli-0.0.1/README.md DELETED
@@ -1,15 +0,0 @@
1
- # xmemcli
2
-
3
- Standalone UV-managed CLI for the xmemory HTTP API (stdlib only). PyPI package
4
- name: **xmemcli**; console command: ``xmemcli``.
5
-
6
- This tree is generated by ``scripts/prepare_xmemcli_release.py`` from the
7
- monorepo ``cli/`` sources. Version: **0.0.1**.
8
-
9
- ## Quick check
10
-
11
- ```bash
12
- uv sync
13
- uv run xmemcli version
14
- uv run xmemcli status
15
- ```
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes