Source profileQuality 92/100Review permissions

terrylica/cc-skills/plugins/whatsapp-commander/skills/send-message/SKILL.md

send-message

user wants to send a WhatsApp message, share a link or document via WhatsApp, generate a wa.me click-to-chat link, or message a contact on WhatsApp by phone number.

Source repository stars
61
Declared platforms
0
Static risk flags
3
Last source update
2026-08-26
Source checked
2026-08-28

Decision brief

What it does: where it fits

Reach a contact on WhatsApp. Unlike Telegram (tlg, full MTProto personal send) and Gmail (gmail-commander, OAuth API send), WhatsApp has no sanctioned personal-account send API — Meta only offers programmatic send through the Business Cloud API, and everything else (WhatsApp Web…

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/terrylica/cc-skills --skill "plugins/whatsapp-commander/skills/send-message"
    Safe inspection promptEditorial

    Inspect the Agent Skill "send-message" from https://github.com/terrylica/cc-skills/blob/05f53c5b24a445c1895e9b0590212e66cd70f39e/plugins/whatsapp-commander/skills/send-message/SKILL.md at commit 05f53c5b24a445c1895e9b0590212e66cd70f39e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Usage: wa-cli.ts

      The CLI is function/enum-driven Bun TypeScript — run it directly with bun (no build step). The link command writes the URL to stdout and its preflight/round-trip proof to stderr (e.g. ✓ link carries the full 439-char body), so URL=$(bun … link …) still captures a clean URL. It e…

      The CLI is function/enum-driven Bun TypeScript — run it directly with bun (no build step). The link command writes the URL to stdout and its preflight/round-trip proof to stderr (e.g. ✓ link carries the full 439-char bo…bash /usr/bin/env bash << 'WAEOF' SCRIPT="$(cc-plugin-root whatsapp-commander)/scripts/wa-cli.ts"
    2. 02

      Capability Tiers (pick the lowest that works)

      Default to Tier 1. Only use Tier 3 when the user has explicitly set up the Business Cloud API and the credentials resolve (see Preflight).

      Default to Tier 1. Only use Tier 3 when the user has explicitly set up the Business Cloud API and the credentials resolve (see Preflight).
    3. 03

      Preflight

      1. You need the recipient's phone number in international format (any punctuation is fine — the CLI strips non-digits). If you only have an email/username, ask for the number; WhatsApp is phone-number addressed. 2. WhatsApp registration is not verifiable from here — a wa.me link…

      You need the recipient's phone number in international format (any punctuation isWhatsApp registration is not verifiable from here — a wa.me link still opens evenFor Tier 3 only, confirm credentials are present:
    4. 04

      Tier 1 — build a click-to-chat link (the recommended default; BMP-only body, round-trip verified)

      bun "$SCRIPT" link "+1 (555) 123-4567" "Hi {{CONTACT}} — short note and a link: https://example.com/x"

      bun "$SCRIPT" link "+1 (555) 123-4567" "Hi {{CONTACT}} — short note and a link: https://example.com/x"
    5. 05

      Tier 1 — body read from a file (multi-paragraph messages are awkward inline)

      bun "$SCRIPT" link 15551234567 --file ./whatsapp-message.txt

      bun "$SCRIPT" link 15551234567 --file ./whatsapp-message.txt

    Permission review

    Static risk signals and limitations

    Network access

    medium · line 49

    The documentation includes network, browsing, or remote request actions.

    bun "$SCRIPT" link "+1 (555) 123-4567" "Hi {{CONTACT}} — short note and a link: https://example.com/x"

    Runs scripts

    medium · line 49

    The documentation asks the agent to run terminal commands or scripts.

    bun "$SCRIPT" link "+1 (555) 123-4567" "Hi {{CONTACT}} — short note and a link: https://example.com/x"

    Reads files

    low · line 51

    The documentation asks the agent to read local files, directories, or repositories.

    # Tier 1 — body read from a file (multi-paragraph messages are awkward inline)

    Runs scripts

    medium · line 52

    The documentation asks the agent to run terminal commands or scripts.

    bun "$SCRIPT" link 15551234567 --file ./whatsapp-message.txt

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score92/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars61SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    terrylica/cc-skills
    Skill path
    plugins/whatsapp-commander/skills/send-message/SKILL.md
    Commit
    05f53c5b24a445c1895e9b0590212e66cd70f39e
    License
    MIT
    Collected
    2026-08-28
    Default branch
    main
    View the original SKILL.md

    Send WhatsApp Message

    Reach a contact on WhatsApp. Unlike Telegram (tlg, full MTProto personal send) and Gmail (gmail-commander, OAuth API send), WhatsApp has no sanctioned personal-account send API — Meta only offers programmatic send through the Business Cloud API, and everything else (WhatsApp Web automation, whatsmeow/Baileys/wppconnect libraries) is unofficial and risks account bans. This skill therefore defaults to the safe, zero-credential path and escalates only when the user has set up the Cloud API.

    Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.

    Capability Tiers (pick the lowest that works)

    TierMethodActually sends?CredentialsWhen to use
    1 (default)wa.me click-to-chat linkNo — opens WhatsApp with text pre-filled; the human taps SendNoneAlmost always. ToS-safe, instant, works for any number.
    2WhatsApp Web browser automationYes, but brittleA logged-in WhatsApp Web session (QR)Not implemented here — DOM-fragile and ToS-gray. Document, don't build, unless the user insists.
    3WhatsApp Business Cloud APIYes, officiallyWHATSAPP_TOKEN + WHATSAPP_PHONE_NUMBER_ID (1Password)The user has a Meta Business app + registered number. See references/business-cloud-api.md.

    Default to Tier 1. Only use Tier 3 when the user has explicitly set up the Business Cloud API and the credentials resolve (see Preflight).

    Preflight

    1. You need the recipient's phone number in international format (any punctuation is fine — the CLI strips non-digits). If you only have an email/username, ask for the number; WhatsApp is phone-number addressed.
    2. WhatsApp registration is not verifiable from here — a wa.me link still opens even if the number is not on WhatsApp (it shows an "invalid number" notice on tap). State this assumption rather than claiming delivery.
    3. For Tier 3 only, confirm credentials are present:
    [ -n "${WHATSAPP_TOKEN:-}" ] && [ -n "${WHATSAPP_PHONE_NUMBER_ID:-}" ] && echo "cloud-api: READY" || echo "cloud-api: NOT CONFIGURED — use the link tier"
    

    Usage: wa-cli.ts

    The CLI is function/enum-driven Bun TypeScript — run it directly with bun (no build step). The link command writes the URL to stdout and its preflight/round-trip proof to stderr (e.g. ✓ link carries the full 439-char body), so URL=$(bun … link …) still captures a clean URL. It exits 2 if the body has emoji/astral chars (they would tofu).

    /usr/bin/env bash << 'WA_EOF'
    SCRIPT="$(cc-plugin-root whatsapp-commander)/scripts/wa-cli.ts"
    
    # Tier 1 — build a click-to-chat link (the recommended default; BMP-only body, round-trip verified)
    bun "$SCRIPT" link "+1 (555) 123-4567" "Hi {{CONTACT}} — short note and a link: https://example.com/x"
    
    # Tier 1 — body read from a file (multi-paragraph messages are awkward inline)
    bun "$SCRIPT" link 15551234567 --file ./whatsapp-message.txt
    
    # Tier 3 — actually send via the Business Cloud API (creds resolved into env first)
    export WHATSAPP_TOKEN="$(op item get <ITEM> --vault 'Claude Automation' --fields token --reveal)"
    export WHATSAPP_PHONE_NUMBER_ID="$(op item get <ITEM> --vault 'Claude Automation' --fields phone_number_id --reveal)"
    bun "$SCRIPT" send 15551234567 "Your appointment is confirmed."
    WA_EOF
    

    What to hand back to the user

    • Tier 1: present the wa.me URL as a Markdown link and tell them tapping it opens the chat with the text pre-filled — the final Send tap is theirs (WhatsApp does not allow automating that tap). On desktop they need WhatsApp Web logged in; on phone it deep-links.
      • You cannot see the recipient's rendered message on this tier — there is no feedback loop. So get it right in one shot: the CLI now runs a preflight (hard-fails on emoji/astral chars, warns on lone list-number lines / trailing —— / over-length) and a round-trip check, printing ✓ link carries the full N-char body to stderr. Relay that N as proof of completeness rather than eyeballing.
      • The api.whatsapp.com/send gray box is a scrollable PREVIEW, not the message. It truncates visually (a long or list-heavy body "ends at 1"), which triggers false "it got cut off" reports. Tell the user to click "Continue to WhatsApp Web" / "Open app" — the full body drops into the real compose box. Don't assert this blind; the round-trip line is the actual evidence the link is complete.
    • Tier 3: the API returns JSON with a messages[0].id; report the message id as proof of submission (subject to the 24-hour window / template rules — see references).

    Cloud API Window Rules (Tier 3)

    The Business Cloud API does not let you send arbitrary text to anyone at any time:

    • Inside the 24-hour customer-service window (the user messaged you in the last 24h): free-form type: "text" messages are allowed. wa-cli.ts send sends exactly this.
    • Outside the window (first contact / re-engagement): you may send only pre-approved message templates (type: "template"), not free text. A free-text send outside the window returns error 131047. For first contact, prefer Tier 1, or send an approved template via the raw Graph API (see references).

    Message Body Encoding — keep wa.me bodies emoji-free (BMP only)

    Do not put emoji or any other astral-plane (> U+FFFF) character in a Tier-1 wa.me link body. They arrive on the recipient's device as (U+FFFD replacement char / a diamond-? tofu) — even though the source file and the percent-encoded URL are both perfectly valid UTF-8. The wa.me → WhatsApp deep-link handoff mangles 4-byte codepoints (surrogate pairs), while Basic-Multilingual-Plane text — including all CJK — survives untouched. That asymmetry (Chinese renders fine, emoji become ) is the diagnostic tell: it is NOT a source-encoding bug, so don't go re-saving the file as UTF-8 — the bytes are already correct.

    • Verified 2026-07-04 (CPC ↔ {{CONTACT}} zh-Hans report): all Chinese rendered correctly but 👋 ✅ ❌ and keycap sequences (1️⃣) showed as in WhatsApp. Source bytes were valid (👋 = f0 9f 91 8b; the URL held %F0%9F%91%8B). Removing the emoji fixed it entirely.

    • Substitute BMP markers: headings 【…】, bullets -, numbering 1) / 2), quotes 「…」, arrows . All ≤ U+FFFF, render everywhere.

    • Guard before building a link — fail if any codepoint is astral or an emoji selector:

      python3 - "$MSG_FILE" <<'PY'
      import sys
      t = open(sys.argv[1], encoding="utf-8").read()
      bad = sorted({hex(ord(c)) for c in t
                    if ord(c) > 0xFFFF or ord(c) in (0xFE0F, 0x20E3)
                    or 0x1F000 <= ord(c) or 0x2600 <= ord(c) <= 0x27BF})
      print("ASTRAL/EMOJI PRESENT — will tofu to ⬜/�:", bad) if bad else print("BMP-only: safe")
      PY
      

    Tier 3 Cloud API send transmits real UTF-8 in the POST body and does not have this problem — the mangling is specific to the Tier-1 click-to-chat deep link.

    The link command now enforces the emoji check itself (hard error, exit 2) and prints a round-trip ✓ link carries the full N-char body line — so you rarely need to run the guard above by hand, but it's kept for quick pre-checks on a draft file.

    Keep Tier-1 bodies short and structurally flat

    The landing-page preview is a fixed, scrollable box. Long or list-heavy bodies scroll out of view and look truncated, which reads as a bug to the recipient/operator even though the link carries everything. Two of the three round-trips in the CPC ↔ {{CONTACT}} case (2026-07-04) were this false alarm, not real defects. So, for Tier-1:

    • Keep it concise (the CLI warns past ~700 chars). WhatsApp messages are read on phones; a tight 300–450-char note beats a wall of text.
    • Inline the asks as (1) … (2) … inside a paragraph — do NOT start a line with a bare 1) / 1.. A line that is just 1 is the classic "message got cut at 1" preview artifact.
    • Never end a line with —— flowing into a numbered item — it renders as a dangling -- 1. Use a colon lead-in (…问两件事:) instead.
    • The CLI's preflight warns on all three; treat the warnings as "fix before you hand it over".

    Anti-Patterns (NEVER DO)

    Anti-PatternWhy It Fails
    Claiming a wa.me link "sent" the messageIt only pre-fills; the human taps Send. Say so.
    Using an unofficial library (Baileys, whatsmeow, wppconnect) to send as a personal accountViolates WhatsApp ToS; risks number ban. Not part of this skill.
    Passing a number without a country codewa.me needs full E.164; the CLI rejects <8 digits.
    Free-text Cloud API send to a cold contactOutside the 24h window only approved templates send (error 131047).
    Hardcoding the Cloud API token in a script/commitResolve from 1Password into env at call time (mirrors gmail-commander/tlg).
    Emoji / astral-plane chars (👋✅❌, keycaps) in a wa.me link bodyArrive as (U+FFFD) — the deep-link handoff drops 4-byte codepoints; BMP/CJK survive. Keep Tier-1 bodies BMP-only.

    Error Handling

    SymptomCauseFix
    CLI: too few digitsNumber missing country codePass full international format
    CLI: Cloud API send needs WHATSAPP_TOKEN…Tier 3 creds absentUse Tier 1 link, or resolve creds via 1Password
    API Cloud API HTTP 401Token expired/invalidRotate the token in Meta → update 1Password
    API error 131047Outside 24h windowSend an approved template, or use Tier 1
    wa.me opens but shows "invalid number"Recipient not on WhatsApp / wrong numberConfirm the number with the user
    Recipient sees / diamond-? where emoji wereAstral-plane emoji lost in the wa.me→WhatsApp deep-link decode (source UTF-8 fine; CJK survives)Strip emoji from the body; use BMP markers (【】, -, 1)). See "Message Body Encoding".
    User reports the message "ends at 1" / looks cut offThe api.whatsapp.com/send gray box is a scrollable preview, not the message; long/list-y bodies scroll out of viewNot a bug — the round-trip ✓ carries N chars proves completeness. Tell them to click "Continue to WhatsApp Web"; keep bodies short & inline (1)(2).

    Evolution Log

    • 2026-07-04 (later) — hardened the Tier-1 path against the two failure modes above. Added to wa-cli.ts link: (1) an emoji/astral preflight (hard error, exit 2) so a tofu body is never emitted; (2) structural warnings for lone list-number lines / trailing —— / over-length that make the preview look truncated; (3) a round-trip check that decodes the built URL and asserts it equals the input, printing ✓ link carries the full N-char body. Lesson baked in: on Tier-1 the agent has no view of the rendered result, so verify what's verifiable (round-trip) and never assert preview behavior blind. Cost that motivated this: one CPC ↔ {{CONTACT}} message took three user round-trips (emoji → dangling dash → false "truncated" preview) — all now caught before hand-off.

    • 2026-07-04 — emoji tofu on the Tier-1 link path. A zh-Hans report (CPC ↔ {{CONTACT}}) rendered all Chinese correctly but showed 👋 ✅ ❌ / keycaps as in WhatsApp. Root cause: the wa.me → WhatsApp deep-link handoff drops astral-plane (4-byte) codepoints while BMP text, including CJK, survives — the source file and percent-encoded URL were both valid UTF-8. Fix + guard documented in the new "Message Body Encoding" section: keep Tier-1 bodies BMP-only.

    • 2026-06-22 — initial skill. WhatsApp has no personal-account send API. Modelled on tlg/gmail-commander conventions but split into capability tiers because the platform forbids the equivalent of MTProto/OAuth personal send. Default = wa.me link (the path proven in the VanJobbers ↔ CPC engagement); Cloud API send wired but credential-gated. CLI written as function/enum-driven Bun TypeScript per the repo language preference.

    Post-Execution Reflection

    After this skill completes, check before closing:

    1. Did the command succeed? — If not, fix the instruction or error table that caused it.
    2. Did wa-cli.ts flags or output change? — Update the Usage block to match.
    3. Was a workaround needed? — Capture it here so the next run doesn't rediscover it.
    4. New convention learned about WhatsApp's limits? — Add it to the tier table / window rules.

    Only update if the issue is real and reproducible — not speculative.

    Frequently asked questions

    What to verify before installation and use

    What does the send-message source document cover?

    Reach a contact on WhatsApp. Unlike Telegram (tlg, full MTProto personal send) and Gmail (gmail-commander, OAuth API send), WhatsApp has no sanctioned personal-account send API — Meta only offers programmatic send through the Business Cloud API, and everything else (WhatsApp Web…

    How do I install send-message?

    The source record exposes this install command: npx skills add https://github.com/terrylica/cc-skills --skill "plugins/whatsapp-commander/skills/send-message". Inspect the command and pinned source before running it.

    Which permission-related actions were detected?

    Static rules flagged network, exec-script, read-files in the source; the page lists the matching lines and excerpts.

    Alternatives

    Compare before choosing

    Computed 10045,960

    coreyhaines31/marketingskills

    ab-testing

    When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

    Computed 10029,236

    garrytan/gbrain

    bulk-ingestion

    End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.

    Computed 10025,136

    alirezarezvani/claude-skills

    app-store-optimization

    App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

    Computed 1005,277

    dotnet/skills

    migrate-vstest-to-mtp

    Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing