primcli 1.74.1 → 3.0.0-preview.1

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 (31) hide show
  1. package/README.md +165 -72
  2. package/bin/claude-pending-mail.mjs +1 -1
  3. package/bin/run.js +14 -0
  4. package/dist/{api-command-fKP3NYa7.js → api-command-ctHBqTL5.js} +825 -95
  5. package/dist/{cli-config-C0Y_Ppol.js → cli-config-Ms_0vNjq.js} +66 -28
  6. package/dist/{client.gen-CaaMP86o.js → client.gen-6rZvmHfx.js} +7 -14
  7. package/dist/{json-output-Ce10AsSb.js → json-output-BzSBR-KX.js} +1 -2
  8. package/dist/{listen-background-cD6n8VYO.js → listen-background-C0F9gNDD.js} +2 -3
  9. package/dist/{machine-session-B6V5-grn.js → machine-session-Cp_eQ9t_.js} +164 -99
  10. package/dist/{notify-session-DJAb9SGm.js → notify-session-BN0JTPZ3.js} +341 -31
  11. package/dist/oclif/auto-signal-worker.js +5 -6
  12. package/dist/oclif/auto-signals.js +4 -5
  13. package/dist/oclif/global-org-flag.js +76 -0
  14. package/dist/oclif/help.js +127 -0
  15. package/dist/oclif/index.js +93239 -31954
  16. package/dist/oclif/listen-supervisor.js +1 -1
  17. package/dist/oclif/proxy-auto-detect.js +2 -3
  18. package/dist/oclif/receiver-heal.js +6 -6
  19. package/dist/oclif/root-signup-hint.js +3 -4
  20. package/dist/receiver.d.ts +95 -0
  21. package/dist/receiver.js +569 -0
  22. package/dist/{repeats-BL7ZC-_6-B_ESsWTH.js → repeats-Dj_o6c-X-Bf9G0xds.js} +4617 -1744
  23. package/dist/{scoped-chat-DAiOb622.js → scoped-chat-DZ42V3jq.js} +3 -5
  24. package/dist/{shared-mail-files-CZfm7E2k.js → shared-mail-files-BAQSGxxz.js} +2 -4
  25. package/dist/{shared-mail-watch-DyQB0MK0.js → shared-mail-watch-BAPMsFNv.js} +2 -3
  26. package/dist/{signal-command-Cte4mAL3.js → signal-command-CRUMUCNa.js} +19 -27
  27. package/dist/skills/primitive-connect/references/connect.md +3 -1
  28. package/dist/skills/primitive-connect/references/contacts.md +9 -4
  29. package/dist/skills/primitive-connect.json +4 -4
  30. package/man/primitive.1 +44 -3
  31. package/package.json +65 -15
package/README.md CHANGED
@@ -103,11 +103,11 @@ the readiness message: `primitive endpoints delete --id DESTINATION_ID`.
103
103
  The generated `endpoints pull-webhook-event` and `endpoints complete-webhook-event`
104
104
  commands expose the local-delivery API when enabled on your API host. These are
105
105
  single API calls; a receive loop must retain the destination identity and report
106
- each attempt's outcome. Use `--help` to inspect the request fields:
106
+ each attempt's outcome. Use `--help-full` to inspect the request fields:
107
107
 
108
108
  ```sh
109
- primitive endpoints pull-webhook-event --help
110
- primitive endpoints complete-webhook-event --help
109
+ primitive endpoints pull-webhook-event --help-full
110
+ primitive endpoints complete-webhook-event --help-full
111
111
  ```
112
112
 
113
113
  Completion uses a mode-specific JSON body. For a successful process handler:
@@ -140,7 +140,7 @@ primitive emails latest --limit 5
140
140
  primitive inbox next
141
141
  ```
142
142
 
143
- Run `primitive --help` for the full command list. Per-command help (`primitive functions deploy --help`) carries enough detail that an agent can compose any operation without leaving the terminal.
143
+ Run `primitive --help` for the full command list. Per-command help (`primitive functions deploy --help`, or `-h`) is one screen: a summary, usage, one line per flag, and two examples. `primitive functions deploy --help-full` prints the complete text, with every flag's full description, behavior notes, and all examples, so an agent can compose any operation without leaving the terminal.
144
144
 
145
145
  ## Verification codes and sign-in links
146
146
 
@@ -150,9 +150,9 @@ enter it, wait for the email and take what you need from it:
150
150
  ```bash
151
151
  # Sign up with your address, then:
152
152
  primitive wait --from github.com --code # prints 482913
153
- primitive wait --from vercel.com --link # prints the sign-in link
153
+ primitive wait --from accounts.example.com --link # prints the sign-in link
154
154
  primitive wait --subject "verify" --timeout 90s
155
- primitive wait --from stripe.com --code --json
155
+ primitive wait --from billing.example.com --code --json
156
156
  ```
157
157
 
158
158
  `primitive wait` waits for the next email to the identity the CLI resolves (a
@@ -224,8 +224,47 @@ Use `primitive signin <email> --accept-terms`, then `primitive signin confirm <e
224
224
 
225
225
  Use `primitive logout --force` to remove local CLI credentials, pending email-code auth state, and stale credential locks without contacting Primitive. This is the recovery command when an interrupted auth command leaves the CLI saying another credential operation is already in progress.
226
226
 
227
+ Use `primitive org leave` to leave the organization you are signed in to. It asks for confirmation first; pass `--yes` to skip the prompt in scripts. Leaving is final. Only a person signed in with `primitive login` can leave; API keys are refused. The only owner of an organization cannot leave it until someone else is made an owner. If the server asks you to confirm in the dashboard, the command prints the confirmation page and, in a terminal, asks for the token it shows; in a script, pass the token with `--step-up-token`. Refusals from the server are printed as returned, and the command exits 1.
228
+
227
229
  Use `primitive signup <email>` for new account creation, then `primitive signup confirm <email> <code>` with the emailed verification code. Non-interactive signup is available with `--accept-terms`.
228
230
 
231
+ ### Switching organizations
232
+
233
+ Where the server supports it, browser login (`primitive login` with no email) logs you in as yourself rather than into one organization. The organization you choose in the browser becomes the current one, and you can switch without logging in again:
234
+
235
+ ```bash
236
+ primitive orgs # your organizations, your role, and whether the CLI may be used there
237
+ primitive org use acme # switch by name or id
238
+ primitive emails list --org beta # act in another organization for one command
239
+ ```
240
+
241
+ `--org` works on every command (set `PRIMITIVE_CLI_ORG` for the same effect; `primitive memories` keeps its own `--org` flag for organization-scoped memories). Each organization decides who may use the CLI there; when it refuses, `primitive orgs` and `primitive org use` show the reason (`not_a_member`, `cli_access_disabled_by_org`, `role_insufficient` or `cli_access_revoked`). The CLI keeps a short-lived access token per organization and gets a new one when it expires or is rejected. `primitive logout` signs you out of every organization.
242
+
243
+ Against a server without organization switching, and for logins saved by earlier CLI versions, the login stays bound to one organization and works as before. `--org` naming a different organization is refused for such a login, for an API key and for a connected agent profile.
244
+
245
+ `primitive login --permission <permission>` asks for a narrowed login. A server that does not offer narrowed CLI logins refuses it, and the CLI stops rather than logging in with a wider grant.
246
+
247
+ ### Grants and keys
248
+
249
+ `primitive whoami` shows your organization, role and grant when the server reports them. `primitive whoami --check mail:send` asks whether the current credential may use a permission, prints the decision, and exits 1 when it may not; nothing is enforced by asking. A request refused because the credential's grant lacks a permission fails with `grant_forbidden`, and the CLI names the permission.
250
+
251
+ ```bash
252
+ primitive keys list
253
+ primitive keys list --json
254
+ ```
255
+
256
+ `keys list` shows each key's id, prefix, name, grant, expiry and last use. It never shows a secret. API keys are created, rotated and revoked in the dashboard for now. CLI commands for this are planned. `keys list` uses the credential inventory, which the server answers only for an owner or admin in a dashboard session, so from the CLI it shows the server's refusal.
257
+
258
+ `primitive roles list`, `primitive roles groups`, `primitive roles mailbox-access` and `primitive roles access-mode` read roles, groups, mailbox access and the access mode. Where the server has not enabled them, they print `feature_disabled`. The built-in roles are `owner`, `admin`, `operator` and `member`. `operator` has every permission `admin` has except managing members, changing roles, sending invitations and billing. By default, owners, admins and operators may use the CLI. An organization can open it to every member by setting `cli_access` to `all_members` in its credential policy.
259
+
260
+ ### Trying the preview
261
+
262
+ Install the 3.0.0 preview with `npm install -g primitive@preview`. `npm install -g primitive` stays on the latest stable version.
263
+
264
+ ### Downgrading after signing in as yourself
265
+
266
+ A login as yourself is saved with `auth_method: "user_grant"`, which CLI 1.75.0 and earlier cannot read: every command there fails with `Stored Primitive CLI credentials are malformed`. Run `primitive logout` with this CLI before installing an older one. If you have already downgraded, `primitive logout` removes the local file but does not revoke the login on the server, so sign in again afterwards.
267
+
229
268
  ## Reply state and the agent loop
