@capxul/cli 4.20.0-beta.3 → 4.20.0-beta.30

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.
Files changed (44) hide show
  1. package/README.md +1156 -21
  2. package/dist/browser/GeistVF.woff +0 -0
  3. package/dist/browser/signer.js +85954 -0
  4. package/dist/browser/signer.js.map +1 -0
  5. package/dist/entry-Cp3LiVYn.mjs +46472 -0
  6. package/dist/entry-Cp3LiVYn.mjs.map +1 -0
  7. package/dist/fast-Dvf2EM7j.mjs +57 -0
  8. package/dist/fast-Dvf2EM7j.mjs.map +1 -0
  9. package/dist/{lib-BOge5QZP.mjs → lib-5nM6ORJd.mjs} +5 -4
  10. package/dist/{lib-BOge5QZP.mjs.map → lib-5nM6ORJd.mjs.map} +1 -1
  11. package/dist/{lib-DH_xJGSE.mjs → lib-BJgR4mWJ.mjs} +6 -5
  12. package/dist/{lib-DH_xJGSE.mjs.map → lib-BJgR4mWJ.mjs.map} +1 -1
  13. package/dist/lib-BlUleR2B.mjs +3 -0
  14. package/dist/{lib-C8ENT9j6.mjs → lib-BspI667y.mjs} +7 -6
  15. package/dist/{lib-C8ENT9j6.mjs.map → lib-BspI667y.mjs.map} +1 -1
  16. package/dist/{lib-C4fpnzyy.mjs → lib-Buegx0dz.mjs} +6 -5
  17. package/dist/{lib-C4fpnzyy.mjs.map → lib-Buegx0dz.mjs.map} +1 -1
  18. package/dist/{lib-DVGoRCJN.mjs → lib-CJw8te9L.mjs} +38 -38
  19. package/dist/{lib-DVGoRCJN.mjs.map → lib-CJw8te9L.mjs.map} +1 -1
  20. package/dist/lib-C_-etuHZ.mjs +3 -0
  21. package/dist/lib-CoGPQsbr.mjs +655 -0
  22. package/dist/lib-CoGPQsbr.mjs.map +1 -0
  23. package/dist/lib-Dd_fsz7h.mjs +3 -0
  24. package/dist/lib-DnmstTkB.mjs +578 -0
  25. package/dist/lib-DnmstTkB.mjs.map +1 -0
  26. package/dist/lib-IlYdzOHo.mjs +3 -0
  27. package/dist/main.mjs +22 -51062
  28. package/dist/main.mjs.map +1 -1
  29. package/dist/organizations-Dkb73lVO.mjs +37607 -0
  30. package/dist/organizations-Dkb73lVO.mjs.map +1 -0
  31. package/dist/permission-approvals-C3cUSQeT.mjs +139 -0
  32. package/dist/permission-approvals-C3cUSQeT.mjs.map +1 -0
  33. package/dist/record-U7Yu4KQP.mjs +1295 -0
  34. package/dist/record-U7Yu4KQP.mjs.map +1 -0
  35. package/dist/{secp256k1-Cc9JhcTQ.mjs → secp256k1-D8L212-Z.mjs} +5 -298
  36. package/dist/secp256k1-D8L212-Z.mjs.map +1 -0
  37. package/dist/sha2-CR2DnMEk.mjs +298 -0
  38. package/dist/sha2-CR2DnMEk.mjs.map +1 -0
  39. package/dist/utils-DmKXBQjM.mjs +130 -0
  40. package/dist/utils-DmKXBQjM.mjs.map +1 -0
  41. package/dist/where-view-DuGbrSLp.mjs +1420 -0
  42. package/dist/where-view-DuGbrSLp.mjs.map +1 -0
  43. package/package.json +18 -10
  44. package/dist/secp256k1-Cc9JhcTQ.mjs.map +0 -1
package/README.md CHANGED
@@ -1,46 +1,841 @@
1
1
  # Capxul CLI
2
2
 
3
- The CLI provides local diagnostics, an online backend check, and one global
4
- collection preference. It requires Node 24 or later on macOS or Linux.
3
+ The CLI provides email OTP login, persistent first-party sessions, a handover to
4
+ the web app for Account setup, personal and Organization contacts, a bundled
5
+ Openfort wallet page for Organization setup,
6
+ backend profile and account reads, diagnostics, and one global collection
7
+ preference. It requires Node 24 or later on macOS or Linux.
5
8
 
6
9
  ```sh
7
10
  capxul --help
8
11
  capxul --version
9
12
  capxul --completions bash
10
13
  capxul doctor --json
11
- capxul telemetry status --json
12
- capxul telemetry disable --json
13
- capxul telemetry enable --json
14
+ capxul config telemetry status --json
15
+ capxul config telemetry off --json
16
+ capxul config telemetry on --json
14
17
  capxul doctor --online --timeout-ms 30000 --json
15
18
  ```
16
19
 
17
20
  Help and version do not require application credentials or a working backend.
21
+ With no arguments, `capxul` shows the same generated help as `capxul --help`.
18
22
  They use the same observation policy as ordinary commands. Shell completion
19
23
  machinery and collection controls send no observation records.
20
24
  `doctor` checks local configuration unless `--online` is present. An online
21
25
  check uses the public Capxul SDK and verifies the backend response nonce.
22
26
  It does not authenticate a person or submit a transaction.
23
27
 
