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 peepshowUse it
WHATSAPP_PHONE_NUMBER_ID=123456789012345 \
WHATSAPP_TOKEN=EAAG... \
WHATSAPP_TO=15551234567 \
peepshow ./clip.mp4 --sink whatsappMake 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_IDCloud API phone number id (path segment, not the display number). requiredWHATSAPP_TOKENLong-lived access token (system-user or permanent). requiredWHATSAPP_TORecipient phone in E.164 digits, no `+` (e.g. `15551234567`). requiredWHATSAPP_MAX_FRAMESCap on images per run, clamped to `[1, 30]`. Default `4` for rate-limit safety.WHATSAPP_CAPTIONOverride the default per-image caption template.WHATSAPP_API_URLGraph 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
.envit can load), - the
peepshowCLI is onPATH— install withnpm 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,mov3. Example LLM session
You → drop a
.movinto Claude Code.Claude → auto-invokes
/peepshow:slides ./clip.mov. peepshow extracts frames + audio, the
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'.