@agentcomms/resend 0.13.0 → 0.13.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.
package/README.md CHANGED
@@ -17,9 +17,9 @@ code, but the key itself would not stop anything else that held it. A sending-on
17
17
  enforces that — and it cannot read anything, so reads with it are reported as unavailable. `agent-resend doctor`
18
18
  says this on every run.
19
19
 
20
- **Nothing is sent without a person.** A send is prepared, previewed — every recipient, BCC included, the reach
21
- (unique recipients), the From domain and whether it is verified — and approved: a yes in the conversation under the
22
- account's `chat` policy, or `agent-resend approve <id>` and a typed code under `confirm`. Above ten recipients, or to
20
+ **Nothing is sent without a person.** A send is prepared, previewed — every recipient, BCC included, the reach (unique
21
+ recipients), the From domain and whether it is verified — and approved: a yes in the conversation under the account's
22
+ `chat` policy, or the approve command the result gives and a typed code under `confirm`. Above ten recipients, or to
23
23
  an address that arrived in mail read here, a person at a terminal approves, whatever the policy. The approval id is
24
24
  the request's `Idempotency-Key` and an `agentcomms_approval` tag; a send whose outcome is unknown is never repeated,
25
25
  only checked.
@@ -98,7 +98,7 @@ terminal), `approve` (under `confirm`, a person at a terminal) and `mcp` (it sta
98
98
  | `agent-resend send status <approvalId>` | `resend_send_status` |
99
99
  | `agent-resend scheduled list` | `resend_scheduled_list` |
100
100
  | `agent-resend scheduled cancel <id>` | `resend_scheduled_cancel` |
101
- | `agent-resend approve <approvalId>` | — a person at a terminal |
101
+ | `agent-resend approve <approvalId>` | — a person at a terminal, with the command the result gives |
102
102
  | `agent-resend mcp` | — it starts the server |
103
103
  | `agent-resend mcp install --client <client>` | `comms_server_install` (core) |
104
104
  | `agent-resend mcp prune` | `comms_server_prune` (core) |
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as inlineCommand, B as agentMarker, C as policyChange, D as sendPolicyOf, E as removeAccountChange, F as CHANNEL_SERVERS, H as approvalsOf, I as CommsError, J as commandPathOf, L as EXIT_CODES, N as checkNewName, O as showAccount, Q as gatedChangeAtTerminal, R as SEND_LOOKUP, S as policyApprovalRefusal, T as policyWanted, U as approveChangeAtTerminal, V as approvalKind, W as canPrompt, X as exemptFromUpdateGate, Y as escapeForDisplay, _ as runDoctor, a as revokeSendApproval, at as renderPrune, b as listAccounts, c as downloadReceived, ct as serverInstallChange, d as listReceived, dt as terminalUpdateHooks, et as installExitStatus, f as listScheduled, g as showSentEmail, gt as writeResult, h as showReceived, i as prepareSend, it as renderInstall, k as ResendContext, l as getMetrics, lt as serverPruneChange, m as listSuppressions, mt as updateGateAtTerminal, n as executeSend, nt as paint, o as sendStatus, ot as runCommand, p as listSentEmails, pt as truncateDisplay, q as colorEnabled, r as finishSendApproval, rt as refuseUnclaimedApproval, s as cancelScheduledChange, st as runUpdateCheckChild, t as beginSendApproval, tt as openCore, u as listDomains, ut as shellCommand, v as addAccountChange, w as policyReport, x as modeOf, xt as VERSION, y as inspectKey, z as UPDATE_CHECK_CHILD_COMMAND } from "./send-D2ZOWO_6.mjs";
2
+ import { B as UPDATE_CHECK_CHILD_COMMAND, C as policyChange, D as sendPolicyOf, Dt as VERSION, E as removeAccountChange, F as CHANNEL_SERVERS, G as canPrompt, H as approvalKind, I as CommsError, J as cliHandoffs, L as EXIT_CODES, N as checkNewName, O as showAccount, Q as exemptFromUpdateGate, R as PATH_OPTIONS, S as policyApprovalRefusal, St as RESEND_CALLER, T as policyWanted, U as approvalsOf, V as agentMarker, W as approveChangeAtTerminal, X as commandPathOf, Y as colorEnabled, Z as escapeForDisplay, _ as runDoctor, _t as truncateDisplay, a as revokeSendApproval, at as paint, b as listAccounts, bt as writeResult, c as downloadReceived, ct as renderInstall, d as listReceived, dt as runCommand, et as gatedChangeAtTerminal, f as listScheduled, ft as runUpdateCheckChild, g as showSentEmail, h as showReceived, ht as terminalUpdateHooks, i as prepareSend, it as openCore, k as ResendContext, l as getMetrics, lt as renderPrune, m as listSuppressions, mt as serverPruneChange, n as executeSend, nt as handoffSentenceToFill, o as sendStatus, ot as pathOverridesFromCliOptions, p as listSentEmails, pt as serverInstallChange, r as finishSendApproval, rt as installExitStatus, s as cancelScheduledChange, st as refuseUnclaimedApproval, t as beginSendApproval, tt as handoffSentence, u as listDomains, ut as resolvePaths, v as addAccountChange, vt as updateGateAtTerminal, w as policyReport, x as modeOf, y as inspectKey, z as SEND_LOOKUP } from "./send-DtBNDnE4.mjs";
3
3
  import path from "node:path";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { stripVTControlCharacters } from "node:util";