28
+ ## Agent plugin
29
+
30
+ The Claude Code plugin lives in its own private repository,
31
+ [`Xelmar-tech/capxul-plugin`](https://github.com/Xelmar-tech/capxul-plugin): one
32
+ `capxul` skill that makes an agent act as the person's Capxul through this CLI,
33
+ with journeys as references, local memory under `~/.capxul/`, and the
34
+ paste-a-prompt. Install it with:
35
+
36
+ ```sh
37
+ claude plugin marketplace add Xelmar-tech/capxul-plugin
38
+ claude plugin install capxul@capxul
39
+ ```
40
+
41
+ That repository's CI checks every command the skill names against
42
+ `capxul schema --json` from `@capxul/cli@latest`, so a renamed or removed command
43
+ fails there.
44
+
45
+ ## Command schema
46
+
47
+ ```sh
48
+ capxul schema
49
+ capxul schema payment send
50
+ capxul schema org payroll
51
+ ```
52
+
53
+ `capxul schema` prints every command as JSON: its name, what it does and whether
54
+ it moves money, with the global flags and what each exit code means.
55
+ `capxul schema <command…>` prints one command: usage, arguments, flags, global
56
+ flags and examples, read from the command's own definition (Effect's help
57
+ document, so `--help` and the schema always agree), plus `movesMoney`, `output`
58
+ (what `data` is) and `errors` (the codes it can answer with). A group lists its
59
+ commands. Agents look commands up here instead of copying flags.
60
+
61
+ ## Home screen
62
+
63
+ ```sh
64
+ capxul
65
+ capxul --json
66
+ capxul --org acme
67
+ ```
68
+
69
+ Bare `capxul` is the home screen. It prints where you are at once, from this
70
+ machine: who you are, who you act as and the Safe. Then one backend read
71
+ (`accounts.summaries.home`) returns your balances (or the Organization
72
+ treasury) and what needs you, each with the command that resolves it (requests
73
+ to pay, payroll runs to approve, payments to retry), and it shows a few
74
+ commands to try. A backend without that read gets the separate reads instead.
75
+ A read that fails shows its section as unavailable, never as empty. Signed out,
76
+ it prints `Not signed in · capxul auth login` without a network call. `--json`
77
+ returns the same as data: `where`, `signedIn`, `balances` (the asset
78
+ positions), `needsYou` (each with `next.argv`) and `try`. `capxul --help` is
79
+ the command list.
80
+
81
+ ## Where you are
82
+
83
+ ```sh
84
+ capxul whoami # local, under 0.3 s
85
+ capxul whoami --json # the same, with where each value came from
86
+ capxul auth login # sign in with an email code
87
+ capxul auth verify 123456 # finish a sign-in that auth login started (scripts and agents)
88
+ capxul auth switch ada@example.com
89
+ capxul auth logout
90
+ capxul use org acme # act as one of your Organizations
91
+ capxul use personal # act as yourself
92
+ capxul use env devnet # use this environment from now on
93
+ ```
94
+
95
+ `whoami` prints the signed-in person, who you act as, the Safe, and the
96
+ environment with its network. It reads only this machine's files and makes no
97
+ network call. With `--json`, each value carries its `source`: `flag`, `env`
98
+ (a variable), `saved`, or `default`.
99
+
100
+ Every human command prints one header line on stderr when someone is signed in:
101
+ `▸ <actor> · <environment> · <network>`, for example
102
+ `▸ Acme Ltd · staging · Base Sepolia`. The environment name is highlighted on a
103
+ terminal. Production is the normal case and will show no environment label.
104
+ Red is only used for errors. JSON output has no header.
105
+
106
+ The environment comes from `--env <name>`, then `CAPXUL_ENV`, then
107
+ `CAPXUL_BOOTSTRAP_URL`, then the environment `use env` saved, then staging. The
108
+ names are `staging` and `devnet`; production is not available in this CLI yet.
109
+ The devnet uses its fixed test key, so it needs no `CAPXUL_PUBLISHABLE_KEY`.
110
+
111
+ `use org <handle>` finds the Organization among those you belong to and saves
112
+ it for this environment. It grants no authority; the backend checks every
113
+ command. `org` commands act as the saved Organization unless `--org` names
114
+ another. `use personal` forgets it. Signing in as a different person forgets the
115
+ previous person's Organization and Safe.
116
+
117
+ Scripts and agents sign in with two commands: `auth login --email EMAIL` sends
118
+ the code and returns `next.argv` for `auth verify <code>`, which finishes it.
119
+ `--email` is not needed on later commands.
120
+
121
+ ## Guided terminal input
122
+
123
+ In a human terminal, these commands collect missing required fields one step at
124
+ a time:
125
+
126
+ ```sh
127
+ capxul org permission change
128
+ capxul org member invite
129
+ capxul payment get
130
+ capxul document get
131
+ ```
132
+
133
+ Supplied valid values remain in the command. Preview and confirmation still
134
+ apply to writes. `--wizard` provides an explicit entry to the same native input
135
+ flow. Ctrl+C or Ctrl+D cancels with exit 130. Bare groups show help. JSON, CI,
136
+ and noninteractive runs require their declared input and do not prompt.
137
+
138
+ ## Waiting output
139
+
140
+ Pending setup and observation commands show a waiting message. Human terminals
141
+ also show an activity indicator. The indicator stops before a prompt or final
142
+ result. Noninteractive human output uses text without animation.
143
+
144
+ Payment, Payroll, Permission, Organization, and Invitation waits print observed
145
+ state changes on stderr. JSON mode uses declared progress objects on stderr and
146
+ one final version 1 result on stdout. Account setup reports public signer states.
147
+ Activity shows that the CLI is waiting. It does not prove settlement or a healthy
148
+ connection. A deadline stops observation; it does not cancel a submitted operation.
149
+
150
+ ## Sending money through the approval page
151
+
152
+ ```sh
153
+ capxul payment send rex@example.com 50
154
+ capxul payment send @rex 12.5 --asset USDT
155
+ capxul payment send 0x91f2…aa10 40
156
+ capxul payment send rex@example.com 50 --json
157
+ capxul payment send rex@example.com 50 --org acme [--from BUDGET]
158
+ capxul payment send --input payment.json [--org acme] [--request-key K]
159
+ capxul payment wait PAYMENT_ID_OR_APPROVAL_ID [--org acme] [--timeout-seconds N] [--json]
160
+ ```
161
+
162
+ `send` prepares the payment and opens its approval page. The page is the one
163
+ and only confirmation: there is no `[y/N]` and no `--confirm`. Nothing moves
164
+ until a person approves it there with their own key; the CLI never signs.
165
+
166
+ `<to>` is an email, a @handle or an 0x address (an address you type is your
167
+ own choice, and the page shows it again). `<amount>` is in `--asset`, a symbol
168
+ the payer holds (USDC by default). With `--org`, the payment spends from a
169
+ Budget you hold in that Organization: the one Budget for the asset, or the one
170
+ `--from` names (by its name or ID). `--input FILE|-` takes the SDK's payment JSON instead, with
171
+ documents; an Organization's adds its `permissionId`.
172
+
173
+ A person sees what they are approving (who pays and what is left, who receives
174
+ it, the amount, and that there is no fee: every operation is sponsored). The
175
+ CLI opens the page on a terminal, prints the link, and follows it: `✓ Signed`
176
+ when the person approves, `✓ Confirmed` when the payment settles, then the paid
177
+ amount, the transaction and the receipt command. A rejection on the page ends
178
+ `✗ Not sent` with exit 130; an approval that lapses sends nothing (exit 2).
179
+ Ctrl-C stops following; the link still works, and `payment wait` follows it.
180
+
181
+ With `--json`, `send` returns at once:
182
+
183
+ ```json
184
+ {
185
+ "status": "awaiting_approval",
186
+ "approvalId": "approval_01JA…",
187
+ "approvalUrl": "https://app.staging.capxul.com/approve/approval_01JA…",
188
+ "paymentIds": ["payment_01JB…"],
189
+ "expiresAt": 1791359237000,
190
+ "next": { "argv": ["capxul", "payment", "wait", "approval_01JA…", "--json"] }
191
+ }
192
+ ```
193
+
194
+ An agent gives the person the link and runs `next.argv`. `payment wait
195
+ APPROVAL_ID` follows the approval: once it is approved it sends it (unless the
196
+ page already did; only one send can claim it) and waits for the payment to
197
+ settle. Its result is the SDK's `{ approval, payments }`. An Organization
198
+ payment's wait carries `--org`. Without `--timeout-seconds`, `payment wait` follows
199
+ until the approval lapses and the payment settles, as `send` does; with it, the wait
200
+ stops after that many seconds (1 to 3600) with exit 5 and the same command to run again.
201
+
202
+ ## Personal Payments
203
+
204
+ ```sh
205
+ capxul payment retry PAYMENT_ID --json
206
+ capxul payment send rex@capxul.com 50 --release-at 2026-11-01 --json
207
+ capxul payment cancel PAYMENT_ID --json
208
+ capxul payment redirect PAYMENT_ID sam@acme.co --json
209
+ capxul payment list --json
210
+ capxul payment get PAYMENT_ID --json
211
+ capxul payment wait PAYMENT_ID --json
212
+ capxul payment wait PAYMENT_ID --timeout-seconds 120 --json
213
+ ```
214
+
215
+ These commands use the current authenticated session. Add `--email EMAIL` to
216
+ select a saved session. In a terminal, omit the required Payment ID to enter it.
217
+ `wait` follows a Payment until it ends unless `--timeout-seconds` bounds it.
218
+ `get` refuses when the Payment is absent or unavailable to the session. Human
219
+ output shows the full ID, status, amount, counterparty and available receipt.
220
+
221
+ `wait` observes the exact Payment until it reaches a terminal state or needs an
222
+ action. A failed Payment can be a completed observation. The timeout accepts
223
+ 1–3600 seconds and includes session restoration. A timeout or unavailable read
224
+ prints exact get/wait commands. Waiting never resubmits a Payment.
225
+
226
+ `send --release-at DATE` holds the payment in escrow until that date (midnight
227
+ UTC), from your own Safe or from an Organization Budget. `cancel` returns a held
228
+ payment to whoever funded it; `redirect` sends it to someone else. For an
229
+ Organization's held payment only an Owner may cancel or redirect it; anyone else,
230
+ a Budget member included, is refused before anything is prepared. Both hand over
231
+ to the approval page as `send` does, then read the Payment until the chain shows
232
+ the step (`payment wait <approval id>` reports them once sent). A cancelled
233
+ payment keeps the amount it was for. A cancel or redirect of a payment that is
234
+ no longer held is refused (`WRONG_STATE`, exit 2) with `Payment <id> is already
235
+ cancelled.` or the state it is in. A held payment that was never signed reads
236
+ `failed`, not `scheduled`.
237
+
238
+ Retry prepares the retry of the exact Payment and hands over to the approval
239
+ page, exactly as `payment send` does: the page is the one and only
240
+ confirmation, and `--json` returns `awaiting_approval`, the link and
241
+ `next.argv` for `payment wait <approval id>`. It addresses the existing Payment
242
+ command and never creates a replacement send.
243
+
244
+ ## Activity
245
+
246
+ ```sh
247
+ capxul activity list --limit 25 --json
248
+ capxul activity get --kind payment --id PAYMENT_ID --json
249
+ capxul activity get --kind movement --id MOVEMENT_ID --json
250
+ capxul activity summary --from 1790553600000 --to 1790639999999 --json
251
+ capxul activity annotate --input annotation.json --confirm --json
252
+ ```
253
+
254
+ Add explicit `--org ORGANIZATION_ID` for Organization scope. The saved
255
+ Organization read default does not select this scope. List supports kind,
256
+ direction, status and inclusive epoch-millisecond bounds. Reuse a cursor with
257
+ the same filters and actor. An unavailable indexer produces a visible incomplete
258
+ activity warning. Movement rows remain Movements.
259
+
260
+ Summary keeps exact per-asset raw-unit totals. Get returns exact detail and
261
+ refuses a missing or unavailable reference. Annotation accepts only `reference`,
262
+ `accountingCategory` and `memo`; it cannot alter settlement or documents. Human
263
+ writes require preview and confirmation. Scripted writes require `--confirm`.
264
+ In a terminal, omit required fields for guided flags and annotation input.
265
+
266
+ ## Issued requests and received Inbox
267
+
268
+ ```sh
269
+ capxul request list
270
+ capxul request issue --input invoice.json --confirm
271
+ capxul request get REQUEST_ID
272
+ capxul request cancel REQUEST_ID --confirm
273
+ capxul inbox list
274
+ capxul inbox get REQUEST_ID
275
+ capxul inbox pay REQUEST_ID
276
+ capxul inbox decline REQUEST_ID --confirm
277
+ capxul request list --org ORGANIZATION_ID
278
+ capxul request issue --org ORGANIZATION_ID --input invoice.json --confirm
279
+ capxul request get --org ORGANIZATION_ID REQUEST_ID
280
+ capxul request cancel --org ORGANIZATION_ID REQUEST_ID --confirm
281
+ capxul inbox list --org ORGANIZATION_ID
282
+ capxul inbox get --org ORGANIZATION_ID REQUEST_ID
283
+ capxul inbox pay --org ORGANIZATION_ID REQUEST_ID --permission-id PERMISSION_ID
284
+ capxul inbox decline --org ORGANIZATION_ID REQUEST_ID --confirm
285
+ ```
286
+
287
+ `request` reads the issued Invoice and payment requests of whoever you act as:
288
+ you, or the Organization `--org`, `CAPXUL_ORG` or `use org` names. `inbox` reads
289
+ payment requests addressed to that actor. Add `--email EMAIL` to select a saved
290
+ session. No signer is required for these reads.
291
+
292
+ For human reads, start with `capxul request --help` or `capxul inbox --help`.
293
+ Run `request list` for requests you issued. Run `inbox list` for requests you
294
+ received. Copy the full request ID from the list into the matching `get` command.
295
+ In a terminal, omit required fields to start guided input. Ctrl+C or Ctrl+D
296
+ cancels with exit 130. The wizard can ask about optional email selection before
297
+ required fields. Provide `--email EMAIL` when you need one saved session.
298
+
299
+ For agent reads, supply all required flags and add `--json`. Capture stdout,
300
+ stderr, and the process exit code separately. A refusal is still a version 1
301
+ result on stdout. Inspect `outcome` and `error.code`; do not infer success from
302
+ valid JSON. Missing required input exits 2. A missing authenticated session exits 3. Noninteractive human refusals use stderr. These runs do not prompt.
303
+
304
+ Agents pass `--org` on every Organization command, so a saved choice never
305
+ decides whose money a command touches. `--org` takes a handle or an
306
+ Organization ID.
307
+
308
+ Local help, refusal, and cancellation checks do not prove authenticated
309
+ request reads, document output, issuance, or payment; those are separate
310
+ journey checks.
311
+
312
+ Human output shows request ID, reference, amount, status, counterparty
313
+ reference, and document references. An unpaid Invoice can have a document
314
+ before any Payment exists. The document guidance preserves the selected
315
+ session. Run that explicit command to save a PDF. Request and Inbox reads do
316
+ not render or download PDFs. JSON output preserves scope, direction, and the
317
+ SDK item or list. Unavailable reads remain failures, not empty lists.
318
+
319
+ Cancel changes an issued request. Decline changes a received request. Both
320
+ commands read the exact request in the selected scope before the write.
321
+ Terminal writes show a preview and ask for confirmation. Scripted writes
322
+ require `--confirm` before session restoration. A lost write reply gives an
323
+ exact readback command in the same scope and session. It never repeats the
324
+ write. These commands start no signer and move no funds.
325
+
326
+ Issue accepts a basic payment request or an Invoice request JSON object from
327
+ `--input FILE` or `--input -`. Both require `payer` and an exact positive
328
+ `amount`. A basic request requires an explicit `reference` and accepts an
329
+ optional private `memo`. An Invoice request also supplies `invoice`.
330
+ Issue saves no file. Its human output names the `document render` command for
331
+ each document, and its JSON result is `{ scope, direction, item }`: the issued
332
+ request with its document references, with no document output.
333
+ Human and JSON output include `checkoutUrl` for an Invoice or Memo request
334
+ instruction with a link token. Invoice requests keep `/checkout/invoices/`.
335
+ Basic requests use `/checkout/requests/`. Movement documents do not create
336
+ request links.
337
+ The PDF includes the checkout link from the authorized backend render context.
338
+ For a custom deployment, set `CAPXUL_CHECKOUT_FRONTEND_ORIGIN` in both the CLI
339
+ and backend environments. Use the same frontend origin for both.
340
+ Offer create, get, list, revise, and deactivate output also include `checkoutUrl`.
341
+ The checkout page reads current terms and status when the link opens.
342
+ Save a PDF with the printed `document render` command. Do not issue the request
343
+ again to get a PDF.
344
+
345
+ ```json
346
+ {
347
+ "payer": { "kind": "email", "email": "bob@example.com" },
348
+ "amount": { "asset": "<admitted asset ID>", "value": "9" },
349
+ "invoice": {
350
+ "kind": "invoice",
351
+ "invoiceNumber": "INV-002",
352
+ "payerRef": "Bob",
353
+ "payeeRef": "Alice",
354
+ "dueAt": 1900000000000,
355
+ "note": "Thank you",
356
+ "discountMinor": "1000000",
357
+ "lineItems": [{ "description": "Consulting", "quantity": 1, "unitMinor": "10000000" }]
358
+ }
359
+ }
360
+ ```
361
+
362
+ For a basic request, omit `invoice`:
363
+
364
+ ```json
365
+ {
366
+ "payer": { "kind": "email", "email": "bob@example.com" },
367
+ "amount": { "asset": "<admitted asset ID>", "value": "9" },
368
+ "reference": "SESSION-001",
369
+ "memo": "Counselling session"
370
+ }
371
+ ```
372
+
373
+ Supply your Invoice number. The request reference defaults to that number;
374
+ optional `reference` changes the request reference only. `dueAt` uses epoch
375
+ milliseconds, as the shared Invoice document and frontend do. Set it to zero
376
+ for no due date. Optional `expiresAt` also uses epoch milliseconds. `discountMinor` and
377
+ `unitMinor` use the asset's exact minor units. The example is 10 USDC less
378
+ 1 USDC for a six-decimal USDC asset. The backend checks the Invoice total,
379
+ registered payer, and issuer authority before creation. Optional `memo` is a
380
+ request memo; `invoice.note` is the document note. Unknown fields refuse.
381
+
382
+ Earlier CLI guidance incorrectly named Unix seconds for `dueAt`. Convert those
383
+ values to milliseconds for new drafts. Rendering does not change the dates in
384
+ an issued document. Inspect an incorrect Invoice before cancelling it and
385
+ issuing a corrected request.
386
+
387
+ A lost issuance reply provides issued-list readback in the same scope and
388
+ session. Issuance has no automatic resend.
389
+
390
+ Inbox pay reads and confirms exact backend-owned request terms. It uses the existing
391
+ CLI signer and the SDK fulfillment API. Organization payment requires the
392
+ selected Permission; the backend checks Budget and spending authority. The
393
+ command publishes prepared Payment IDs before signing. A submitted Payment
394
+ is not a settled Payment. Use the printed get/wait commands to inspect its state.
395
+
396
+ A lost reply or timeout gives exact readback in the same session and scope.
397
+ Pay refuses an already prepared Invoice unless you explicitly use `--resume`
398
+ after readback. Resumption must retain its linked Payment ID and original
399
+ Invoice terms. It does not create another request or Payment. Use
400
+ `--timeout-seconds N` to change the bounded signing wait (default 120).
401
+ An Invoice retains its issued instruction. A generic request uses a deterministic
402
+ Memo instruction. Reading terms creates no Payment or document. Fulfillment
403
+ checks those terms again and stores the Memo with the original request birth.
404
+
405
+ ## Payment documents
406
+
407
+ ```sh
408
+ capxul document get --document-hash H --content-hash C --json
409
+ capxul document verify --document-hash H --content-hash C --json
410
+ capxul document render --document-hash H --content-hash C
411
+ capxul document render --document-hash H --content-hash C --output-dir ./documents --json
412
+ capxul document export --document-hash H --content-hash C --out original.bin
413
+ ```
414
+
415
+ Each command uses the current authenticated session. Add `--email EMAIL` to
416
+ select a saved session. In a terminal, omit required fields to enter them.
417
+ `get` returns document metadata and the `render` command for it; it writes no
418
+ file and does not print source bytes.
419
+ `verify` reports `ok: false` when verification fails. `render` saves a PDF and its
420
+ self-contained HTML source in the `documents` directory next to CLI settings.
421
+ Use `--output-dir` to change this directory. Human and JSON output contain
422
+ file metadata. Each render uses a new private directory and preserves earlier
423
+ files. `export` writes the original bytes to a new file.
424
+ It refuses an existing output file.
425
+
426
+ Only `document render` and `document export` write files. Reads name each
427
+ document with the `document render` command that saves it: Payment `get`, `wait`
428
+ and `list`, Activity detail, Payroll `get` and `wait`. Writes save nothing either.
429
+ Payment `send` and `retry`, Payroll `run` and Inbox `pay` end with
430
+ `Save the receipt: capxul document render …` once the receipt exists, and
431
+ `request issue` prints that command for each document it issued. No write
432
+ result carries document output. A document that is still pending is named by
433
+ `payment get`.
434
+
435
+ ## Contact commands
436
+
437
+ ```sh
438
+ capxul contact list [--include-hidden]
439
+ capxul contact get PARTY_ID
440
+ capxul contact add --input FILE|- [--confirm]
441
+ capxul contact label PARTY_ID --label TEXT [--confirm]
442
+ capxul contact hide PARTY_ID [--confirm]
443
+ capxul contact unhide PARTY_ID [--confirm]
444
+ capxul contact list --org acme
445
+ ```
446
+
447
+ Contacts belong to whoever you act as: your Account's address book, or the
448
+ Organization `--org`, `CAPXUL_ORG` or `use org` names. `list` omits hidden entries unless
449
+ `--include-hidden` is present. `get`, `label`, `hide`, and `unhide` address one
450
+ stable Party by its ID.
451
+
452
+ `add --input` reads the existing `AddressBookAddInput` JSON shape. For example:
453
+
454
+ ```json
455
+ {
456
+ "ref": { "kind": "email", "email": "supplier@example.test" },
457
+ "label": "New Supplier"
458
+ }
459
+ ```
460
+
461
+ Use `--input -` to read the same object from stdin. An interactive `add` can
462
+ collect the reference kind, value, and optional label instead. Interactive
463
+ writes show the actor and exact contact change, then ask a default-no question.
464
+ JSON, CI, and other noninteractive writes require `--confirm` before the CLI
465
+ creates a client. Contact writes do not start a browser signer.
466
+
467
+ Success data is the SDK value without a CLI wrapper: `list` returns
468
+ `AddressBookEntry[]`, `get` returns `AddressBookEntry | null`, and each mutation
469
+ returns `AddressBookEntry`. Human `get` prints `No contact found` for null and
470
+ exits successfully. Entries retain their stable PartyId, exact reference,
471
+ relationships, hidden state, and last activity time.
472
+
473
+ ## Personal Account reads
474
+
475
+ ```bash
476
+ capxul account show --email person@example.com
477
+ capxul balance --json
478
+ capxul address --wizard
479
+ ```
480
+
481
+ These commands reuse your verified current session unless you provide an email.
482
+ They do not start setup or open a signer. `account show` shows lifecycle and
483
+ transaction readiness; a failed lifecycle exposes its stage and error code.
484
+ `balance` and `address` act for whoever you act as: your Account, or the
485
+ Organization's treasury with `--org`. Balance shows exact asset quantities and
486
+ available fiat valuations. An unavailable valuation or failed read is not zero.
487
+ `address` uses the SDK's address and network.
488
+
489
+ Account setup finishes in the Capxul web app, not in the CLI: it creates your
490
+ wallet, which needs you in a browser, and the CLI never opens one. `account retry`
491
+ reads your Account; when it is not ready, it prints the web app link. Run it again
492
+ to check: it returns the same handover until the Account is ready.
493
+
494
+ ## Organization commands
495
+
496
+ ```sh
497
+ capxul org list --json
498
+ capxul org show --org acme --json
499
+ capxul org show --json
500
+ capxul org me --json
501
+ capxul org member list --json
502
+ capxul org member get ACCOUNT_ID --json
503
+ capxul org wait --timeout-seconds 120 --json
504
+ capxul org create --name NAME --handle HANDLE --country CC [--bio TEXT] [--size TEXT] [--confirm]
505
+ capxul org retry --org ORGANIZATION_ID [--confirm]
506
+ ```
507
+
508
+ These commands accept `--email`. Without it, they restore the protected current
509
+ session. `org` commands act as the Organization `--org` names (a handle or an
510
+ ID), then `CAPXUL_ORG`, then the one `use org` saved. Two different `--org`
511
+ values are refused.
512
+
513
+ A read without --org uses the Organization `use org` saved, then this machine's
514
+ recovery ID, then the one unfinished setup returned by the backend. org list
515
+ includes unfinished founder setups. This works from a clean authenticated home.
516
+ Interactive status/wait offers a choice when several unfinished setups exist.
517
+ Scripted and JSON reads require an exact --org in that case. A ready
518
+ Organization must still appear in current access.
519
+
520
+ Human output shows Organization identity and setup, with a separate unfinished
521
+ setup section and explicit empty results. Members without an Account ID remain
522
+ visible. `org me` shows backend capabilities and exact per-payment Budget caps;
523
+ these caps are not available balances. `--json` keeps the structured SDK data.
524
+
525
+ Member lookup uses an exact AccountId. In a human terminal, omit the ID to
526
+ select an attached Account from the authorized member list. Members without an
527
+ Account ID cannot be selected. Scripted and JSON lookup requires the ID. Reads do not sign or change
528
+ setup state.
529
+
530
+ org wait opens one exact setup subscription. It continues when needsAttention
531
+ has a scheduled next check. It stops at ready, failed, awaitingAuthorization,
532
+ or attention without a next check. It does not request a check or poll. The
533
+ timeout accepts 1 to 3600 seconds and defaults to 120. A deadline returns
534
+ CLI_DEADLINE at exit 5; Ctrl-C returns CANCELLED at exit 130.
535
+
536
+ ## Organization Payment reads
537
+
538
+ ```sh
539
+ capxul payment list --org O [--json]
540
+ capxul payment get P --org O [--json]
541
+ capxul payment wait P --org O [--timeout-seconds N] [--json]
542
+ ```
543
+
544
+ With `--org`, `CAPXUL_ORG` or `use org`, these commands read the Organization's
545
+ Payments; without one they read yours. The backend checks current Organization participation and returns
546
+ only that Organization's outgoing, incoming, and self Payments. Get refuses
547
+ a missing or mismatched Payment ID. Reads do not need a signer.
548
+
549
+ Wait observes the exact Organization and Payment through the SDK subscription.
550
+ It stops on a terminal state, required action, or required retry. The timeout
551
+ accepts 1 to 3600 seconds and defaults to 120. It covers session restoration
552
+ and observation. Deadline exit 5 and interruption exit 130 retain read/wait
553
+ instructions with both Organization and Payment IDs.
554
+
555
+ ## Organization Payment retry
556
+
557
+ ```sh
558
+ capxul payment retry P --org O --json
559
+ ```
560
+
561
+ Retry addresses the original command and every Payment in that command. It
562
+ creates no replacement send or request key. The Organization's retry is
563
+ prepared for your own key and handed over to the approval page; the page
564
+ shows the whole cohort. `--json` returns the link and `next.argv` for
565
+ `payment wait <approval id> --org O`, which follows every Payment to its end.
566
+
567
+ ## Permissions
568
+
569
+ ```sh
570
+ capxul org permission list [--org O] [--json]
571
+ capxul org permission get B [--org O] [--json]
572
+ capxul org permission create --org O --input budget.json --request-key K [--wait] [--json]
573
+ capxul org permission change B --org O --input budget.json --request-key K [--wait] [--json]
574
+ ```
575
+
576
+ These commands use `--org`, then `CAPXUL_ORG`, then the Organization `use org` saved.
577
+ A human terminal can select an accessible Organization when neither exists.
578
+ Each read checks current Organization access. `get` requires an exact Permission
579
+ ID and refuses a missing or mismatched result. Reads do not need a signer.
580
+
581
+ Human output shows Permission and assignment IDs, revisions, and states.
582
+ Budget output labels the exact per-payment cap or no cap. It does not show a
583
+ remaining balance. JSON preserves the public SDK result.
584
+
585
+ Every Budget write supplies the complete policy:
586
+
587
+ ```json
588
+ {
589
+ "type": "budget",
590
+ "asset": "A",
591
+ "limit": { "asset": "A", "value": "500" },
592
+ "scope": {
593
+ "recipients": { "type": "allowlist", "accounts": ["account_alice"] },
594
+ "actions": ["pay"]
595
+ },
596
+ "refill": "monthly"
597
+ }
598
+ ```
599
+
600
+ Use an exact admitted AssetId for `A`. The cap must be positive and finite.
601
+ `refill` is `monthly`, which refills the cap every 30 days (a fixed period from
602
+ the block that sets it, not a calendar month), or `none`. A create without
603
+ `refill` means `none`. A change without `refill` keeps the Budget's current
604
+ refill; write `"refill": "none"` to turn a refill off.
605
+ Recipients are `anyone` or 1 to 32 unique Account IDs. Actions are `pay`,
606
+ `commitments`, or both. `pay` covers single and batch Payments. Missing scope,
607
+ duplicate recipients/actions, unknown fields, and an asset mismatch refuse.
608
+ A Budget change keeps its asset. Management input is `{"type":"managePeople"}`.
609
+ Use `--input -` for stdin. Input is limited to 64 KiB.
610
+
611
+ A human terminal can guide policy input. Change prefills the exact active
612
+ revision's complete stored policy. Every Permission write (`create`, `change`,
613
+ `assign`, `revoke`, `replace`) goes through the approval page, as `payment
614
+ send` does: the preview shows all before/after rights and any allowance reset,
615
+ then the CLI prepares the command, records the verified prepared IDs, compares
616
+ the frozen policy with the preview, and opens the approval. If the policy
617
+ changed, nothing opens and the prepared command is closed. A person sees
618
+ `✓ Prepared`, `… Approve in your browser` and the link; the page is the one and
619
+ only confirmation, and the CLI follows it to `✓ Signed`. A rejection on the
620
+ page is `cancelled` (exit 130). With `--json` the command returns at once with
621
+ `status: "awaiting_approval"`, `approvalUrl` and `next.argv` for
622
+ `payment wait <approval id> --org O`. A missing human key is generated and
623
+ printed before the first write. Scripted runs require `--request-key`.
624
+
625
+ Success means sent and pending application. It does not prove active rights.
626
+ Add `--wait` to follow it through, as `org permission command wait` does: after
627
+ you approve it, the CLI follows the command until it is applied (`✓ Confirmed`),
628
+ failed or needs action. The result then also holds `command`, the command's view
629
+ (`status` is `applied`, `failed` or `actionable`), and exits 0 in each case;
630
+ read `status`. `--json --wait` writes the approval link to stderr as one
631
+ `approval.awaiting` event and returns once it is followed through.
632
+ `--timeout-seconds` bounds how long the CLI follows it (default: until the
633
+ approval lapses). A follow that runs out of time fails with exit 5 and names the
634
+ wait command. The same write run again with a request key whose command was
635
+ already sent opens no approval and shows no link: it reads the command and
636
+ prints `Already applied: …` (or where it stands), with the command's view in
637
+ `command`. After an interruption or uncertain result, retain the original
638
+ input, Organization ID, key, command ID, and execution ID. The key alone cannot
639
+ restore wizard/stdin input.
640
+
641
+ `org permission replace --org O --request-key K` replaces the current
642
+ Roles module and carries its active Permissions, assignments, and admitted
643
+ Invitation rights. Human mode guides missing scope and shows the full frozen
644
+ before/after snapshot, then hands over to the approval page. Machine mode
645
+ requires scope and key. A changed snapshot opens no approval. Unfinished Invitation configuration must complete or cancel first.
646
+ Submission remains pending application. After an uncertain result, follow the
647
+ exact command with `org permission command get` or `org permission command wait`
648
+ and the request key (not listed in the help); the command does not promise
649
+ unconditional replacement replay.
650
+
651
+ ## Payroll runs, rosters, and reads
652
+
653
+ ```sh
654
+ capxul org payroll groups list --org O [--json]
655
+ capxul org payroll groups save --org O --input group.json --confirm [--json]
656
+ capxul org payroll groups remove G --org O --confirm [--json]
657
+ capxul org payroll terms --org O [--json]
658
+ capxul org payroll list --org O [--json]
659
+ capxul org payroll run --org O --input run.json --request-key K [--json]
660
+ capxul org payroll run --org O --resume K [--json]
661
+ capxul org payroll get --org O R [--json]
662
+ capxul org payroll wait --org O R --timeout-seconds 120 [--json]
663
+ ```
664
+
665
+ Group input contains `name`, `tone`, and `members`. Each member supplies a
666
+ canonical `partyId`, draft `amount` text, and `currency`. An optional `id`
667
+ updates that exact group. These commands do not sign or transfer money.
668
+ Group amounts stay unchanged, including unfinished draft text. They do not
669
+ supply payout quantities or currency conversion. A lost create response must
670
+ be reconciled with the same scoped group list before another create.
671
+
672
+ Terms retain raw rates, decimals, units, and effective dates. Run listing
673
+ retains the backend `settledThisMonth` aggregate. The CLI does not sum a partial
674
+ run page or compute earned pay.
675
+
676
+ Run input contains `permissionId`, `asset`, `period`, and ordered `items`.
677
+ Each item supplies a recipient Ref, asserted `partyId`, settlement `amount`,
678
+ raw-unit `gross` and `net`, and signed `adjustments`. Net must equal the exact
679
+ settlement quantity and gross plus adjustments. Keep Organization, actor, signer,
680
+ and request-key routing outside the JSON. `--input -` reads bounded stdin.
681
+ The current Payroll producer accepts email and Party Refs. Other Ref kinds
682
+ refuse before client work.
683
+
684
+ In a human terminal, `capxul org payroll run` guides the current Organization,
685
+ Budget, settlement asset, date, roster or known Parties, and actual payout
686
+ quantities. Roster amounts and terms are reference data. The complete preview
687
+ shows each recipient and Safe, quantity, raw units, and adjustment. The run
688
+ is then prepared and handed over to the approval page, the one and only
689
+ confirmation. Machine runs require exact scope, input and key; `--json`
690
+ returns the approval link and `next.argv` for `payment wait <approval id> --org O`.
691
+
692
+ The command saves the exact input in protected storage under the verified actor,
693
+ Organization, and key before execution. `--resume K` restores that snapshot.
694
+ It requires the same explicit Organization and cannot combine fresh input or
695
+ another key. Payroll accepts email and Party references. Raw external addresses
696
+ are outside the current run contract.
697
+ `--resume K` prepares the same run again, so it reopens a pending approval
698
+ rather than paying twice.
699
+
700
+ Get returns the full authorized run detail, command, ordered items, and recorded
701
+ times. Wait observes the exact run without polling or submitting. It keeps
702
+ waiting through partial settlement and ends when all Payments settle, a failure
703
+ is recorded, or action is required. Timeout exits 5. Cancellation exits 130.
704
+ Recovery retains exact Organization, run, and any observed request key.
705
+
706
+ ## Invitation commands
707
+
708
+ ```sh
709
+ capxul invite list [--limit N] [--after C] [--phase PHASE ...]
710
+ capxul invite accept [ID] --offer-digest D [--confirm] [--timeout-seconds N]
711
+ capxul invite decline [ID] [--confirm]
712
+ capxul org invite list [--limit N] [--after C] [--phase PHASE ...]
713
+ capxul org invite cancel [ID] [--confirm]
714
+ capxul org invite resend [ID] [--confirm]
715
+ capxul org member invite [EMAIL | --account-id ID] [--budget-id B ...] [--permission-id M ...] [--new-budget-name N --asset A (--limit Q | --unlimited) (--recipient-account ID ... | --any-recipient) --actions pay[,commitments]] [--request-key K] [--preview]
716
+ ```
717
+
718
+ `invite` holds the invitations you received; `org invite` holds the invitations
719
+ the Organization you act as sent. `invite list` returns your own offers.
720
+ `org invite list` returns that Organization's invitations for a current Admin.
721
+ Both accept `--limit` (1--100), `--after`, and repeated `--phase` values, and
722
+ their result carries `invitations`, `nextCursor`, and `observedAt`: pass
723
+ `nextCursor` back as `--after`, and change no other filter between the two calls.
724
+
725
+ A received invitation names its own Organization: `invite accept` and
726
+ `invite decline` walk your own-offer pages, 100 rows per request, to find it.
727
+ `org invite cancel` and `org invite resend` act in the Organization `--org`,
728
+ `CAPXUL_ORG` or `use org` names.
729
+
730
+ Recovery guidance can also name `invite get`, `invite review`, `invite wait`,
731
+ `org invite get`, `org invite wait` and `org invite retry`. They work as before
732
+ but are not listed in the help: `get` and `review` read one offer, `wait`
733
+ follows it until it settles with one SDK subscription, and `retry` resumes the
734
+ backend's own recovery action. None of them writes a new offer.
735
+
736
+ Invitation lists label own-offer or Organization Admin scope and the verified
737
+ actor. They show an explicit empty page, next cursor, or end of results.
738
+
739
+ Invitation human output shows the authoritative phase, delivery, expiry, and
740
+ offered policies. An offer does not prove active membership. Manual resend/retry commands come only
741
+ from the backend action projection, with exact scope/session and earliest time.
742
+ Member-invite previews show exact per-payment caps and allowed recipients/actions;
743
+ expiry is unavailable before authoring. Every authoring write prints its request
744
+ key before submission. JSON result data stays unchanged.
745
+
746
+ Uncertain decline/cancel/resend/retry failures and transition deadlines print an
747
+ exact `get` command for the offer with the resolved session. Read the current
748
+ offer before another transition; a lost response does not authorize replay.
749
+
750
+ The transitions never author a new offer. A noninteractive or JSON run requires
751
+ `--confirm`. An interactive run shows the resolved current offer and asks a
752
+ default-no question.
753
+
754
+ `org member invite` authorizes one exact offer. `--preview` writes nothing and
755
+ needs no request key. A noninteractive write requires `--request-key`. Every
756
+ run prints the request key it used before it prepares, so a lost response is
757
+ recoverable with the same identity. The write authors the invitation, prepares
758
+ the configuration that sets up its offered rights, and hands over to the
759
+ approval page, as `payment send` does: a person sees the preview, `✓ Prepared`,
760
+ `… Approve in your browser` and the link, the CLI follows it to `✓ Signed`, and
761
+ it prints the invitation as it stands. With `--json` it returns at once with
762
+ `status: "awaiting_approval"`, `approvalUrl` and `next.argv` for
763
+ `payment wait <approval id> --org O`. A request key whose invitation is already
764
+ set up returns that invitation. At most one `--new-budget-name` is accepted per
765
+ command.
766
+
767
+ `invite accept` is the exact grantee's consent commit. It takes the exact
768
+ digest the offer shows as `--offer-digest`: a noninteractive or JSON run must
769
+ supply it, and without it the command refuses with exit 2 before it creates a
770
+ client. An interactive run may omit it, and then reads the offer and fills the
771
+ digest from the value it displayed. A digest you state is never replaced by the
772
+ displayed one. `--expected-offer` remains a compatibility spelling, and both
773
+ spellings must match when supplied together. The command returns the
774
+ `InvitationView` directly in `data`. The grant is executed by the deployment's
775
+ technical executor, so the command needs no browser bridge and works in a
776
+ headless or CI session. A repeat with the stored digest returns the same
777
+ accepted result; a different digest refuses and cannot overwrite consent.
778
+
779
+ ## Organization writes
780
+
781
+ org create and org retry use the protected current session unless --email names
782
+ one. A JSON or noninteractive write requires --confirm. A terminal write shows
783
+ the current Organization and recovery information, then asks a default-no
784
+ question. The signer starts after confirmation.
785
+
786
+ `org create --wizard` guides name, handle, country, optional bio and size, then
787
+ session email. Supplied flags remain in the generated command. The final write
788
+ preview names the verified actor and starts with No selected.
789
+ `org retry --wizard` collects the exact Organization ID before session email.
790
+ Its final preview shows the verified actor and current lifecycle. Saved read
791
+ defaults and creation recovery records cannot change that retry ID.
792
+
793
+ org create validates name, handle, and country before client work. It calls
794
+ onboarding.beginOrganization, saves and prints the exact Organization ID,
795
+ authorizes only an awaitingAuthorization setup, then subscribes to setup
796
+ changes. It reports success only after ready and current access. JSON progress
797
+ uses one line per state:
798
+
799
+ { "type": "organization.lifecycle", "organizationId": "O", "status": "processing" }
800
+
801
+ org retry requires one exact --org. It authorizes only awaitingAuthorization.
802
+ For an accepted setup it asks the backend to check the same operation hash
803
+ through setup.resume, then subscribes. Neither command replaces a submitted
804
+ operation. The local recovery record keeps a safe handle and Organization ID
805
+ for convenience; the backend unfinished list supports recovery without it.
806
+
807
+ --timeout-seconds sets one 1-to-3600-second deadline for the command. A
808
+ deadline stops local work and returns exit 5. If the last observed setup has
809
+ another automatic check scheduled, the message is "Stopped waiting.
810
+ Organization setup continues in the background." Before acceptance or without
811
+ a scheduled check, the message is "Stopped waiting. Read the Organization
812
+ setup status." The error details include the safe Organization ID when known,
813
+ last observed setup state, setup reason, and bounded provider diagnostics.
814
+ Ctrl-C stops local work at exit 130. Neither stop writes a backend failure.
815
+
24
816
  ## Configuration