230
269
 
231
270
  Every inbound email carries reply state: `awaiting` is `you` when the latest
@@ -315,6 +354,7 @@ primitive emails get --id <inbound-email-id> --compact
315
354
  primitive sent list
316
355
  primitive sent delete --id <sent-email-id>
317
356
  primitive domains list
357
+ primitive billing
318
358
  primitive functions templates
319
359
  primitive functions init my-fn --template email-reply
320
360
  primitive functions logs --id <function-id>
@@ -427,8 +467,8 @@ signal or interaction, so two agents cannot keep acknowledging each other.
427
467
  acknowledgement for a message identified by its Message-Id.
428
468
 
429
469
  A plain `primitive reply` to an email the server classifies as an interaction
430
- the reply does not complete (a payment or contact request, or a kind this CLI
431
- cannot answer), or to informational mail or a status signal, is still sent.
470
+ the reply does not complete (a contact request, or a kind this CLI cannot
471
+ answer), or to informational mail or a status signal, is still sent.
432
472
  Without `--json` one `Warning:` line on stderr names the command that answers
433
473
  it; with `--json` the envelope carries `interaction_warning` (`code`,
434
474
  `email_id`, `kind`, `category`, `message`, `expected`), null otherwise.
@@ -629,65 +669,79 @@ primitive routes remove <route-id>
629
669
  Recipient routing is gated by an organization entitlement; routes are inert
630
670
  until it is enabled.
631
671
 
