primcli 1.22.0 → 1.25.0

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.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @primitivedotdev/cli
1
+ # primitive
2
2
 
3
3
  Official Primitive CLI. Deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal.
4
4
 
@@ -10,24 +10,116 @@ primitive whoami
10
10
  Or with npm:
11
11
 
12
12
  ```bash
13
- npm install -g @primitivedotdev/cli
13
+ npm install -g primitive
14
14
  primitive whoami
15
15
  # `prim` is installed as a short alias for the same CLI.
16
16
  prim whoami
17
17
  ```
18
18
 
19
- The same CLI is also published unscoped as [`primcli`](https://www.npmjs.com/package/primcli). `npm install -g primcli` installs an identical build with the same `primitive`/`prim` commands. Use whichever name you prefer; they track the same version.
19
+ The same CLI is also published as [`primcli`](https://www.npmjs.com/package/primcli) and under the legacy scoped name [`@primitivedotdev/cli`](https://www.npmjs.com/package/@primitivedotdev/cli). Each installs an identical build with the same `primitive`/`prim` commands. Use whichever name you prefer; they track the same version.
20
20
 
21
21
  Or with no install:
22
22
 
23
23
  ```bash
24
- npx @primitivedotdev/cli@latest <command>
24
+ npx primitive@latest <command>
25
25
  ```
26
26
 
27
27
  This package wraps the [@primitivedotdev/sdk](https://www.npmjs.com/package/@primitivedotdev/sdk) runtime client with one-shot commands. For in-handler use (calling Primitive from inside a Function), import `createPrimitiveClient` from `@primitivedotdev/sdk/api` directly; the CLI is for operator and deploy workflows.
28
28
 
29
29
  ## Quickstart
30
30
 
31
+ ### Receive webhook events without a public endpoint
32
+
33
+ With an existing Primitive account and inbox, sign in or set `PRIMITIVE_API_KEY`.
34
+ Run `primitive listen` to print existing webhook events as JSONL. Status goes to
35
+ stderr. No public URL or separate destination setup is required.
36
+
37
+ For an agent, use a short hook that saves each event into its durable inbox:
38
+
39
+ ```sh
40
+ primitive listen init --language python
41
+ cd primitive-listener
42
+ primitive listen --subscription my-agent --exec 'python3 accept_event.py'
43
+ ```
44
+
45
+ The starter works locally and refuses to overwrite an existing directory. Its
46
+ SQLite inbox is application-owned example code. Replace `accept_event` with your
47
+ agent's existing durable input function. Exit 0 means the input was saved; run
48
+ model work separately so the listener can keep receiving while the agent thinks.
49
+ The hook has a 30-second deadline. Do not spawn a background agent from the hook.
50
+ `--exec` requires macOS or Linux for process-group cleanup. On Windows, use
51
+ `--forward-to` with your agent's local HTTP acceptance handler.
52
+
53
+ The CLI passes the unchanged event body on stdin, plus `PRIMITIVE_EVENT_ID`,
54
+ `PRIMITIVE_DELIVERY_ID`, and `PRIMITIVE_EVENT_TYPE` in the hook environment.
55
+ Deduplicate by `PRIMITIVE_EVENT_ID`, which stays the same on redelivery. Delivery
56
+ IDs identify individual attempts. Related events need not contain an email or a
57
+ body-level event ID. The generated processing example shows existing Python SDK
58
+ conversation and reply calls; sending requires an explicit choice.
59
+
60
+ To run an existing HTTP webhook handler locally:
61
+
62
+ ```sh
63
+ primitive listen --subscription local-webhook --forward-to http://localhost:3000/webhook
64
+ ```
65
+
66
+ This mode forwards the exact signed body and existing webhook headers. Configure
67
+ the handler with your existing account webhook secret and normal signature
68
+ verification. The CLI never forwards your API credentials. It does not follow
69
+ redirects or disable TLS verification. A response must finish within 30 seconds
70
+ and remain within 1 MiB. Existing confirmation headers retain their meaning,
71
+ including account content-discard behavior; exec and stdout do not confirm
72
+ content discard.
73
+
74
+ Use `--events email.received,interaction.ack.received` to select events on a new
75
+ subscription. Omitting `--events` when resuming preserves its selection. A
76
+ conflicting selection requires a different subscription name. Ctrl-C disconnects
77
+ without deleting the destination; restart with the same name to receive pending
78
+ events. On the same machine, a second listener cannot consume that subscription
79
+ while the first holds it. The same name on different machines shares consumption;
80
+ different names receive independent copies. With no name, the CLI saves a private
81
+ default identity scoped to your API host and account.
82
+
83
+ `--number N` exits after N successful, server-confirmed completions. A crash after
84
+ the hook saves input but before completion can redeliver it. Bare stdout is for
85
+ inspection: a successful pipe write does not prove a downstream agent saved the
86
+ event. Use the durable hook for ingestion.
87
+
88
+ The server retains pending references for 24 hours, subject to source-content
89
+ availability and queue capacity. The listener reports delivery gaps instead of
90
+ silently claiming it is caught up. Saving download links does not preserve
91
+ attachment bytes or extend their expiry. To remove a destination, use its ID from
92
+ the readiness message: `primitive endpoints delete --id DESTINATION_ID`.
93
+
94
+ ### Low-level delivery API
95
+
96
+ The generated `endpoints pull-webhook-event` and `endpoints complete-webhook-event`
97
+ commands expose the local-delivery API when enabled on your API host. These are
98
+ single API calls; a receive loop must retain the destination identity and report
99
+ each attempt's outcome. Use `--help` to inspect the request fields:
100
+
101
+ ```sh
102
+ primitive endpoints pull-webhook-event --help
103
+ primitive endpoints complete-webhook-event --help
104
+ ```
105
+
106
+ Completion uses a mode-specific JSON body. For a successful process handler:
107
+
108
+ ```sh
109
+ primitive endpoints complete-webhook-event --id ENDPOINT_ID --raw-body '{"queue_id":"QUEUE_ID","delivery_id":"DELIVERY_ID","lease_token":"LEASE_TOKEN","mode":"exec","exit_code":0,"duration_ms":12}'
110
+ ```
111
+
112
+ Use the IDs and lease token returned by pull. HTTP forwarding reports
113
+ `mode: "http"` with `status_code`; stdout reports `mode: "stdout"` with
114
+ `write_succeeded`. Transport failures must also be reported. Successful handler
115
+ acceptance is separate from any later agent reasoning.
116
+
117
+ Pull delivery preserves existing webhook bodies and supplies canonical event and
118
+ attempt IDs separately. Deduplicate by event ID. A successful completion can be
119
+ retried with the same queue, attempt, token, and outcome. Check the returned gap
120
+ count as well as the backlog; queue retention does not extend email-content
121
+ retention. Conversation retrieval and threaded replies use the existing SDK API.
122
+
31
123
  ```bash
32
124
  primitive signin
33
125
  primitive whoami
@@ -64,6 +156,7 @@ primitive chat reply "See attached" --attachment ./report.pdf
64
156
  primitive emails list
65
157
  primitive emails get --id <inbound-email-id>
66
158
  primitive sent list
159
+ primitive sent delete --id <sent-email-id>
67
160
  primitive domains list
68
161
  primitive functions templates
69
162
  primitive functions init my-fn --template email-reply
@@ -75,6 +168,24 @@ primitive deliveries replay --id <delivery-id>
75
168
 
76
169
  Generated API commands remain available for compatibility and full schema parity, for example `primitive emails:list-emails` and `primitive sending:reply-to-email`.
77
170
 
171
+ ## Remove mailbox history
172
+
173
+ `primitive sent delete --id <sent-email-id>` removes sender history and owned
174
+ attachments. It does not recall delivery or delete recipient copies. Cancel
175
+ scheduled sends before deleting them. A 409 means the record is not currently
176
+ eligible; a 500 or 503 may mean some files were removed already, so retry the same
177
+ DELETE. Repeating a completed deletion succeeds.
178
+
179
+ After disconnecting an agent, an owner or admin logged in with OAuth can run
180
+ `primitive agent-connections remove-agent-connection --address agent@example.com`.
181
+ This removes the revoked connection record while preserving mail, notes and the
182
+ external runtime. Active connections return 409; missing records return 404.
183
+ Organization API keys cannot remove connections.
184
+
185
+ Send and reply can return HTTP 410 `sent_email_deleted` when a prior send was
186
+ deleted. Its occupied idempotency key or automatic reply suppression stays reserved.
187
+ Do not generate a new key or send again to bypass this refusal.
188
+
78
189
  ## Primitive Memories
79
190
 
80
191
  Memories are durable JSON key-value records scoped to your org by default. Use
@@ -124,10 +235,11 @@ The `primitive payments` command group drives non-custodial x402 USDC payments.
124
235
  # ownership message locally with your wallet key. Org is auto-resolved.
125
236
  primitive payments register-payout-address --network base-sepolia --label treasury
126
237
 
127
- # Payee: request a payment with a human USDC amount. Prints a summary by default.
238
+ # Payee: request a payment with a human USDC amount. Prints the challenge JSON
239
+ # to stdout; a one-line summary goes to stderr.
128
240
  primitive payments charge --network base-sepolia --amount-usdc 0.01
129
- # Capture the raw challenge JSON to hand to the payer.
130
- primitive payments charge --network base-sepolia --amount-usdc 0.01 --json > challenge.json
241
+ # Capture the challenge JSON to hand to the payer.
242
+ primitive payments charge --network base-sepolia --amount-usdc 0.01 > challenge.json
131
243
 
132
244
  # Payer: sign and settle the challenge locally. Reads the challenge inline,
133
245
  # from a file, or piped on stdin.
@@ -164,7 +276,7 @@ primitive payments get-spend-policy
164
276
  primitive payments update-spend-policy --max-per-payment 5000000
165
277
  ```
166
278
 
167
- `charge` is the friendly verb that matches the SDK `charge` and accepts `--amount-usdc`; `create-challenge` is the lower-level command that takes base-unit `--amount`. Either creates a challenge. The signing commands print a human-readable summary by default; pass `--json` for raw JSON suitable for piping.
279
+ `charge` is the friendly verb that matches the SDK `charge` and accepts `--amount-usdc`; `create-challenge` is the lower-level command that takes base-unit `--amount`. Either creates a challenge. All four signing commands accept `--json`. `register-payout-address` and `pay` print a human-readable summary by default and raw JSON with `--json`; `pay-email` and `pay-email-step` print JSON by default (the send result and the `interaction.json` bytes, respectively), and `--json` switches them to a fuller envelope object.
168
280
 
169
281
  The signing commands (`register-payout-address`, `pay`, `pay-email`, and `pay-email-step`) need your wallet key. `pay-email` is the recommended payer path for the email-native flow: it signs and sends in one step. `pay-email-step` signs only and emits the `interaction.json` artifact for advanced use where you want to deliver it yourself. Set the key in `PRIMITIVE_X402_PRIVATE_KEY` (a `0x`-prefixed hex private key) so it never lands in shell history or the process list:
170
282
 
@@ -172,7 +284,7 @@ The signing commands (`register-payout-address`, `pay`, `pay-email`, and `pay-em
172
284
  export PRIMITIVE_X402_PRIVATE_KEY=0x...
173
285
  ```
174
286
 
175
- A hidden `--private-key` flag is available as an escape hatch for scripted use, but the environment variable is preferred. The non-signing commands (`charge`, `get-challenge`, `list-payout-addresses`, `get-spend-policy`, `update-spend-policy`) need only your Primitive API key. Run `primitive payments <command> --help` for the full flag list of any command.
287
+ A `--private-key` flag is available as an escape hatch for scripted use, but the environment variable is preferred. The non-signing commands (`charge`, `get-challenge`, `list-payout-addresses`, `get-spend-policy`, `update-spend-policy`) need only your Primitive API key. Run `primitive payments <command> --help` for the full flag list of any command.
176
288
 
177
289
  ## Migrating from `@primitivedotdev/sdk` CLI
178
290
 
@@ -180,10 +292,10 @@ The CLI previously shipped inside `@primitivedotdev/sdk`. The shipped surface ar
180
292
 
181
293
  | Before | After |
182
294
  |--------|-------|
183
- | `npm install -g @primitivedotdev/sdk` | `npm install -g @primitivedotdev/cli` |
184
- | `npx @primitivedotdev/sdk@latest <cmd>` | `npx @primitivedotdev/cli@latest <cmd>` |
295
+ | `npm install -g @primitivedotdev/sdk` | `npm install -g primitive` |
296
+ | `npx @primitivedotdev/sdk@latest <cmd>` | `npx primitive@latest <cmd>` |
185
297
 
186
- `@primitivedotdev/sdk` continues to ship the runtime SDK (webhook, API client, contract, parser, openapi). Use it in your application code; use `@primitivedotdev/cli` in your shell and CI.
298
+ `@primitivedotdev/sdk` continues to ship the runtime SDK (webhook, API client, contract, parser, openapi). Use it in your application code; use `primitive` in your shell and CI.
187
299
 
188
300
  ## License
189
301