25
817
 
26
- | Variable | Use |
27
- | ------------------------------ | ------------------------------------------------------------------------------------------------------------ |
28
- | `CAPXUL_CLI_HOME` | Directory for global CLI settings. Defaults to `$XDG_CONFIG_HOME/capxul/cli`, or `$HOME/.config/capxul/cli`. |
29
- | `CAPXUL_PUBLISHABLE_KEY` | Application publishable key, required for an online check. |
30
- | `CAPXUL_BOOTSTRAP_URL` | Bootstrap origin. Defaults to `https://api.staging.capxul.com`. Convex Cloud origins are rejected. |
31
- | `CAPXUL_POSTHOG_HOST` | Optional development override for the built-in public PostHog ingestion origin. |
32
- | `CAPXUL_POSTHOG_PROJECT_TOKEN` | Optional development override for the built-in public project ingestion token. |
33
- | `CAPXUL_TELEMETRY_DISABLED` | Set to `true` to disable remote observation regardless of the saved preference. |
34
-
35
- The published CLI includes Capxul-owned public ingestion configuration. You do
36
- not need PostHog environment variables. Collection defaults to enabled for
818
+ | Variable | Use |
819
+ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
820
+ | `CAPXUL_CLI_HOME` | Directory for global CLI settings. Defaults to `$XDG_CONFIG_HOME/capxul/cli`, or `$HOME/.config/capxul/cli`. |
821
+ | `CAPXUL_PUBLISHABLE_KEY` | Optional developer override for the bundled first-party staging key. |
822
+ | `CAPXUL_ENV` | Environment for this process: `staging` or `devnet`. Beats `CAPXUL_BOOTSTRAP_URL` and the saved `use env`; `--env` beats it. |
823
+ | `CAPXUL_BOOTSTRAP_URL` | Bootstrap origin. Defaults to `https://api.staging.capxul.com`. Convex Cloud origins are rejected. |
824
+ | `CAPXUL_CHECKOUT_FRONTEND_ORIGIN` | Checkout frontend origin. Staging uses `https://app.staging.capxul.com`. Devnet at `http://127.0.0.1:3211` uses `http://127.0.0.1:3002`. Custom bootstrap origins require this value. |
825
+ | `CAPXUL_POSTHOG_HOST` | Optional development override for the built-in public PostHog ingestion origin. |
826
+ | `CAPXUL_POSTHOG_PROJECT_TOKEN` | Optional development override for the built-in public project ingestion token. |
827
+ | `CAPXUL_TELEMETRY_DISABLED` | Set to `true` to disable remote observation regardless of the saved preference. |
828
+
829
+ The published CLI includes the verified first-party staging application key and
830
+ Capxul-owned public ingestion configuration. You do not need key or PostHog
831
+ environment variables. A different bootstrap origin requires an explicit key. Collection defaults to enabled for
37
832
  ordinary local and online commands, help, version, and safely attributed argument
