Skip to content

feat: CRUD action helpers, skills install, setup improvements, remove audiences#3

Merged
rafa-thayto merged 18 commits into
mainfrom
chore/remove-deprecated-audiences
Feb 27, 2026
Merged

feat: CRUD action helpers, skills install, setup improvements, remove audiences#3
rafa-thayto merged 18 commits into
mainfrom
chore/remove-deprecated-audiences

Conversation

@rafa-thayto

Copy link
Copy Markdown
Contributor

Summary

  • lib/actions.ts — five CRUD helpers (runGet, runList, runCreate, runWrite, runDelete) that eliminate the repetitive requireClient → withSpinner → if/else pattern; applied to all commands across every namespace (~1 900 lines removed)
  • resend skills install command — multi-target install of Claude agent skills with interactive npx delegation (Cursor, Claude Desktop, VS Code, Claude Code, OpenClaw targets)
  • Setup / MCP improvements — extract writeMcpJsonConfig helper; all targets now use npx -y resend-mcp with RESEND_API_KEY resolved at setup time; fix stale resend mcp serve reference in help text
  • Remove deprecated audiences namespace — thin wrapper over segments; all six command files, four test files, and CLI registration removed
  • Install script fixesinstall.sh: write fish config to conf.d/resend.fish using fish_add_path; both scripts add a next-steps block with RESEND_API_KEY hint; install.ps1 uses a temp dir for extraction with proper finally cleanup

Test Plan

  • bun test passes with no failures
  • resend skills install runs interactively and writes correct config files for each target
  • resend setup cursor/claude-desktop/vscode/claude-code writes npx -y resend-mcp entries with API key
  • resend audiences is no longer a recognised command
  • install.sh on a fish shell machine writes conf.d/resend.fish and prints next-steps
  • install.ps1 on Windows cleans up the temp directory on success and failure

Notes

The audiences namespace was already marked deprecated (thin wrapper over segments). Users should migrate to resend segments.

All 8 delete commands and 10 list commands shared identical
auth → confirm/pagination → spinner → output patterns.

- Add src/lib/actions.ts with runDelete and runList<T> helpers
- runDelete: requireClient, optional confirmDelete, withSpinner, synthesized {object,id,deleted:true} output
- runList<T>: requireClient, withSpinner, onInteractive callback for table/hint rendering
- Each command action goes from ~15 lines to ~7 lines
- Zero behavior changes; 0 TS errors; 448/448 tests pass
Hardcoded Unicode literals (box-drawing, checkmarks) in source files
are corrupted to "Ââ"-style garbage when the bundled JS is read with
Latin-1 encoding — a common occurrence on Windows or certain npm
distribution paths.

Fix mirrors the approach used in outlit-sdk (commit cc87517):
generate all non-ASCII characters at runtime via String.fromCodePoint()
so source files contain only safe ASCII integer literals.

- tty.ts: export isUnicodeSupported (false on legacy Windows cmd.exe)
- table.ts: all box-drawing via String.fromCodePoint() + ASCII fallback
- spinner.ts: TICK/WARN/CROSS via String.fromCodePoint() + ASCII fallback

unicode-animations is already safe: it uses String.fromCodePoint()
internally to generate braille frames — no changes needed there.
…resend-mcp

cursor, claude-desktop, and vscode previously wrote { command: 'resend',
args: ['mcp', 'serve'] } — pointing at an unimplemented Phase 3 feature.
Switch to { command: 'npx', args: ['-y', 'resend-mcp'] } with the
RESEND_API_KEY env resolved at setup time. Extract writeMcpJsonConfig()
into setup/utils.ts so all three targets share a single implementation.
Primary path now runs: claude mcp add [-e RESEND_API_KEY=<key>] resend -- npx -y resend-mcp
Fallback (.claude.json) also switches to the npx resend-mcp entry with env.
Previously both paths referenced 'resend mcp serve', an unimplemented command.
Installs all skills from github.com/resend/resend-skills into
.claude/skills/ (project) or ~/.claude/skills/ (--global).