632
- ## x402 payments
633
-
634
- The `primitive payments` command group drives non-custodial x402 USDC payments. One agent registers a payout address and requests a payment; the paying agent signs locally with its own wallet key and settles. The key never leaves your machine. Networks are `base` and `base-sepolia`. Amounts take a human USDC value (`--amount-usdc 0.01`) or token base units (`--amount 10000`, since USDC has 6 decimals). Your org is resolved automatically from your API key, so payout registration takes no org flag.
635
-
636
- ```bash
637
- # Payee, one time: register the default address your org is paid at. Signs an
638
- # ownership message locally with your wallet key. Org is auto-resolved.
639
- primitive payments register-payout-address --network base-sepolia --label treasury
640
-
641
- # Payee: request a payment with a human USDC amount. Prints the challenge JSON
642
- # to stdout; a one-line summary goes to stderr.
643
- primitive payments charge --network base-sepolia --amount-usdc 0.01
644
- # Capture the challenge JSON to hand to the payer.
645
- primitive payments charge --network base-sepolia --amount-usdc 0.01 > challenge.json
646
-
647
- # Payer: sign and settle the challenge locally. Reads the challenge inline,
648
- # from a file, or piped on stdin.
649
- primitive payments pay --challenge-file challenge.json
650
- cat challenge.json | primitive payments pay
651
-
652
- # Email-native flow: the payee issues a challenge over an email thread.
653
- # Note: create-email-challenge takes --amount in token base units only; unlike
654
- # `charge` it has no --amount-usdc. USDC has 6 decimals, so multiply by
655
- # 1,000,000: 0.01 USDC is --amount 10000.
656
- primitive payments create-email-challenge --from payee@your-domain.example \
657
- --to payer@their-domain.example --amount 10000 --network base-sepolia
658
- # Payer (recommended): pay the email challenge in one step. Signs the challenge
659
- # locally with your wallet key AND sends the signed interaction.json, so you
660
- # skip the manual sign-then-send dance. --in-reply-to is the inbound challenge
661
- # email you received; it is fetched to address the payment to the payee, with
662
- # From defaulting to the payer it was sent to. The send is not threaded under
663
- # the challenge (the payment associates by interaction_id). The message carries
664
- # a short default note alongside the attachment; pass --body to customize it.
665
- primitive payments pay-email --challenge-file challenge.json \
666
- --in-reply-to <inbound-challenge-email-id> --wait
667
-
668
- # Advanced: sign only, without sending. Emits the portable interaction.json
669
- # artifact you can attach yourself (e.g. with `primitive send --attachment`).
670
- primitive payments pay-email-step --challenge-file challenge.json > interaction.json
671
-
672
- # Inspect a challenge by id, or list your registered payout addresses.
673
- primitive payments get-challenge --id <challenge-id>
674
- primitive payments list-payout-addresses
675
-
676
- # Read and update the org spend policy (kill-switch, per-payment and daily caps,
677
- # payee allowlist). The update merges: omitted fields keep their value.
678
- primitive payments get-spend-policy
679
- primitive payments update-spend-policy --max-per-payment 5000000
680
- ```
681
-
682
- `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.
683
-
684
- 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:
685
-
686
- ```bash
687
- export PRIMITIVE_X402_PRIVATE_KEY=0x...
672
+ ## Supported receiver API
673
+
674
+ A receiver in a coding harness that the CLI does not support must decide
675
+ which received emails may wake its session. `primitive/receiver` exposes the
676
+ CLI's own contact admission policy for that decision. It is the only
677
+ supported library import from this package.
678
+
679
+ ```ts
680
+ import { createWakePolicy, WakePolicyError } from "primitive/receiver";
681
+
682
+ const policy = createWakePolicy({
683
+ recipient: "agent@example.com",
684
+ contactRequests: false,
685
+ readContactPolicy: (signal) => readPolicy(signal),
686
+ readContactPage: (cursor, signal) => readContacts(cursor, signal),
687
+ readNetworkAdmission: (emailId, sender, signal) =>
688
+ checkNetworkAdmission(emailId, sender, signal),
689
+ });
690
+
691
+ const decision = await policy.admit({ emailId, sender, receivedAt }, signal);
692
+ if (decision.kind !== "denied") {
693
+ const confirm = await policy.recheck(decision, signal);
694
+ confirm(); // immediately before the wake
695
+ wake(decision.kind === "request" ? "contact request" : "mail");
696
+ }
688
697
  ```
689
698
 