38
833
  refusals. Parser refusals produce a completion without a start. Early native
39
834
  global errors with no resolved command route send nothing, because the CLI
40
835
  cannot determine whether they belong to a silent collection control.
41
- `telemetry disable` saves one preference for the OS user and sends no final
836
+ `config telemetry off` saves one preference for the OS user and sends no final
42
837
  remote event. Already running CLI processes check the current preference before
43
- each export. Requests already sent cannot be recalled. `telemetry status`
838
+ each export. Requests already sent cannot be recalled. `config telemetry status`
44
839
  reports the stored preference, effective policy, configuration, and reason.
45
840
  `--log-level` controls normal diagnostic output, not collection. An eligible
46
841
  invocation still produces its remote completion unless collection is disabled.
@@ -59,8 +854,68 @@ unsafe permissions, symlinks, and corrupt state produce a storage failure.
59
854
 
60
855
  ## Output
61
856
 
62
- `--json` writes one version 1 envelope to stdout. Success contains `data`.
63
- Failure contains `error.code` and CLI-owned `error.message`. Each envelope has
857
+ Organization setup failures include a copyable command with the exact ID and
858
+ selected email. When state is uncertain, read status first. A supported retry
859
+ includes `--confirm`; terminal runs still ask for confirmation. If no ID is
860
+ known, the command lists your Organizations instead of guessing one.
861
+ `--json` writes one version 1 envelope to stdout. Success contains `data`: the
862
+ SDK's own value for the command, with no CLI wrapper. A list is the SDK page,
863
+ `{ items, nextCursor }`; pass `nextCursor` back as `--after` where the command
864
+ takes one. A list whose next cursor would show the same page again fails with
865
+ exit 1 and `The list did not advance past the cursor <cursor>`, so a paging loop
866
+ ends. `--fields a,b` keeps only those fields of `data` (`amount.value`
867
+ reaches inside an object; a list keeps `nextCursor` and picks from each item).
868
+ `--fields` without `--json` refuses, and so does a typo: a name the result lacks that is a
869
+ letter or two off a name it has (exit 2, `field: "fields"`); the message names it, the
870
+ closest real field and the fields in this result. Any other name the result lacks, such as
871
+ an optional `execution` on a Payment that has none, is left out, as `jq` would.
872
+ The commands that move money (`payment send`, `payment retry`, `payment cancel`,
873
+ `payment redirect`, `inbox pay`,
874
+ `org payroll run`) check the names against the result they declare before they
875
+ run, so a typo never costs an approval: `status`, `approvalId`, `approvalUrl`,
876
+ `paymentIds`, `expiresAt` and `next`.
877
+
878
+ A failure contains `error`:
879
+
880
+ ```json
881
+ {
882
+ "code": "CLI_USAGE",
883
+ "message": "Unknown command \"paymnt\".",
884
+ "hint": "Did you mean: capxul payment list",
885
+ "next": { "argv": ["capxul", "payment", "list"] }
886
+ }
887
+ ```
888
+
889
+ `code` and `message` are always present. `hint` says what to do when a sentence
890
+ helps, `field` names the refused input, and `next.argv` is the command that
891
+ fixes it or reads where an interrupted command stands: `capxul auth login` when
892
+ no one is signed in, the corrected command for a typo, or the exact `get` for an
893
+ uncertain write. `next` preserves the same scope as the human command; it does
894
+ not grant authority or bypass current checks. `error.details.recovery` keeps
895
+ its `kind` (`read` or `retry`) next to the same `argv`.
896
+
897
+ A person sees one red line for what happened and one for what fixes it (on the
898
+ same line when both fit in 80 columns), then a dim last line, `ref <id>`, for
899
+ support:
900
+
901
+ ```text
902
+ ✗ Unknown command "paymnt". Did you mean: capxul payment list
903
+ ✗ Not signed in. Try: capxul auth login
904
+ ref 6a0e10d1-06fb-4eed-9c2a-1f6f0c2b7d11
905
+ ```
906
+
907
+ The `ref` is the backend's request ID when the error carries one, else its
908
+ correlation ID, else this run's `invocationId`. A mistyped command has none,
909
+ because no command started. An error that already quotes its request ID in its
910
+ sentence (a redacted backend error) has no `ref` line. JSON output has no `ref`
911
+ line and is unchanged: read `error.details.requestId` or `invocationId`.
912
+
913
+ A wallet failure
914
+ also includes its known `error.mode` and allowed `error.details`: wallet stage,
915
+ operation, provider, provider code, and HTTP status. An unknown browser failure
916
+ uses mode `unknown`. No provider message, token, signature, or native cause enters
917
+ the result. These fields remain available when collection is off or
918
+ `--log-level none` is set. Each envelope has
64
919
  `command`, `invocationId`, and `outcome`. An invocation ID is null before a
