peepshow/ sinks/ whatsapp

Reel #40 Messaging

peepshow sink / whatsapp

WhatsAppPost every run to a WhatsApp chat via Meta's Cloud API.

POST /media uploads per frame, one text summary, one image message per frame.

drop · process · whatsapp

What it does

Send peepshow runs to a WhatsApp chat using Meta's WhatsApp Cloud API. Each run uploads up to `WHATSAPP_MAX_FRAMES` frames (default 4) to `/media`, posts a text summary with container tags, then sends one `image` message per uploaded media id with an ordinal caption. The 24-hour customer-service-window rules apply: the recipient must have messaged the business number recently, or a template message must open the window before freeform sends succeed.

When to reach for it

  • Ops / on-call teams that live in WhatsApp and want video triage in-thread
  • Sandbox / test numbers where the customer-service window is already open
  • Chained workflows where an upstream template send has already opened the 24-hour window

Install

npm i -g peepshow

Use it

WHATSAPP_PHONE_NUMBER_ID=123456789012345 \
WHATSAPP_TOKEN=EAAG... \
WHATSAPP_TO=15551234567 \
peepshow ./clip.mp4 --sink whatsapp

Make it automatic

Register the sink once — every run fires it afterward. Scope by --when so it only runs for matching videos.

peepshow sinks add whatsapp
peepshow sinks add whatsapp --when extension=mp4,mov
peepshow sinks add whatsapp --when path=/Volumes/Work/

Configuration

  • WHATSAPP_PHONE_NUMBER_ID Cloud API phone number id (path segment, not the display number). required
  • WHATSAPP_TOKEN Long-lived access token (system-user or permanent). required
  • WHATSAPP_TO Recipient phone in E.164 digits, no `+` (e.g. `15551234567`). required
  • WHATSAPP_MAX_FRAMES Cap on images per run, clamped to `[1, 30]`. Default `4` for rate-limit safety.
  • WHATSAPP_CAPTION Override the default per-image caption template.
  • WHATSAPP_API_URL Graph API base. Default `https://graph.facebook.com/v20.0`.

Use with an LLM agent

Every peepshow sink reads its config from env vars and receives a single JSON payload on stdin. An LLM agent (Claude Code, Cursor, Windsurf, Gemini, Codex) can drive the WhatsApp sink automatically when three things are true:

  • the env vars below are exported in the agent's shell (or a project .env it can load),
  • the peepshow CLI is on PATH — install with npm i -g peepshow,
  • a peepshow auto-sink is registered for the run (optional but recommended — makes invocation zero-argument).

1. Set the environment

# Add to ~/.zshrc, ~/.bashrc, or a project .env the agent can load
export WHATSAPP_PHONE_NUMBER_ID="..."
export WHATSAPP_TOKEN="..."
export WHATSAPP_TO="..."

2. Register as an auto-sink

peepshow sinks add whatsapp
peepshow sinks add whatsapp --when extension=mp4,mov

3. Example LLM session

You → drop a .mov into Claude Code.

Claude → auto-invokes /peepshow:slides ./clip.mov. peepshow extracts frames + audio, the WhatsApp sink forwards the run to the configured channel. Claude replies with a summary and a link to the created record.

The transcript snippet is posted alongside the frames as a secondary message.

Write your own

A sink is any executable that reads the --emit json payload on stdin. Shell, Node, Python, Go — the spec's in docs/PLUGINS.md. Register persistent ones with peepshow sinks add-cmd 'your-command'.