690
- 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.
699
+ The three readers call the API as the connected address. Each returns the
700
+ `data` of one operation:
701
+
702
+ | Reader | API operation | CLI command |
703
+ | --- | --- | --- |
704
+ | `readContactPolicy` | `getAgentContactPolicy` | `primitive contacts get-agent-contact-policy` |
705
+ | `readContactPage` | `listAgentContacts`, 100 rows per page, with the next `cursor` or `null` | `primitive agent contacts list` |
706
+ | `readNetworkAdmission` | `checkDefaultNetworkContactAdmission` | `primitive agent-networks check-default-network-contact-admission` |
707
+
708
+ `admit` returns one of three decisions for an email:
709
+
710
+ - `allowed`: the email may wake the session.
711
+ - `request`: a first-contact request from an unknown sender. It is returned
712
+ only when `contactRequests` is true and the owner allows contact requests.
713
+ Show it as a request, never as a task. Allow at most one per sender.
714
+ - `denied`: the email must not wake the session.
715
+
716
+ An admission carries the email ID, sender and received time, normalized to
717
+ lower case and ISO 8601. Pass the sender only after you check that it is
718
+ authenticated.
719
+
720
+ Permission can change between admission and wake. Call `recheck` with the
721
+ admission that `admit` returned, then call the function it returns
722
+ synchronously right before the wake. That function throws when the
723
+ permission was refreshed since, or when the policy read behind it is older
724
+ than 30 seconds. Admissions are bound to the policy that issued them, so
725
+ `recheck` rejects any other object with a `TypeError`.
726
+
727
+ Failures are `WakePolicyError` values. Branch on `code`:
728
+
729
+ | `code` | `retryable` | Meaning |
730
+ | --- | --- | --- |
731
+ | `policy_read_failed` | true | A policy read failed temporarily. The policy paces repeated reads itself. |
732
+ | `network_admission_pending` | true | The server has not settled network admission for this email. Retry in a few seconds. |
733
+ | `permission_changed` | true | Permission changed or expired before the wake. Admit the email again. |
734
+ | `policy_unavailable` | false | The policy is invalid or access was lost. Retrying will not help until access is restored. |
735
+
736
+ A reader reports a temporary failure, such as a rate limit, a 5xx response
737
+ or a dropped connection, by throwing `new WakePolicyError("policy_read_failed")`.
738
+ Any other error from a reader makes the policy unavailable. An aborted signal
739
+ rejects with the signal's reason.
740
+
741
+ The package also resolves `primitive/bin/*`, `primitive/dist/*` and
742
+ `primitive/man/*` so existing deep imports keep working. Those paths are not
743
+ supported. File names under `dist/` other than `dist/receiver.js` change
744
+ between releases, and the paths may stop resolving in a later major version.
691
745
 
692
746
  ## Migrating from `@primitivedotdev/sdk` CLI
693
747
 
@@ -852,9 +906,11 @@ policy CLI commands, explicit `--notify` consent, and recovery.
852
906
 
853
907
  ### Agent address notes
854
908
 
855
- Connected profiles default to their own address. They can read another address's
856
- organization notes with `--address`, but can write only their own, and the
857
- server refuses note deletion from a connected-agent credential.
909
+ Connected profiles default to their own address. With `--address` they can
910
+ read the `AGENT_INFO`, `AGENT_WORKING` and `AGENT_RUNTIME` notes of another
911
+ agent in their organization; the server returns 403 for any other note there
912
+ and leaves those notes out of `list`. They can write only their own notes, and
913
+ the server refuses note deletion from a connected-agent credential.
858
914
  Owner logins must pass `--address`.
859
915
 
860
916
  ```sh
@@ -1011,6 +1067,14 @@ one JSON result:
1011
1067
  npx -y primitive@latest agent connect --session "$CODEX_THREAD_ID" --name Research --info "Reviews pull requests" --contact-requests --json < private-invitation.txt
1012
1068
  ```
1013
1069
 
1070
+ `--session auto` reads the session from the runtime instead, so one command
1071
+ works in any harness: `CLAUDE_CODE_SESSION_ID` in Claude Code, or
1072
+ `CODEX_THREAD_ID` then `CODEX_SESSION_ID` in Codex. The result's
1073
+ `sessionDetection` names what it found. With no session in the environment it
1074
+ connects with poll receiving and reports `sessionDetection.state`
1075
+ `not_detected`; when both runtimes name a session it fails before reading
1076
+ stdin, and the session must be passed explicitly.
1077
+
1014
1078
  The receiver defaults to the exact Claude session's hooks in Claude Code and to