65
920
  command starts. Human errors go to stderr.
66
921
 
@@ -109,15 +964,295 @@ compinit
109
964
  Use `npm update -g @capxul/cli` or `brew upgrade xelmar-tech/tap/capxul` to update.
110
965
  Use one installer for the `capxul` executable to avoid conflicting PATH entries.
111
966
 
967
+ After a successful human command, help, or version request, the CLI can show an
968
+ update notice on terminal stderr. It checks the public npm `latest` tag at most
969
+ once per 24 hours. It shows only the command for the verified running npm-global
970
+ or Homebrew installation. It does not execute that command. Unknown installations,
971
+ development versions, JSON output, redirected stderr, CI, shell completion, and
972
+ all `telemetry` commands receive no notice. The optional check has one 500 ms
973
+ budget. Safe failed attempts are cached. Storage or network failures remain
974
+ silent and do not change the command result. This check sends no telemetry.
975
+
976
+ ## Sandbox: `capxul dev`
977
+
978
+ `capxul dev` is for building and testing on Capxul, agents included, without real
979
+ money. It works on a test deployment: staging, or a local DevNet
980
+ (`capxul-devnet up --browser-origin http://localhost:3000` in this repository, then
981
+ `capxul use env devnet`). Production refuses both commands.
982
+
983
+ ```sh
984
+ capxul dev fund 100 # test money into your own Safe (default 100 USDC)
985
+ capxul dev fund 50 --asset USDT
986
+ capxul dev key # a test publishable key for http://localhost:3000, into .env.local
987
+ capxul dev key --origin http://localhost:3100 --print
988
+ ```
989
+
990
+ `dev fund` needs you signed in and funds only your own Safe. `dev key` needs no
991
+ sign-in; it sets `NEXT_PUBLIC_CAPXUL_PUBLISHABLE_KEY` and `CAPXUL_SITE_URL` in
992
+ `.env.local` and keeps every other line. On staging, sign-in works only from
993
+ `http://localhost:3000` or `http://localhost:3100`.
994
+
995
+ [`tests/dev-journeys.mjs`](tests/dev-journeys.mjs) runs the agent plugin's
996
+ journeys with the built CLI against the local DevNet: sign in, `dev fund`, the home
997
+ screen, a payment (refused with its fix while the wallet setup is unfinished, as
998
+ it is on a DevNet with no wallet provider), requests, offers, Inbox, Organizations,
999
+ the account, `schema`, a typo's fix and `dev key`. The `cli-journeys` job in
1000
+ `.github/workflows/devnet-integration.yml` starts the DevNet and runs it.
1001
+
112
1002
  ## Development commands
113
1003
 
114
1004
  ```sh
115
1005
  vp test run apps/cli
116
1006
  vp run --filter @capxul/cli check-types
1007
+ vp run --filter @capxul/cli lint
117
1008
  vp run --filter @capxul/cli build
118
- vp exec node --test --test-name-pattern='@capxul/cli' scripts/__tests__/pack-install-smoke.test.mjs
1009
+ vp exec node --test --test-name-pattern='@capxul/cli' packages/tools/src/modules/release/release.pack-install.test.mjs
119
1010
  ```
120
1011
 
121
1012
  The last command installs the tarball outside the workspace and exercises the
122
1013
  installed executable with isolated settings and a local HTTP server. The CI
123
1014
  `CLI / Linux / Node 24.0.0` job runs this proof at the declared minimum version.
1015
+
1016
+ ## Email login and session restoration
1017
+
1018
+ This CLI establishes a first-party BetterAuth session. An older native
1019
+ `account:read` grant does not count as sign-in and cannot read the profile.
1020
+ Logout clears the selected email's session and attempts to revoke any native
1021
+ grant that was stored before the first-party flow replaced it.
1022
+
1023
+ On a terminal, `auth login` is a wizard. It asks for the email and a masked OTP.
1024
+ It accepts the code as a paste. It retries an invalid code at most three times
1025
+ for one request.
1026
+
1027
+ `auth login` and `account retry` never open a browser, in any output mode. When
1028
+ your Account is not set up, they print where to finish it:
1029
+
1030
+ ```text
1031
+ Signed in as person@example.com.
1032
+ Account setup required.
1033
+ Finish setting up your Account in your browser, signed in as person@example.com:
1034
+ https://app.staging.capxul.com/
1035
+ Then check it with: capxul account retry --email 'person@example.com'
1036
+ ```
1037
+
1038
+ With `--json`, `data` carries the same handover:
1039
+ `setupState: "setup-required"`, `status: "awaiting_setup"`, `setupUrl` and
1040
+ `next.argv` (`["capxul", "account", "retry", "--email", EMAIL, "--json"]`, with the
1041
+ `--org` and `--env` you typed). That read exits 0 and returns the handover again,
1042
+ or the ready report. `capxul schema auth login` declares the shape.
1043
+
1044
+ Ctrl+C or Ctrl+D at a wizard prompt cancels the command. The command prints no
1045
+ success result and exits 130. A step that already finished keeps its result: a
1046
+ completed sign-in keeps its session.
1047
+
1048
+ For an agent, send and verify in separate processes:
1049
+
1050
+ ```sh
1051
+ capxul auth login --email "$TEST_EMAIL" --json
1052
+ # The code from the email, as an argument or on stdin with --otp-stdin.
1053
+ capxul auth verify "$CODE" --json
1054
+ # A later process uses the same protected CLI home; no new code is required.
1055
+ capxul whoami --json
1056
+ capxul auth logout --json
1057
+ ```
1058
+
1059
+ After sending a code, the output names `capxul auth verify <code>`. If
1060
+ verification has no waiting sign-in, the error names `capxul auth login`.
1061
+ Neither command prints the code itself.
1062
+
1063
+ Human profile/status output labels your Profile fields and available Account,
1064
+ wallet and Smart Account identifiers. Failed setup includes its stage and error
1065
+ code. These reads do not open the wallet browser. `--json` retains the structured
1066
+ result, including the same Profile and lifecycle values.
1067
+
1068
+ A machine run never prompts. `auth login` with `--otp-stdin` sends the OTP and
1069
+ verifies one code from stdin. It returns the profile report, with the setup
1070
+ handover when the Account is not ready. It starts no setup work.
1071
+
1072
+ `--otp-stdin` reads up to 64 bytes, ending at EOF. Pipe from a secret provider or
1073
+ use input redirection from a protected file. An invalid value refuses with exit 2.
1074
+ Only `auth verify <code>` accepts a code as an argument: the code is single-use
1075
+ and expires in minutes. Codes are never persisted or included in output.
1076
+
1077
+ `setupState: "ready"` is a personal Account that the Account readiness owner
1078
+ reads as ready and deployed. Its data carries the public identifiers: the
1079
+ Profile, the public wallet address (`smartAccount.signerAddress`), the personal
1080
+ Smart Account address (`smartAccount.smartAccountAddress`), the Account ID
1081
+ (`lifecycle.accountId`), and the ready status. Any other state is
1082
+ `setupState: "setup-required"` with the lifecycle, its failure code, and the
1083
+ handover above.
1084
+
1085
+ A ready personal Account continues the same journey into Organization creation
1086
+ with `capxul org create --name NAME --handle HANDLE --country CC`. The create
1087
+ command records the safe recovery handle for that Organization, so an
1088
+ interruption or a restart resumes the exact same Organization.
1089
+
1090
+ The version 2 `first-party-session` record stores the opaque provider credential
1091
+ in the existing protected plaintext store. Its scope includes the application
1092
+ key, issuer, environment, and email. Each process validates restoration with the
1093
+ backend; cached session data is not authority. Conditional replacement prevents
1094
+ a concurrent logout from being undone by a delayed credential save. The backend
1095
+ owns expiry and revocation. A failed remote logout is reported as `unconfirmed`;
1096
+ local sign-out remains in effect.
1097
+
1098
+ `account show` returns a backend-read Profile and account lifecycle without opening
1099
+ the browser. Successful email authentication can return `setupState: "setup-required"`.
1100
+ `account retry` returns `setupState: "ready"` only after Core reads a ready Account;
1101
+ otherwise it returns the web app handover.
1102
+ After logout, profile reads refuse with `NOT_AUTHENTICATED` and exit 3. An invalid
1103
+ or expired OTP refuses with exit 2.
1104
+
1105
+ Find where to finish an incomplete personal Account:
1106
+
1107
+ ```sh
1108
+ capxul account retry --email you@example.com
1109
+ ```
1110
+
1111
+ It writes nothing and opens no browser. Missing Account or Profile state in other
1112
+ commands directs to `account retry`.
1113
+
1114
+ Read an Organization treasury or deposit target:
1115
+
1116
+ ```sh
1117
+ capxul balance --org org_example --email you@example.com
1118
+ capxul address --org org_example --email you@example.com
1119
+ capxul balance --wizard
1120
+ ```
1121
+
1122
+ These commands use the existing Organization read selection. Balances require
1123
+ backend treasury access. Deposit instructions use the public SDK's own-access
1124
+ projection. Neither command starts a signer or changes Organization setup.
1125
+
1126
+ Contact reads show the selected scope, label, full Party ID, reference,
1127
+ relationships and hidden state. JSON keeps the existing array, entry or null.
1128
+
1129
+ ```sh
1130
+ capxul contact list --include-hidden
1131
+ capxul contact get party_example
1132
+ capxul contact get --org org_example --wizard
1133
+ ```
1134
+
1135
+ In a terminal, omit the ID to select a contact, including hidden contacts.
1136
+ In a script, provide the exact Party ID. Organization contacts always require
1137
+ an explicit `--org`; they never use the personal book as a fallback.
1138
+
1139
+ Contact add shows the reference and optional label before terminal confirmation.
1140
+ Without an input file, the wizard asks for these values. On an uncertain response,
1141
+ use the printed list command to check the same address book before adding again.
1142
+ Adding an existing contact can unhide it or change its label.
1143
+
1144
+ Change a contact label with `contact label party_example --label
1145
+ "New label" --confirm`. In a terminal, omit the Party ID to select from the
1146
+ same book, including hidden contacts. Organization labels require `--org`.
1147
+ After an uncertain response, use the exact get command printed by the CLI.
1148
+
1149
+ `contact hide` can select a contact in a terminal when the ID is omitted.
1150
+ It confirms the hidden state, then prints the exact `contact unhide` command for
1151
+ the same Party, session and scope. The contact's history remains available.
1152
+
1153
+ `contact unhide` uses the same scoped selector, including hidden contacts, when
1154
+ a terminal omits the ID. It confirms the change and shows the visible
1155
+ contact. Scripts provide the exact Party ID and `--confirm`.
1156
+
1157
+ ## Fixed offers
1158
+
1159
+ Manage fixed service offers in your personal Account or an explicit Organization.
1160
+ These commands do not sign payments or create checkout purchases.
1161
+
1162
+ ```sh
1163
+ capxul offer create --input offer.json --request-key consulting-001 --confirm
1164
+ capxul offer list
1165
+ capxul offer get OFFER_ID
1166
+ capxul offer revise OFFER_ID --expected-revision 1 --input offer.json --confirm
1167
+ capxul offer deactivate OFFER_ID --expected-revision 2 --confirm
1168
+ capxul offer list --org ORG_ID
1169
+ ```
1170
+
1171
+ Add `--org ORG_ID` to run any of these as an Organization. Use `--email`
1172
+ to select a saved session. Scripts must supply `--confirm` for each write.
1173
+ A terminal shows the proposed change and asks for confirmation. Use `--json`
1174
+ for structured output. Lists and reads create no PDF.
1175
+
1176
+ The input file contains the complete offer terms. Use `--input -` to read stdin.
1177
+ The input limit is 64 KiB. Supply an admitted Base Sepolia asset ID from the
1178
+ existing asset catalog. Amounts use exact decimal strings. Quantity limits use
1179
+ positive whole numbers.
1180
+
1181
+ ```json
1182
+ {
1183
+ "title": "Consulting",
1184
+ "description": "One hour of consulting",
1185
+ "unitLabel": "hour",
1186
+ "unitAmount": { "asset": "ASSET_ID", "value": "12" },
1187
+ "quantity": { "min": 1, "max": 8 }
1188
+ }
1189
+ ```
1190
+
1191
+ Creation requires an explicit replay key. Keep the key and identical terms when
1192
+ recovering an uncertain result. Read the offer list before another write. Revision
1193
+ and deactivation require the revision you observed. A conflict requires a fresh
1194
+ read. The CLI does not retry a write automatically. Successful offer results
1195
+ include `checkoutUrl`. Share that URL for another purchase of the same offer.
1196
+ An offer link is not a saved purchase or proof of payment.
1197
+
1198
+ The checkout page reads the current offer before the payer continues. A quantity
1199
+ in the URL is a hint. The backend checks its bounds and freezes the selected
1200
+ revision, quantity, price, asset, network, and recipient for that purchase.
1201
+ Changing the URL cannot change a saved purchase. Refresh retains its checkout
1202
+ reference. Separate purchasers receive separate checkout and settlement IDs.
1203
+
1204
+ ## Request and document flow
1205
+
1206
+ Alice issues a basic request or an Invoice to Bob with `request issue`. For an Organization issuer,
1207
+ Alice uses `request issue --org ORGANIZATION_ID`. Issuance returns the request ID,
1208
+ document references, and checkout URL. Alice saves her PDF with the printed
1209
+ `document render` command.
1210
+ Bob runs `inbox list`, then `inbox get REQUEST_ID`. An Organization
1211
+ payer uses the same `inbox` commands with `--org`.
1212
+
1213
+ Bob's Inbox contains the request and document references. Bob uses the printed
1214
+ `document render` command to save his copy. Both participants read the same verified document. Their files can
1215
+ have different local paths. The home screen (`capxul`) shows how many requests wait
1216
+ for you; it does not download documents.
1217
+
1218
+ A direct Payment uses the existing Payment and Activity commands. Alice inspects
1219
+ her outgoing records. Bob inspects his incoming records after the backend observes
1220
+ them. Available document references can then be rendered by an authorized
1221
+ participant. Issuance, signing, submission, and settlement are separate states.
1222
+ A PDF file or checkout link does not prove that funds moved.
1223
+
1224
+ Cancellation removes the request from the received Inbox list. Because `inbox get`
1225
+ reads that list, it cannot find the cancelled ID. Existing participant document
1226
+ access remains available through the saved document and content hashes. Keep
1227
+ those references when retaining a cancelled Invoice.
1228
+
1229
+ The shared document directory is `documents` next to the CLI settings directory.
1230
+ `CAPXUL_CLI_HOME` selects a separate CLI settings directory. `document render
1231
+ --output-dir` changes the document output location. Each render preserves
1232
+ previous files. A failed PDF render does not repeat issuance or payment. Retry
1233
+ `document render` with the existing document references.
1234
+
1235
+ ## Checkout links
1236
+
1237
+ A basic request URL has the form `/checkout/requests/LINK_TOKEN`. Existing Invoice
1238
+ URLs use `/checkout/invoices/LINK_TOKEN`. An offer URL uses `/checkout/offers/OFFER_ID`. Use the complete `checkoutUrl` returned by the
1239
+ CLI. Do not build a payment by sending funds directly to the printed Safe.
1240
+
1241
+ A valid request link holder can fund its fixed obligation. The named debtor and
1242
+ actual sender remain separate. Public checkout shows the approved payment
1243
+ summary. It does not expose private billing details or original document bytes.
1244
+ Only authorized participants can open the private Invoice document.
1245
+
1246
+ The checkout page offers registered Account or Organization funding and supported
1247
+ external wallet funding. Registered funding uses the selected actor's authority.
1248
+ External funding requires the correct network, balance, gas, and any exact token
1249
+ approval. Payment goes through the Payments contract with the validated snapshot.
1250
+ Inspect the resulting state and receipt before reporting payment complete.
1251
+
1252
+ CLI `inbox pay` prepares the request's Payment and hands over to the approval
1253
+ page, as `payment send` does. It does not depend on the hosted checkout page.
1254
+ A rejection on the approval page is not permission to send another Payment.
1255
+ `--resume` reopens the approval of a request whose Payment is already prepared.
1256
+
1257
+ Checkout links do not create recurring billing, automatic debits, booking,
1258
+ refunds, or QR codes.