@@ -3040,12 +3040,12 @@ const KEY_SHAPE = /^re_[A-Za-z0-9_]{8,200}$/;
3040
3040
  async function readApiKey(env, streams, options) {
3041
3041
  const marker = agentMarker(env);
3042
3042
  if (marker) throw new CommsError("AUTH_REQUIRED", "a Resend API key is added by a person at their own terminal, not by an agent", {
3043
- hint: `Ask the user to run ${inlineCommand(options.command)} in their own terminal. Never paste a key into a chat: the transcript keeps it.`,
3043
+ hint: `${handoffSentence(options.command, (command) => `Ask the user to run ${command} in their own terminal.`)} Never paste a key into a chat: the transcript keeps it.`,
3044
3044
  details: { marker }
3045
3045
  });
3046
3046
  let key = env["RESEND_API_KEY"]?.trim() ?? "";
3047
3047
  if (key === "") {
3048
- if (!canPrompt(env, streams, { json: options.json })) throw new CommsError("AUTH_REQUIRED", "a Resend API key is needed, and there is no terminal to ask for it", { hint: `A person runs ${inlineCommand(options.command)} in a terminal, which asks for the key without showing it, or sets ${KEY_ENV} for that one command.` });
3048
+ if (!canPrompt(env, streams, { json: options.json })) throw new CommsError("AUTH_REQUIRED", "a Resend API key is needed, and there is no terminal to ask for it", { hint: handoffSentence(options.command, (command) => `A person runs ${command} in a terminal, which asks for the key without showing it, or sets ${KEY_ENV} for that one command.`) });
3049
3049
  key = (await askHidden(streams, "Resend API key (https://resend.com/api-keys; it is not shown as you type): ")).trim();
3050
3050
  }
3051
3051
  if (!KEY_SHAPE.test(key)) throw new CommsError("BAD_DATA", "that does not look like a Resend API key (they start with re_)", { hint: "Nothing was stored. Copy the key again from the Resend dashboard." });
@@ -3069,8 +3069,9 @@ function renderAccount(view, color) {
3069
3069
  ` ${view.guarantee}`
3070
3070
  ].join("\n");
3071
3071
  }
3072
- function renderAccounts(result, color) {
3073
- if (result.accounts.length === 0) return "No Resend account yet. A person adds one with `agent-resend account add <org/resend>`.";
3072
+ /** The accounts; with none, how a person adds one — this installation's own command, `handoffs`'s, or why there is none. */
3073
+ function renderAccounts(result, color, handoffs) {
3074
+ if (result.accounts.length === 0) return handoffSentenceToFill(handoffs.own(["account", "add"]), ["<org/resend>"], (command) => `No Resend account yet. A person adds one with ${command}.`, { instead: "No Resend account yet." });
3074
3075
  return result.accounts.map((view) => renderAccount(view, color)).join("\n\n");
3075
3076
  }
3076
3077
  function renderAdded(view, color) {
@@ -3131,6 +3132,17 @@ function withoutOptionValues(text) {
3131
3132
  return text.replace(/'(-{1,2}[^'=\s]+)=[^']*'/g, "'$1=…'").replace(/\bre_[A-Za-z0-9_]{4,}/g, "re_…");
3132
3133
  }
3133
3134
  const collect = (value, previous = []) => [...previous, value];
3135
+ /** What a usage error tells the person: this installation's own `--help`, located — or why there is none here. */
3136
+ function usageHint(help) {
3137
+ return handoffSentence(help, (command) => `Run ${command} to see the commands.`);
3138
+ }
3139
+ /**
3140
+ * What a command line that ran nothing says. Commander shows the help for an empty one itself, so this is the fallback
3141
+ * for a parse that ends with no command run and no error — never a bare name either way.
3142
+ */
3143
+ function nothingToDo(help) {
3144
+ return handoffSentence(help, (command) => `Nothing to do. Try ${command}.`);
3145
+ }
3134
3146
  /** `--expect-to a@x.test,b@x.test`, or `none`: a list is always written out, so a permission prompt shows it. */
3135
3147
  function expectList(raw, flag) {
3136
3148
  const value = String(raw ?? "").trim();
@@ -3155,17 +3167,44 @@ async function run(argv, deps = {}) {
3155
3167
  writeErr: (text) => streams.stderr.write(text),
3156
3168
  outputError: (text, write) => write(withoutOptionValues(text))
3157
3169
  }).addHelpText("after", `
3158
- Getting started:
3159
- agent-resend account add acme/resend a person types the key; it goes into the keychain
3160
- agent-resend doctor what works, and who enforces what
3161
- agent-resend domains --account acme/resend
3162
- agent-resend received list --account acme/resend
3163
- agent-resend mcp install --client claude-code register the server with an agent, once a person approves it
3170
+ Getting started — run these with this CLI:
3171
+ account add acme/resend a person types the key; it goes into the keychain
3172
+ doctor what works, and who enforces what
3173
+ domains --account acme/resend
3174
+ received list --account acme/resend
3175
+ mcp install --client claude-code register the server with an agent, once a person approves it
3164
3176
 
3165
3177
  Exit codes: 0 ok · 1 unexpected · 10 a send or a change was refused or needs approval · 11 an update
3166
- is out: update first, or put it off (agentcomms update, agentcomms update --later) · 64 usage ·
3178
+ is out: update first, or put it off (the stop names both commands) · 64 usage ·
3167
3179
  65 bad data · 66 not found · 69 provider or secret store unavailable · 75 temporary (retry later) ·
3168
3180
  77 key or permission needed · 78 configuration problem.`).exitOverride();
3181
+ for (const { flag } of PATH_OPTIONS) program.addOption(new Option(`${flag} <dir>`, "pin this suite directory for this run").argParser((value) => {
3182
+ if (value.length === 0) throw new InvalidArgumentError(`${flag} needs a non-empty directory`);
3183
+ return value;
3184
+ }));
3185
+ let invocationCore;
3186
+ const coreForInvocation = () => {
3187
+ if (invocationCore) return invocationCore;
3188
+ const options = program.opts();
3189
+ const pathOverrides = pathOverridesFromCliOptions(Object.fromEntries(PATH_OPTIONS.map(({ key, option }) => [option, options[key]])));
3190
+ invocationCore = Object.keys(pathOverrides).length === 0 && deps.core ? deps.core : openCore({
3191
+ env,
3192
+ platform,
3193
+ pathOverrides,
3194
+ caller: RESEND_CALLER
3195
+ });
3196
+ return invocationCore;
3197
+ };
3198
+ /** This installation's own `--help`, for a usage error or an empty command line: it opens no folder, so pins none. */
3199
+ const help = () => cliHandoffs({
3200
+ caller: RESEND_CALLER,
3201
+ paths: resolvePaths({
3202
+ env,
3203
+ platform
3204
+ }),
3205
+ platform,
3206
+ env
3207
+ }).own(["--help"], { uses: [] });
3169
3208
  const globals = () => {
3170
3209
  const options = program.opts();
3171
3210
  return {
@@ -3182,7 +3221,7 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3182
3221
  program.hook("preAction", async (_program, command) => {
3183
3222
  const path = commandPathOf(command);
3184
3223
  if (exemptFromUpdateGate(path, ["update-check-child"])) return;
3185
- const core = openCore({ env });
3224
+ const core = coreForInvocation();
3186
3225
  let ended = null;
3187
3226
  const code = await runCommand(output(), async () => {
3188
3227
  ended = await updateGateAtTerminal({
@@ -3194,13 +3233,11 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3194
3233
  output: output(),
3195
3234
  noInput: false,
3196
3235
  streams,
3197
- approveCommand: "agent-resend approve",
3198
3236
  approvals: approvalsOf(command),
3199
3237
  approvalClaim: path.join(" ") === "send status" ? SEND_LOOKUP : void 0,
3200
3238
  ...terminalUpdateHooks(core, env, {
3201
3239
  output: output(),
3202
- streams,
3203
- approveCommand: "agent-resend approve"
3240
+ streams
3204
3241
  })
3205
3242
  });
3206
3243
  }, streams);
@@ -3213,24 +3250,29 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3213
3250
  exitCode = gated;
3214
3251
  return;
3215
3252
  }
3253
+ const core = coreForInvocation();
3216
3254
  const context = new ResendContext({
3217
3255
  ...deps,
3256
+ core,
3218
3257
  env,
3258
+ pathOverrides: core.pathOverrides,
3219
3259
  surface: "cli"
3220
3260
  });
3221
3261
  exitCode = await runCommand(output(), () => body(context, globals(), ...args), streams);
3222
3262
  if (exitCode === 0 && softExit !== null) exitCode = softExit;
3223
3263
  };
3224
- /** A change the way every changing command runs one: core's `gatedChangeAtTerminal`. */
3225
- const changeAt = (context, change, flags, command) => gatedChangeAtTerminal(context.core, change, {
3264
+ /**
3265
+ * A change the way every changing command runs one: core's `gatedChangeAtTerminal`. `rerun` is this command's words
3266
+ * after the program, which core locates as Resend's own and runs again with `--approval <id>`.
3267
+ */
3268
+ const changeAt = (context, change, flags, rerun) => gatedChangeAtTerminal(context.core, change, {
3226
3269
  approvalId: flags.approval === void 0 ? void 0 : String(flags.approval),
3227
3270
  env,
3228
3271
  output: output(),
3229
- command,
3230
- approveCommand: "agent-resend approve",
3272
+ rerun,
3231
3273
  streams
3232
3274
  });
3233
- const approvalOption = (command) => command.option("--approval <approvalId>", "apply a change a person approved: said yes to in chat, or approved with `agent-resend approve`");
3275
+ const approvalOption = (command) => command.option("--approval <approvalId>", "apply a change a person approved: said yes to in chat, or approved with the approve command it gave");
3234
3276
  const accountOption = (command) => command.requiredOption("--account <name>", "which account, as `organisation/resend`");
3235
3277
  const account = program.command("account").description("connect, inspect, re-police and remove Resend accounts");
3236
3278
  approvalOption(account.command("add <name>").description("connect a Resend API key, typed by a person at this terminal (or RESEND_API_KEY); never from a chat").addOption(new Option("--mode <mode>", "read (the default for a full-access key) or send").choices(["read", "send"])).addOption(new Option("--send <policy>", "how its sends are approved; the machine default if left out").choices([
@@ -3239,19 +3281,18 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3239
3281
  "never"
3240
3282
  ])).option("--domain <domain>", "for a sending-only key restricted to one domain: that domain")).action(act(async (context, options, name, flags) => {
3241
3283
  const mode = modeOf(flags.mode);
3242
- const command = shellCommand([
3243
- "agent-resend",
3284
+ const rerun = [
3244
3285
  "account",
3245
3286
  "add",
3246
3287
  name,
3247
3288
  ...mode ? ["--mode", mode] : [],
3248
3289
  ...flags.send ? ["--send", String(flags.send)] : [],
3249
3290
  ...flags.domain ? ["--domain", String(flags.domain)] : []
3250
- ], platform);
3251
- checkNewName(await context.config(), name, context.platform);
3291
+ ];
3292
+ checkNewName(await context.config(), name, context.handoffs);
3252
3293
  const key = await readApiKey(env, streams, {
3253
3294
  json: options.json,
3254
- command
3295
+ command: context.handoffs.own(rerun)
3255
3296
  });
3256
3297
  const inspection = await inspectKey(context, key);
3257
3298
  const added = await changeAt(context, addAccountChange(context, {
@@ -3260,24 +3301,23 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3260
3301
  mode,
3261
3302
  sendPolicy: sendPolicyOf(flags.send),
3262
3303
  domain: flags.domain === void 0 ? void 0 : String(flags.domain)
3263
- }, inspection), flags, command);
3304
+ }, inspection), flags, rerun);
3264
3305
  writeResult(added, output(), (data) => renderAdded(data, options.color), streams);
3265
3306
  }));
3266
3307
  account.command("list").description("the Resend accounts this machine can use, and what each may do").action(act(async (context, options) => {
3267
3308
  const result = await listAccounts(context);
3268
- writeResult(result, output(), (data) => renderAccounts(data, options.color), streams);
3309
+ writeResult(result, output(), (data) => renderAccounts(data, options.color, context.handoffs), streams);
3269
3310
  }));
3270
3311
  account.command("show <name>").description("one account: its key’s permission, its mode, its send policy, and who enforces what").action(act(async (context, options, name) => {
3271
3312
  const result = await showAccount(context, name);
3272
3313
  writeResult(result, output(), (data) => renderAccount(data, options.color), streams);
3273
3314
  }));
3274
3315
  approvalOption(account.command("remove <name>").description("forget an account and delete its key, once a person approves it")).action(act(async (context, _options, name, flags) => {
3275
- const removed = await changeAt(context, removeAccountChange(context, name), flags, shellCommand([
3276
- "agent-resend",
3316
+ const removed = await changeAt(context, removeAccountChange(context, name), flags, [
3277
3317
  "account",
3278
3318
  "remove",
3279
3319
  name
3280
- ], platform));
3320
+ ]);
3281
3321
  writeResult(removed, output(), renderRemoved, streams);
3282
3322
  }));
3283
3323
  approvalOption(account.command("policy <name>").description("report how its sends and changes are approved, or set --send, --mode and --change; loosening is approved by a person").option("--send <policy>", "chat, confirm or never").option("--mode <mode>", "read or send").option("--change <policy>", "how a loosening of this account is approved: chat or confirm")).action(act(async (context, _options, name, flags) => {
@@ -3288,15 +3328,14 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3288
3328
  });
3289
3329
  const reporting = wanted.send === void 0 && wanted.mode === void 0 && wanted.change === void 0;
3290
3330
  if (reporting) refuseUnclaimedApproval(flags.approval, policyApprovalRefusal("cli"));
3291
- const result = reporting ? await policyReport(context, name) : await changeAt(context, policyChange(context, name, wanted), flags, shellCommand([
3292
- "agent-resend",
3331
+ const result = reporting ? await policyReport(context, name) : await changeAt(context, policyChange(context, name, wanted), flags, [
3293
3332
  "account",
3294
3333
  "policy",
3295
3334
  name,
3296
3335
  ...wanted.send ? ["--send", wanted.send] : [],
3297
3336
  ...wanted.mode ? ["--mode", wanted.mode] : [],
3298
3337
  ...wanted.change ? ["--change", wanted.change] : []
3299
- ], platform));
3338
+ ]);
3300
3339
  writeResult(result, output(), renderPolicy, streams);
3301
3340
  }));