1015
1079
  the supervised native background listener elsewhere; native receiving waits
1016
1080
  briefly for the listener's first mail check. The profile defaults to
@@ -1089,8 +1153,9 @@ with status `ok`, `warn`, `fail` or `skip`; `action` (`login`, `install_cli`,
1089
1153
  `{version: 1, cliVersion, checks, summary: {ok, warn, fail, skip}, fixedCount}`
1090
1154
  and the command exits 0 only when every check is ok or skipped. Checks cover
1091
1155
  the CLI install, version (`--min-cli-version` sets a floor) and location, the
1092
- saved member login, Claude `settings.json`, Primitive's Claude SessionStart,
1093
- SessionEnd and receive hooks (each present once, pointing at this CLI, with
1156
+ saved member login, which coding agent harnesses are installed, Claude
1157
+ `settings.json`, Primitive's Claude SessionStart, SessionEnd and receive hooks
1158
+ (each present once, pointing at this CLI, with
1094
1159
  stale copies from older installs removed), the Codex SessionStart hook
1095
1160
  in `$CODEX_HOME/hooks.json` (repaired in place without moving any other hook,
1096
1161
  since Codex keys approvals by hook position, and reported as `warn` until the
@@ -1100,6 +1165,19 @@ content) and `~/.omp/agent/AGENTS.md`, the bundled primitive-connect skill, and
1100
1165
  saved agent profiles that were disconnected in Primitive (moved aside locally;
1101
1166
  nothing changes server side).
1102
1167
 
1168
+ `claude.installed`, `codex.installed` and `omp.installed` report each supported
1169
+ harness. A harness counts as installed when its config directory exists
1170
+ (`$CLAUDE_CONFIG_DIR` or `~/.claude`, `$CODEX_HOME` or `~/.codex`,
1171
+ `$PI_CONFIG_DIR` or `~/.omp`) or its binary (`claude`, `codex`, `omp`) is on
1172
+ PATH. One that is not installed is reported as `skip` with `installed: false`,
1173
+ its setup checks are skipped too, and `--fix` writes nothing for it. One that
1174
+ is installed is reported as `ok` with `installed: true` and `setup`:
1175
+ `present` when its setup checks pass, `incomplete` when any of them warns or
1176
+ fails (the detail names them; those checks carry the failure, so this one does
1177
+ not change the exit code), or `not_used` when all of them are skipped, as on a
1178
+ machine whose agents connect per session. These checks read only and are never
1179
+ fixable.
1180
+
1103
1181
  Claude receives mail through one shared set of receive hooks per config
1104
1182
  directory (`Stop`, `SessionStart` on resume, and `PostToolUse`). Each run reads
1105
1183
  the session id from the hook input and looks up the profiles that session
@@ -1233,6 +1311,10 @@ can see the network; explicit silence still applies. Network visibility permits
1233
1311
  discovery and communication but does not grant task authority.
1234
1312
  Known addresses can still exchange ordinary email outside the network.
1235
1313
 
1314
+ From a connected profile, the notes of another agent in the organization are
1315
+ limited to `AGENT_INFO`, `AGENT_WORKING` and `AGENT_RUNTIME`. Other notes there
1316
+ return 403 and are left out of list reads.
1317
+
1236
1318
  With a signed-in member login, `primitive network members` shows your own
1237
1319
  personal agents. Use `primitive network set <address> --see off` to stop one of
1238
1320
  them browsing, or `--be-seen off` to hide it from discovery. Owners and admins
@@ -1329,7 +1411,6 @@ untrusted content names the command:
1329
1411
 
1330
1412
  | Server classification | `how to answer` |
1331
1413
  |---|---|
1332
- | `x402.payment/1` | `primitive payments challenge-from-email --id <id>` to review, `primitive payments pay-email --in-reply-to <id>` to pay |
1333
1414
  | `primitive.contact/1` | `primitive contacts accept --id <id>` |
1334
1415
  | `repeat.tick/1` | reply if needed; `primitive repeat stop --id <id>` once its goal is met |
1335
1416
  | `repeat.stop/1`, status signals, `fyi` | no reply needed |
@@ -1342,7 +1423,7 @@ When the server classifies the email as an interaction, its `interaction.json`
1342
1423
  part is left out of the attachment list. `primitive inbox next` carries the
1343
1424
  same `interaction` and `next_actions` in its JSON envelope, prints the same
1344
1425
  line above the conversation, and ends with matching instructions: the answering
1345
- command first for payment and contact requests (a reply only as optional), "No
1426
+ command first for contact requests (a reply only as optional), "No
1346
1427
  reply needed." for fyi mail, signals and repeat-stopped notices, and the stop
1347
1428
  command for a repeat only when the recipient may stop it. `inbox next` skips
1348
1429
  mail that needs no reply (fyi mail, status signals, repeat-stopped notices):
@@ -1421,6 +1502,18 @@ profile. `unmute` removes the server mute and the matching local one, and
1421
1502
  thread is still received and readable; its delivery event is completed without
1422
1503
  a wake.
1423
1504
 
1505
+ Group email follows a mention rule. When an email names this agent and at
1506
+ least one other address in To or Cc, and its new text mentions any of those
1507
+ addresses, only the mentioned agents are woken. A mention is `@` and the
1508
+ address's local part (`@reviewer`) or the full address
1509
+ (`reviewer@agents.example.com`), matched case-insensitively and only as a whole
1510
+ handle or address, so `@reviewer` does not match `@reviewer2`. Quoted history
1511
+ and quoted (`>`) lines are ignored, so an earlier message's mention does not
1512
+ count again, and addresses the email was not sent to are ignored. A local part
1513
+ shared by two recipients mentions both. Group email that mentions none of its recipients wakes every
1514
+ recipient as before, and email addressed to one agent alone always wakes it.
1515
+ Like a muted thread, mail that skips the wake is still received and readable.
1516
+
1424
1517
  When an email read carries the server's `collaboration.sender_relationship`,
1425
1518
  the wake line and `--context` use it for an authenticated sender, `other`
1426
1519
  included (`org_agent` reads as `agent`); only when the field is absent or
@@ -200,7 +200,7 @@ export const WAKE_SENTENCES = {
200
200
  export function wakeSentence(label) {
201
201
  if (label === "fyi" || label === "repeat.stop/1")
202
202
  return WAKE_SENTENCES.no_reply;
203
- if (label === "x402.payment/1" || label === "primitive.contact/1")
203
+ if (label === "primitive.contact/1")
204
204
  return WAKE_SENTENCES.answer_with_command;
205
205
  if (label === "repeat.tick/1") return WAKE_SENTENCES.repeat;
206
206
  return WAKE_SENTENCES.unsupported;
package/bin/run.js CHANGED
@@ -72,5 +72,19 @@ const { writeRootAuthContextIfNeeded } = await import(
72
72
  );
73
73
  await writeRootAuthContextIfNeeded();
74
74
 
75
+ // `--org <org>` works on every command: take it out of argv before oclif
76
+ // parses the command, and pass it on as PRIMITIVE_CLI_ORG. Applied last, so
77
+ // the detached receiver and signal workers started above never inherit it.
78
+ {
79
+ const { applyGlobalOrgFlag } = await import(
80
+ "../dist/oclif/global-org-flag.js"
81
+ );
82
+ const orgFlagError = applyGlobalOrgFlag();
83
+ if (orgFlagError) {
84
+ process.stderr.write(`${orgFlagError}\n`);
85
+ process.exit(2);
86
+ }
87
+ }
88
+
75
89
  const { execute } = await import("@oclif/core");
76
90
  await execute({ dir: import.meta.url });