feat(inboxes): match the inbox commands to the stable Inboxes API

Merged
FE
16d ago
+2018-421

What broke in 2.25.0

The Inboxes API is now stable. Three commands of the released 2.25.0 fail against the live API.

  • inboxes agent get reads enabled_actions. The API now returns actions, so the interactive output crashes on .join.
  • inboxes agent update --enabled-actions sends enabled_actions. The API ignores it and returns 422.
  • inboxes threads update --add-label-ids and --remove-label-ids send fields that the API strips. The request returns 422.

This PR moves the CLI to resend@6.34.1 and matches every inbox command to the merged OpenAPI spec (resend-openapi#137).

Changes per command group

agent

  • agent get reads and prints actions.
  • agent update takes --actions and removes duplicate values. The values are archive and move_to_trash, not archive_thread and delete_thread. An old value fails with invalid_actions and names the new value.
  • --tone accepts only the four presets from INBOX_AGENT_TONES, or "" to clear it. Other text fails with invalid_tone (MES-2747).
  • The error code invalid_enabled_actions is now invalid_actions. The sibling codes (invalid_tone, invalid_limit, invalid_header) take the name of the flag.
  • main had no SDK bridge for actions. The bridge was only in the closed #417, so MES-2740 needs no code removal here.

threads labels (new)

  • threads labels add <inbox> <thread> --labels <ids...> calls POST /inboxes/{inbox_id}/threads/{thread_id}/labels.
  • threads labels set <inbox> <thread> --labels <ids...> calls PUT on the same path. --labels "" removes every label.
  • threads labels remove <inbox> <thread> <label> calls DELETE .../labels/{label_id}.
  • Each command calls one SDK method (resend.inboxes.threads.labels.add|set|remove) and outputs the label list of the thread.

threads

  • threads update takes only --read, --unread and --folder.
  • threads search drops highlights from help and from the table. The table shows matched_email_id, which is now the email ID that threads emails list returns.

Inbox ID or email address

  • Every command that names an inbox takes its ID or its email address. A value with @ goes to the SDK as emailAddress. Any other value goes as inboxId, like the MCP servers.
  • The help of every argument and --inbox-id flag says "Inbox UUID or email address".
  • inboxes delete prints the API result, so an address argument still prints the inbox UUID.

inboxes, drafts, attachments, keys

  • inboxes get and list help show created_at and updated_at. get prints both in interactive mode.
  • inboxes create help says the address cannot contain a +.
  • drafts update help shows the new output {"object":"inbox_draft","id":"<uuid>"}.
  • drafts create and drafts send help say a reply draft without a subject is sent with the thread subject and a Re: prefix.
  • threads emails reply and forward help state only the 25 MB attachment rule. The path rule now matches the API.
  • threads emails reply, threads emails forward, drafts create and drafts send accept a sending-access key. The other inbox commands still need full access. The interactive pickers list inboxes, threads or drafts, so a sending-access key must pass every ID.

Docs

  • README and skills/resend-cli/references/inboxes.md describe all of the above. The SKILL.md command table lists threads labels.

Compatibility

  • --enabled-actions and --enabled_actions stay as hidden aliases of --actions.
  • --add-label-ids, --remove-label-ids and their snake_case spellings stay as hidden flags. They fail with invalid_options and a message that names threads labels add, remove and set. The CLI does not drop them silently.
  • invalid_enabled_actions is now invalid_actions.
  • drafts update JSON output is now only object and id, because the API changed.

Checks

  • pnpm install --frozen-lockfile passes. resend is in minimumReleaseAgeExclude in pnpm-workspace.yaml, so 6.34.1 installs.
  • pnpm lint, pnpm typecheck, CI=true pnpm vitest run (1479 passed, 1 skipped) and pnpm build pass.
  • New tests assert the whole SDK payload for each new and changed command. tests/commands/inboxes/email-address.test.ts runs every inbox command with an address. tests/commands/inboxes/sending-access.test.ts checks the key access.
  • pnpm test:e2e was not run.

E2E

Built CLI, .env key, fixture inbox 43cd94f5-63f2-4abe-93d4-58b9c26f353e.

  • --help for all 36 inbox commands exits 0.
  • agent get by ID and by address returns actions. Interactive output prints Actions: (none). agent update was not called on the API, so the fixture agent did not change. Its local invalid_tone and invalid_actions errors were checked.
  • threads labels add, set, remove and set --labels "" on thread 772da839 returned the expected lists. An unknown label returned 404 Label not found.. The thread labels are [] again, as before. The labels spec-137 a and spec-137 b did not change.
  • threads update --add-label-ids returned invalid_options before any API call.
  • inboxes get, labels list, threads list, threads search, threads get, threads emails list, threads emails get, drafts list and drafts get passed by ID, by address and by an uppercase address. matched_email_id equals the id from threads emails list.
  • One draft was created, updated (output {object, id}), read and deleted.
  • A throwaway inbox was created with --forwarding and deleted by its address. The delete output held the inbox UUID.

Release

Release 2.26.0. package.json is 2.26.0 and the resend-cli skill is 2.23.0.