3302
3341
  program.command("doctor").description("check what has to work, and say who enforces what — read-only is this package’s promise, not the key’s").option("--account <name>", "check only this account").option("--offline", "do not ask Resend anything", false).action(act(async (context, options, flags) => {
@@ -3397,31 +3436,23 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3397
3436
  writeResult(result, output(), (data) => renderRead(data, options.color), streams);
3398
3437
  }));
3399
3438
  approvalOption(accountOption(scheduled.command("cancel <id>")).description("cancel a scheduled email; one this machine did not schedule is approved by a person first")).action(act(async (context, _options, id, flags) => {
3400
- const cancelled = await changeAt(context, cancelScheduledChange(context, String(flags.account), id), flags, shellCommand([
3401
- "agent-resend",
3439
+ const cancelled = await changeAt(context, cancelScheduledChange(context, String(flags.account), id), flags, [
3402
3440
  "scheduled",
3403
3441
  "cancel",
3404
3442
  id,
3405
3443
  "--account",
3406
3444
  String(flags.account)
3407
- ], platform));
3445
+ ]);
3408
3446
  writeResult(cancelled, output(), renderCancelled, streams);
3409
3447
  }));
3410
3448
  program.command("approve <approvalId>").description("approve a send or a change at this terminal: read it, then type the code back").action(act(async (context, options, approvalId) => {
3411
3449
  const marker = agentMarker(env);
3450
+ const approve = context.handoffs.own(["approve", approvalId]);
3412
3451
  if (marker) throw new CommsError("APPROVAL_REQUIRED", "only a person can approve a send or a change, not an agent", {
3413
- hint: `Ask the user to run ${inlineCommand(shellCommand([
3414
- "agent-resend",
3415
- "approve",
3416
- approvalId
3417
- ], context.platform))} in their own terminal.`,
3452
+ hint: handoffSentence(approve, (command) => `Ask the user to run ${command} in their own terminal.`),
3418
3453
  details: { marker }
3419
3454
  });
3420
- if (!canPrompt(env, streams, { json: options.json })) throw new CommsError("APPROVAL_REQUIRED", "approving needs an interactive terminal", { hint: `Run ${inlineCommand(shellCommand([
3421
- "agent-resend",
3422
- "approve",
3423
- approvalId
3424
- ], context.platform))} directly in a terminal.` });
3455
+ if (!canPrompt(env, streams, { json: options.json })) throw new CommsError("APPROVAL_REQUIRED", "approving needs an interactive terminal", { hint: handoffSentence(approve, (command) => `Run ${command} directly in a terminal.`) });
3425
3456
  const pending = await context.core.approvals.get(approvalId);
3426
3457
  if (pending && approvalKind(pending) === "change") {
3427
3458
  const outcome = await approveChangeAtTerminal(context.core, approvalId, env, {
@@ -3445,10 +3476,14 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3445
3476
  }));
3446
3477
  const mcp = program.command("mcp").description("run the MCP server on stdio, for a coding agent to connect to").option("--account <name>", "pin the server to one account; every tool then acts on it and no other").action(async (flags) => {
3447
3478
  ran = true;
3448
- const { startResendStdioServer } = await import("./stdio-entry-BCnq_EyF.mjs");
3479
+ const startResendStdioServer = deps.startMcp ?? (await import("./stdio-entry-CUFTANFM.mjs")).startResendStdioServer;
3480
+ const core = coreForInvocation();
3449
3481
  await startResendStdioServer({
3450
3482
  ...deps,
3483
+ core,
3451
3484
  env,
3485
+ pathOverrides: core.pathOverrides,
3486
+ platform,
3452
3487
  ...flags.account ? { account: String(flags.account) } : {}
3453
3488
  });
3454
3489
  });
@@ -3465,12 +3500,16 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3465
3500
  "npx",
3466
3501
  "local"
3467
3502
  ])).option("--no-verify", "do not start the server to check the entry works").option("--force", "replace this server's own earlier entry — this is how you upgrade", false).option("--print", "only print what would be written", false).option("--approval <approvalId>", "register the server this approval was given for").action(act(async (context, options, flags) => {
3468
- if (!flags.client) throw new CommsError("USAGE", "name the client with --client", { hint: "For example: `agent-resend mcp install --client claude-code`." });
3503
+ if (!flags.client) throw new CommsError("USAGE", "name the client with --client", { hint: handoffSentence(context.handoffs.own([
3504
+ "mcp",
3505
+ "install",
3506
+ "--client",
3507
+ "claude-code"
3508
+ ]), (command) => `For example: ${command}.`) });
3469
3509
  const pinned = flags.account ?? mcp.opts().account;
3470
3510
  const launcher = flags.launcher;
3471
3511
  const name = flags.name;
3472
- const again = shellCommand([
3473
- "agent-resend",
3512
+ const again = [
3474
3513
  "mcp",
3475
3514
  "install",
3476
3515
  "--client",
@@ -3480,7 +3519,7 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3480
3519
  ...launcher !== void 0 ? ["--launcher", launcher] : [],
3481
3520
  ...flags.verify === false ? ["--no-verify"] : [],
3482
3521
  ...flags.force === true ? ["--force"] : []
3483
- ], platform);
3522
+ ];
3484
3523
  const result = await changeAt(context, serverInstallChange(context.core, env, {
3485
3524
  channel: "resend",
3486
3525
  client: flags.client,
@@ -3500,12 +3539,11 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3500
3539
  channel: "resend",
3501
3540
  dryRun: flags.dryRun === true,
3502
3541
  includePrinted: flags.includePrinted === true
3503
- }, RESEND_MCP), flags, shellCommand([
3504
- "agent-resend",
3542
+ }, RESEND_MCP), flags, [
3505
3543
  "mcp",
3506
3544
  "prune",
3507
3545
  ...flags.includePrinted === true ? ["--include-printed"] : []
3508
- ], platform));
3546
+ ]);
3509
3547
  writeResult(result, output(), () => renderPrune(result, options.color), streams);
3510
3548
  }));
3511
3549
  program.command(`${UPDATE_CHECK_CHILD_COMMAND} <claimedAt>`, { hidden: true }).description("internal: finish the day's update check a command handed on").action(act(async (context, _options, claimedAt) => {
@@ -3522,13 +3560,13 @@ is out: update first, or put it off (agentcomms update, agentcomms update --late
3522
3560
  ].includes(error.code)) return 0;
3523
3561
  const message = withoutOptionValues(error.message.replace(/^error: /, ""));
3524
3562
  return runCommand(output(), async () => {
3525
- throw new CommsError("USAGE", message, { hint: "Run `agent-resend --help` to see the commands." });
3563
+ throw new CommsError("USAGE", message, { hint: usageHint(help()) });
3526
3564
  }, streams);
3527
3565
  }
3528
3566
  throw error;
3529
3567
  }
3530
3568
  if (!ran) {
3531
- streams.stderr.write(`${paint(globals().color, "dim", "Nothing to do. Try `agent-resend --help`.")}\n`);
3569
+ streams.stderr.write(`${paint(globals().color, "dim", nothingToDo(help()))}\n`);
3532
3570
  return 64;
3533
3571
  }
3534
3572
  return exitCode;