Fetches the repo file tree via the GitHub API, downloads each file,
and writes it preserving the subdirectory structure. The root SKILL.md
is placed in resend/SKILL.md so every skill lives in a named folder.

Excluded: README.md, LICENSE, package.json, pnpm-lock.yaml, tests/, .github/

Skills installed: resend, send-email, resend-inbound, templates, agent-email-inbox
Update the claude-code target description to match the actual command
(npx -y resend-mcp) and add a pointer to resend skills install.
The GitHub tree includes .gitignore at the repo root which was being
written to .claude/skills/.gitignore. Replace the specific .github/
pattern with /^\./ to exclude all root-level dotfiles and dot-directories.
- Change skillDir from ~/clawd/skills to ~/.openclaw/skills/resend
- Change skillPath from resend.md to SKILL.md (agent skills standard)
- Add YAML frontmatter with name/description to SKILL_CONTENT
- Update tests to assert correct path and frontmatter presence
- Interactive mode delegates to `npx skills add resend/resend-skills`
- Non-interactive writes to .claude/skills/ + .agents/skills/ (project)
- --global writes to detected per-agent dirs (~/.claude, ~/.cursor, etc.)
- InstallTarget[] signature replaces single-string skillsDir arg
- Output shape: { installed, targets: [{name,dir}], files }
- New test: multiple targets multiply write count correctly
- Add runGet<T> to lib/actions.ts alongside runList/runDelete
- Extract SdkCall<T> and SpinnerMessages local types to DRY runList/runDelete signatures
- Apply runGet to 8 commands: contacts, contact-properties, segments, topics,
  webhooks, broadcasts, domains, emails/receiving — removing ~8 lines of boilerplate each
- No behavior changes; tsc --noEmit and all 455 tests pass
Eliminates the requireClient → withSpinner(errorCode) → if/else tail
pattern duplicated across 8 update/verify/remove-segment commands.
- emails/receiving/list.ts → runList
- emails/receiving/attachments.ts → runList (error code normalized to list_error)
- broadcasts/send.ts → runWrite (successMsg computed before call)
Eliminates requireClient → withSpinner('create_error') → if/else tail
duplicated across 8 create commands. audiences/create.ts excluded due
to deprecated output-wrapping structure.
The audiences namespace was a thin deprecated wrapper over segments.
All CRUD commands, tests, and the CLI registration are removed.
Users should use `resend segments` instead.
This planning document tracked which CLI namespaces still needed
implementing. All namespaces are now complete, so the index is obsolete.
- install.sh: write fish config to conf.d/resend.fish using
  fish_add_path instead of editing config.fish; add next-steps
  block with RESEND_API_KEY export hint
- install.ps1: extract to a temp directory (not just a temp zip)
  so cleanup in finally removes the whole dir; add next-steps block
  with RESEND_API_KEY hint
@rafa-thayto rafa-thayto merged commit 0df0555 into main Feb 27, 2026
1 check failed
@felipefreitag felipefreitag deleted the chore/remove-deprecated-audiences branch March 16, 2026 19:43
dielduarte added a commit that referenced this pull request Jun 25, 2026
Felipe review (#3): whoami's help says it is local-only, which is now accurate —
it passes { refresh: false } so it reads the grant from keychain/file without a
network call. Tighten the help wording to 'active credential' (not 'API key') and
label OAuth credentials as 'Token' rather than 'API Key' in the human output.
Add a test asserting whoami never calls fetch for an OAuth profile.
dielduarte added a commit that referenced this pull request Jul 3, 2026
Felipe review (#3): whoami's help says it is local-only, which is now accurate —
it passes { refresh: false } so it reads the grant from keychain/file without a
network call. Tighten the help wording to 'active credential' (not 'API key') and
label OAuth credentials as 'Token' rather than 'API Key' in the human output.
Add a test asserting whoami never calls fetch for an OAuth profile.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant