← All Skills

snappy-outbound

v1.0.0
5 files, 30.8 KB ~1,100 words · 5 min read Updated 2026-09-09

snappy-outbound skill

43 of 45 checks pass
What it can do
pick contact-idread
statusread
send contact-idsend
What does not pass yet
$ npx snappy-skills install snappy-outbound
zip ↓
Documents
AGENTS.md

Show produced work with snappy-faces: call draw for image channels or lang for MCP Apps.

<!-- SKILL-INDEX-START -->

[snappy-outbound Index]|root: ~/.claude/skills/snappy-outbound|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md}

<!-- SKILL-INDEX-END -->

snappy-outbound — Channel Router#

One send() call, picks the channel, delivers. Every recipe that reaches

a human routes through this skill instead of re-implementing channel logic.

Purpose#

  • A recipe's deliver hook needs to message a contact and doesn't care which channel
  • A workflow wants to message many contacts at once, each at their preferred channel
  • Another skill wants "just reach this person" without hard-coding slack vs email

When NOT to use#

  • You need a specific channel for a specific reason — call the channel skill directly
  • You're broadcasting to a public channel (slack sendSlackMessage(C…), not DM) — use snappy-slack directly
  • You're posting content (LinkedIn post, blog, youtube) — use the content skill

API shape#

tsimport { send } from "../snappy-outbound/api.ts";

// Returns a Cert { ok, link, note, error }
const cert = await send({
  contact_id: 42,       // look up from snappy-knowledge
  body: "Hey…",
  channel?: "slack",    // optional override
  subject?: "...",      // used only for email
  thread_id?: "...",    // used only for slack
});

Channel fallback chain#

explicit channelcontact.preferred_channelslackemail

linkedintelegramimessagewhatsapp

Channels are skipped if the contact has no handle/address for them.

Email sends as a draft; everything else sends immediately. LinkedIn is

not programmatically sendable — the cert returns ok: false, note: "manual"

with the profile URL so a human can finish the job.

CLI#

bashnpx tsx api.ts send 42 "Hey — quick question"
npx tsx api.ts send 42 "Hi" --channel email --subject "Follow up"
npx tsx api.ts pick 42                 # dry-run: show picked channel + reason

Used by#

Nothing in the collection names this skill.

<!-- SNAPPY-CONTRACT-VERBS-START -->

Contract verbs#

Generated from api.ts HAND_CONTRACT. Do not hand-edit this block.

Verb Contract arguments Effect First call
pick contact-id read npx tsx ~/.claude/skills/snappy-outbound/api.ts pick <contact-id>
status read npx tsx ~/.claude/skills/snappy-outbound/api.ts status
send contact-id send npx tsx ~/.claude/skills/snappy-outbound/api.ts send <contact-id>

Show the result#

When an answer carries face_hint, show it with one snappy_present(<answer>) call.

See /snappy-faces for face selection. Human-facing images must crop to the

element, render at 2x on Retina, and fill the destination channel instead of

placing a small card in a full-page screenshot.

<!-- SNAPPY-CONTRACT-VERBS-END -->

Show produced work with `snappy-faces`: call `draw` for image channels or `lang` for MCP Apps.

<!-- SKILL-INDEX-START -->
[snappy-outbound Index]|root: ~/.claude/skills/snappy-outbound|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md}
<!-- SKILL-INDEX-END -->

# snappy-outbound — Channel Router

One `send()` call, picks the channel, delivers. Every recipe that reaches
a human routes through this skill instead of re-implementing channel logic.

## Purpose

- A recipe's `deliver` hook needs to message a contact and doesn't care which channel
- A workflow wants to message many contacts at once, each at their preferred channel
- Another skill wants "just reach this person" without hard-coding slack vs email

## When NOT to use

- You need a specific channel for a specific reason — call the channel skill directly
- You're broadcasting to a public channel (slack `sendSlackMessage(C…)`, not DM) — use snappy-slack directly
- You're posting content (LinkedIn post, blog, youtube) — use the content skill

## API shape

```ts
import { send } from "../snappy-outbound/api.ts";

// Returns a Cert { ok, link, note, error }
const cert = await send({
  contact_id: 42,       // look up from snappy-knowledge
  body: "Hey…",
  channel?: "slack",    // optional override
  subject?: "...",      // used only for email
  thread_id?: "...",    // used only for slack
});
```

## Channel fallback chain

`explicit channel` → `contact.preferred_channel` → `slack` → `email` →
`linkedin` → `telegram` → `imessage` → `whatsapp`

Channels are skipped if the contact has no handle/address for them.
Email sends as a **draft**; everything else sends immediately. LinkedIn is
**not** programmatically sendable — the cert returns `ok: false, note: "manual"`
with the profile URL so a human can finish the job.

## CLI

```bash
npx tsx api.ts send 42 "Hey — quick question"
npx tsx api.ts send 42 "Hi" --channel email --subject "Follow up"
npx tsx api.ts pick 42                 # dry-run: show picked channel + reason
```

## Used by

Nothing in the collection names this skill.

<!-- SNAPPY-CONTRACT-VERBS-START -->
## Contract verbs

Generated from `api.ts` `HAND_CONTRACT`. Do not hand-edit this block.

| Verb | Contract arguments | Effect | First call |
|---|---|---|---|
| `pick` | `contact-id` | `read` | `npx tsx ~/.claude/skills/snappy-outbound/api.ts pick <contact-id>` |
| `status` | — | `read` | `npx tsx ~/.claude/skills/snappy-outbound/api.ts status` |
| `send` | `contact-id` | `send` | `npx tsx ~/.claude/skills/snappy-outbound/api.ts send <contact-id>` |

## Show the result

When an answer carries `face_hint`, show it with one `snappy_present(<answer>)` call.
See `/snappy-faces` for face selection. Human-facing images must crop to the
element, render at 2x on Retina, and fill the destination channel instead of
placing a small card in a full-page screenshot.
<!-- SNAPPY-CONTRACT-VERBS-END -->

Keyboard Shortcuts

Search in document⌘K
Focus search/
Previous file tab
Next file tab
Close overlayEsc
Show shortcuts?