Send User Message
TinyAGI/tinyagi
Send a proactive message to a paired user via their channel (Discord, Telegram, or WhatsApp).
Agent skill
by Lifecycle-Innovations-Limited in Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "whatsapp business", "template message"…
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-whatsapp-biz --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .claude/skills && cp -r skills-src/claude-ops/skills/ops-whatsapp-biz .claude/skills/ops-whatsapp-biz && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ops-whatsapp-biz" agent skill from https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-biz into .claude/skills/ops-whatsapp-biz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ops-whatsapp-biz", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-bizType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-whatsapp-biz --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .agents/skills && cp -r skills-src/claude-ops/skills/ops-whatsapp-biz .agents/skills/ops-whatsapp-biz && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ops-whatsapp-biz" agent skill from https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-biz into .agents/skills/ops-whatsapp-biz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ops-whatsapp-biz", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-whatsapp-biz --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/claude-ops/skills/ops-whatsapp-biz .cursor/skills/ops-whatsapp-biz && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ops-whatsapp-biz" agent skill from https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-biz into .cursor/skills/ops-whatsapp-biz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ops-whatsapp-biz", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Lifecycle-Innovations-Limited/claude-ops.git --path claude-ops/skills/ops-whatsapp-biz--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-whatsapp-biz --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/claude-ops/skills/ops-whatsapp-biz .gemini/skills/ops-whatsapp-biz && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ops-whatsapp-biz" agent skill from https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-biz into .gemini/skills/ops-whatsapp-biz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ops-whatsapp-biz", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-whatsapp-bizInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .github/skills && cp -r skills-src/claude-ops/skills/ops-whatsapp-biz .github/skills/ops-whatsapp-biz && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ops-whatsapp-biz" agent skill from https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-biz into .github/skills/ops-whatsapp-biz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ops-whatsapp-biz", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-whatsapp-biz --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/claude-ops/skills/ops-whatsapp-biz .opencode/skills/ops-whatsapp-biz && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ops-whatsapp-biz" agent skill from https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-whatsapp-biz into .opencode/skills/ops-whatsapp-biz/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ops-whatsapp-biz", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ops-whatsapp-bizOPS on-demand: This skill should be used when the user asks to "whatsapp business", "template message"…
Ops Whatsapp Biz is an agent skill from Lifecycle-Innovations-Limited/claude-ops. OPS on-demand: This skill should be used when the user asks to "whatsapp business", "template message"…
Its SKILL.md is about 3.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Productivity & Automation. It works with WhatsApp. The repository describes itself as: Business operating system for Claude Code — 57 skills, 21 agents, smart daemon. Unified inbox (WhatsApp/Email/Slack/Telegram), autonomous PR merge, full-AWS monitoring, revenue… The licence is MIT.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit ee9c784. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
BashReadWriteGrepAskUserQuestionFrom allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
jqcurlFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
graph.facebook.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
WABA_TOKENWHATSAPP_BUSINESS_TOKENFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Ops Whatsapp Biz loads about 3.9k tokens when it runs. Until then it costs about 30 tokens; SKILL.md has 524 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Bash, Read, Write, Grep, AskUserQuestionAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Lifecycle-Innovations-Limited/claude-ops at commit ee9c784, republished under its MIT licence (© Lifecycle-Innovations-Limited). 524 words, ~3,945 tokens.
.claude/skills/ops-whatsapp-biz/SKILL.md (or your agent's skills folder).Load ops-rules before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If AskUserQuestion / Workflow are missing, follow Rule 10 in ops-rules (Hermes: numbered options / two-turn Telegram card; delegate_task).
WhatsApp Business Cloud API — distinct from wacli personal WhatsApp.
Key difference: This skill uses the WhatsApp Business Cloud API (Meta Graph API) for business-to-customer messaging at scale. wacli is for personal WhatsApp messaging. Different credentials, different phone numbers, different use cases.
PREFS_PATH="${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json"
# WhatsApp Business credentials (separate from wacli personal)
WABA_TOKEN="${WHATSAPP_BUSINESS_TOKEN:-$(jq -r '.user_config.whatsapp_business_token // empty' "$PREFS_PATH" 2>/dev/null)}"
WABA_PHONE_ID="${WHATSAPP_PHONE_NUMBER_ID:-$(jq -r '.user_config.whatsapp_phone_number_id // empty' "$PREFS_PATH" 2>/dev/null)}"
WABA_ACCOUNT_ID="${WHATSAPP_BUSINESS_ACCOUNT_ID:-$(jq -r '.user_config.whatsapp_business_account_id // empty' "$PREFS_PATH" 2>/dev/null)}"
# Doppler fallback
if [ -z "$WABA_TOKEN" ]; then
WABA_TOKEN="$(doppler secrets get WHATSAPP_BUSINESS_TOKEN --plain 2>/dev/null)"
fi
if [ -z "$WABA_PHONE_ID" ]; then
WABA_PHONE_ID="$(doppler secrets get WHATSAPP_PHONE_NUMBER_ID --plain 2>/dev/null)"
fi
if [ -z "$WABA_ACCOUNT_ID" ]; then
WABA_ACCOUNT_ID="$(doppler secrets get WHATSAPP_BUSINESS_ACCOUNT_ID --plain 2>/dev/null)"
fiCredential check: If WABA_TOKEN or WABA_PHONE_ID is empty, print:
WhatsApp Business not configured. Run /ops:whatsapp-biz setup to configure credentials.
and stop.
Route $ARGUMENTS:
| Input | Action |
|---|---|
| (empty), list-templates | List all templates with approval status |
| send-template | Send an approved template message to one or more recipients |
| create-template | Guided template creation wizard |
| check-template <NAME> | Poll approval status for a specific template |
| catalog | View and manage linked product catalog |
| setup | Configure WhatsApp Business API credentials |
List all message templates for the WhatsApp Business Account.
RESULT=$(curl -s "https://graph.facebook.com/v20.0/${WABA_ACCOUNT_ID}/message_templates?fields=name,status,category,language,components&limit=50" \
-H "Authorization: Bearer ${WABA_TOKEN}")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " WHATSAPP BUSINESS TEMPLATES"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
printf "| %-30s | %-10s | %-12s | %-8s |\n" "Template Name" "Status" "Category" "Language"
printf "|%s|%s|%s|%s|\n" "--------------------------------" "------------" "--------------" "----------"
echo "$RESULT" | jq -r '.data[]? | [.name, .status, .category, .language] | @tsv' 2>/dev/null | \
while IFS=$'\t' read -r name status category language; do
STATUS_ICON="○"
[ "$status" = "APPROVED" ] && STATUS_ICON="✓"
[ "$status" = "REJECTED" ] && STATUS_ICON="✗"
[ "$status" = "PENDING" ] && STATUS_ICON="…"
printf "| %-30s | %s %-9s | %-12s | %-8s |\n" "${name:0:30}" "$STATUS_ICON" "$status" "${category:0:12}" "$language"
done
TOTAL=$(echo "$RESULT" | jq '.data | length // 0')
APPROVED=$(echo "$RESULT" | jq '[.data[]? | select(.status == "APPROVED")] | length')
echo ""
echo "Total: ${TOTAL} templates | Approved: ${APPROVED}"
echo ""
echo "Note: Per-template pricing applies since July 2025. Check Meta pricing page for current rates."Send an approved template message to one or more recipients.
Before sending, collect via AskUserQuestion:
list-templates first to see available)If template has variables, ask for each parameter value via AskUserQuestion (free text).
Cost note: Always display approximate cost before sending. Utility templates: ~$0.005/msg; Marketing: ~$0.025/msg (US rates — varies by country). Show AskUserQuestion to confirm before bulk sends > 10 recipients.
# Parse recipients
IFS=',' read -ra RECIPIENTS <<< "$PHONE_NUMBERS"
RECIPIENT_COUNT=${#RECIPIENTS[@]}
# For bulk sends > 10, confirm
if [ $RECIPIENT_COUNT -gt 10 ]; then
# AskUserQuestion: "Send to ${RECIPIENT_COUNT} recipients? Estimated cost: ~$$(awk "BEGIN {printf \"%.2f\", $RECIPIENT_COUNT * 0.025}") for marketing templates." options [Send, Cancel]
[ "$CONFIRM" = "Cancel" ] && echo "Cancelled." && exit 0
fi
# Send to each recipient
SUCCESS=0; FAILED=0
for PHONE in "${RECIPIENTS[@]}"; do
PHONE=$(echo "$PHONE" | tr -d ' ')
RESP=$(curl -s -X POST "https://graph.facebook.com/v20.0/${WABA_PHONE_ID}/messages" \
-H "Authorization: Bearer ${WABA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"messaging_product\": \"whatsapp\",
\"to\": \"${PHONE}\",
\"type\": \"template\",
\"template\": {
\"name\": \"${TEMPLATE_NAME}\",
\"language\": {\"code\": \"en_US\"},
\"components\": ${TEMPLATE_COMPONENTS_JSON:-[]}
}
}")
MSG_ID=$(echo "$RESP" | jq -r '.messages[0].id // empty')
if [ -n "$MSG_ID" ]; then
SUCCESS=$((SUCCESS + 1))
else
FAILED=$((FAILED + 1))
ERR=$(echo "$RESP" | jq -r '.error.message // "unknown error"')
echo " Failed for ${PHONE}: ${ERR}"
fi
done
echo ""
echo "Sent: ${SUCCESS}/${RECIPIENT_COUNT} messages delivered"
[ $FAILED -gt 0 ] && echo "Failed: ${FAILED} — check phone number format (+country_code + number)"Template components format (build TEMPLATE_COMPONENTS_JSON from user input):
For templates with header + body variables:
[
{
"type": "header",
"parameters": [{ "type": "text", "text": "{{header_value}}" }]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "{{var1}}" },
{ "type": "text", "text": "{{var2}}" }
]
}
]For templates with no variables: TEMPLATE_COMPONENTS_JSON=[]
Guided template creation wizard.
Step 1 — Collect basic info:
AskUserQuestion: "Template category?" options [MARKETING, UTILITY, AUTHENTICATION, More...]
If More: AskUserQuestion: [AUTHENTICATION, UTILITY, Skip]
Step 2 — AskUserQuestion: "Template name (lowercase, underscores only, e.g. order_confirmation):" (free text)
Step 3 — AskUserQuestion: "Language?" options [en_US, en_GB, es, fr]
Step 4 — Collect body text (free text). Instruct user: "Use {{1}}, {{2}} etc for variables."
Step 5 — AskUserQuestion: "Add a header?" options [Text header, Image header, No header, Video header]
Step 6 — AskUserQuestion: "Add call-to-action button?" options [URL button, Phone button, No button, Quick reply]
# Build components array
COMPONENTS='[{"type":"BODY","text":"'"${BODY_TEXT}"'"}]'
# Add header if selected
if [ "$HEADER_TYPE" = "Text header" ]; then
HEADER_TEXT_INPUT="..." # collected via AskUserQuestion
COMPONENTS=$(echo "$COMPONENTS" | jq '. + [{"type":"HEADER","format":"TEXT","text":"'"${HEADER_TEXT_INPUT}"'"}]')
elif [ "$HEADER_TYPE" = "Image header" ]; then
COMPONENTS=$(echo "$COMPONENTS" | jq '. + [{"type":"HEADER","format":"IMAGE","example":{"header_handle":["<upload_handle>"]}}]')
fi
# Add button if selected
if [ "$BUTTON_TYPE" = "URL button" ]; then
BUTTON_URL="..." # collected via AskUserQuestion: "Button URL:"
BUTTON_TEXT="..." # collected via AskUserQuestion: "Button text:"
COMPONENTS=$(echo "$COMPONENTS" | jq '. + [{"type":"BUTTONS","buttons":[{"type":"URL","text":"'"${BUTTON_TEXT}"'","url":"'"${BUTTON_URL}"'"}]}]')
elif [ "$BUTTON_TYPE" = "Phone button" ]; then
BUTTON_PHONE="..." # collected via AskUserQuestion: "Phone number for button:"
BUTTON_TEXT="..."
COMPONENTS=$(echo "$COMPONENTS" | jq '. + [{"type":"BUTTONS","buttons":[{"type":"PHONE_NUMBER","text":"'"${BUTTON_TEXT}"'","phone_number":"'"${BUTTON_PHONE}"'"}]}]')
fi
RESP=$(curl -s -X POST "https://graph.facebook.com/v20.0/${WABA_ACCOUNT_ID}/message_templates" \
-H "Authorization: Bearer ${WABA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"${TEMPLATE_NAME}\",
\"category\": \"${CATEGORY}\",
\"language\": \"${LANGUAGE}\",
\"components\": ${COMPONENTS}
}")
TEMPLATE_ID=$(echo "$RESP" | jq -r '.id // empty')
STATUS=$(echo "$RESP" | jq -r '.status // empty')
if [ -n "$TEMPLATE_ID" ]; then
echo "Template submitted (ID: ${TEMPLATE_ID}, status: ${STATUS})."
echo "Approval typically takes 24-48 hours. Check status with: /ops:whatsapp-biz check-template ${TEMPLATE_NAME}"
else
echo "Template creation failed: $(echo "$RESP" | jq -r '.error.message // "unknown error"')"
fiPoll approval status for a specific template by name.
TEMPLATE_NAME_ARG=$(echo "$ARGUMENTS" | awk '{print $2}')
if [ -z "$TEMPLATE_NAME_ARG" ]; then
# AskUserQuestion: "Template name to check:" (free text)
TEMPLATE_NAME_ARG="$USER_INPUT"
fi
RESULT=$(curl -s "https://graph.facebook.com/v20.0/${WABA_ACCOUNT_ID}/message_templates?name=${TEMPLATE_NAME_ARG}&fields=name,status,rejected_reason,quality_score" \
-H "Authorization: Bearer ${WABA_TOKEN}")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " TEMPLATE STATUS: ${TEMPLATE_NAME_ARG}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "$RESULT" | jq -r '.data[]? | "Status: \(.status)\nQuality: \(.quality_score.score // "N/A")\nRejection reason: \(.rejected_reason // "—")"' 2>/dev/null
STATUS=$(echo "$RESULT" | jq -r '.data[0].status // "NOT_FOUND"')
case "$STATUS" in
APPROVED) echo "Template is ready to use with send-template." ;;
REJECTED) echo "Template was rejected. Review the rejection reason and create a revised template." ;;
PENDING) echo "Template is pending review (typically 24-48h)." ;;
NOT_FOUND) echo "Template '${TEMPLATE_NAME_ARG}' not found. Run list-templates to see available templates." ;;
esacView and manage the product catalog linked to your WhatsApp Business Account.
# List linked catalogs
CATALOGS=$(curl -s "https://graph.facebook.com/v20.0/${WABA_ACCOUNT_ID}?fields=catalog_id" \
-H "Authorization: Bearer ${WABA_TOKEN}")
CATALOG_ID=$(echo "$CATALOGS" | jq -r '.catalog_id // empty')
if [ -z "$CATALOG_ID" ]; then
echo "No product catalog linked to this WhatsApp Business Account."
echo "To link a catalog: go to Meta Business Manager → Commerce Manager → link your catalog to WhatsApp."
exit 0
fi
# List products in catalog
PRODUCTS=$(curl -s "https://graph.facebook.com/v20.0/${CATALOG_ID}/products?fields=id,name,retailer_id,price,availability,url&limit=20" \
-H "Authorization: Bearer ${WABA_TOKEN}")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " WHATSAPP PRODUCT CATALOG"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Catalog ID: ${CATALOG_ID}"
echo ""
printf "| %-25s | %-12s | %-10s | %-12s |\n" "Product Name" "SKU" "Price" "Availability"
printf "|%s|%s|%s|%s|\n" "---------------------------" "--------------" "------------" "--------------"
echo "$PRODUCTS" | jq -r '.data[]? | [.name, (.retailer_id // "—"), (.price // "—"), (.availability // "—")] | @tsv' 2>/dev/null | \
while IFS=$'\t' read -r name sku price avail; do
printf "| %-25s | %-12s | %-10s | %-12s |\n" "${name:0:25}" "${sku:0:12}" "$price" "$avail"
done
PRODUCT_COUNT=$(echo "$PRODUCTS" | jq '.data | length // 0')
echo ""
echo "Total products shown: ${PRODUCT_COUNT} (use catalog in message templates with product cards)"MM Lite note: Marketing Messages Lite (AI-optimized sends) is a beta API as of 2026. It is not implemented here — check Meta's developer documentation for current availability and enrollment requirements.
Configure WhatsApp Business API credentials.
Before asking, auto-scan for existing credentials:
PREFS_PATH="${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json"
# Scan env vars
printenv WHATSAPP_BUSINESS_TOKEN WHATSAPP_PHONE_NUMBER_ID WHATSAPP_BUSINESS_ACCOUNT_ID 2>/dev/null
# Scan Doppler
for proj in $(doppler projects --json 2>/dev/null | jq -r '.[].slug'); do
for cfg in dev stg prd; do
doppler secrets --project "$proj" --config "$cfg" --json 2>/dev/null | \
jq -r --arg p "$proj" --arg c "$cfg" 'to_entries[] | select(.key | test("WHATSAPP_BUSINESS|WHATSAPP_PHONE"; "i")) | "\(.key)=\(.value.computed) (doppler:\($p)/\($c))"'
done
done
# Shell profiles
grep -h 'WHATSAPP_BUSINESS\|WHATSAPP_PHONE' ~/.zshrc ~/.bashrc ~/.zprofile ~/.envrc 2>/dev/null | grep -v '^#'
# Existing plugin config
jq -r '.user_config.whatsapp_business_token // empty' "$PREFS_PATH" 2>/dev/null && echo "✓ whatsapp_business_token already configured"
jq -r '.user_config.whatsapp_phone_number_id // empty' "$PREFS_PATH" 2>/dev/null && echo "✓ whatsapp_phone_number_id already configured"
jq -r '.user_config.whatsapp_business_account_id // empty' "$PREFS_PATH" 2>/dev/null && echo "✓ whatsapp_business_account_id already configured"If credentials not found, guide user:
[Paste token now, Find in Meta dashboard, Skip]Where to find credentials in Meta:
WHATSAPP_BUSINESS_TOKEN: Meta Developer Portal → Your App → WhatsApp → API Setup → Temporary access token (or generate a permanent System User token)WHATSAPP_PHONE_NUMBER_ID: Same page → "From" phone number → Phone Number IDWHATSAPP_BUSINESS_ACCOUNT_ID: Meta Business Manager → Business Settings → WhatsApp Accounts → Account IDCollect each value via AskUserQuestion (free text):
Save via plugin config:
PREFS_PATH="${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json"
ops_user_config_set() { # write into preferences.json .user_config.<key>
local key="$1" value="$2" tmp
[ -n "$key" ] && [ -f "$PREFS_PATH" ] || return 0
tmp="$(mktemp "${PREFS_PATH}.XXXXXX")" || return 0
if jq --arg k "$key" --arg v "$value" '.user_config[$k] = $v' "$PREFS_PATH" >"$tmp" 2>/dev/null; then
chmod 600 "$tmp"; mv -f "$tmp" "$PREFS_PATH"
else
rm -f "$tmp"
fi
}
ops_user_config_set whatsapp_business_token "$WABA_TOKEN"
ops_user_config_set whatsapp_phone_number_id "$WABA_PHONE_ID"
ops_user_config_set whatsapp_business_account_id "$WABA_ACCOUNT_ID"TEST=$(curl -s "https://graph.facebook.com/v20.0/${WABA_PHONE_ID}" \
-H "Authorization: Bearer ${WABA_TOKEN}")
NAME=$(echo "$TEST" | jq -r '.display_phone_number // empty')
if [ -n "$NAME" ]; then
echo "WhatsApp Business ✓ connected — Phone: ${NAME}"
else
echo "WhatsApp Business ✗ connection failed: $(echo "$TEST" | jq -r '.error.message // "invalid token or phone ID"')"
fiReport: WhatsApp Business ✓ connected or ✗ invalid — [error].
© Lifecycle-Innovations-Limited, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in claude-ops/skills/ops-whatsapp-biz of Lifecycle-Innovations-Limited/claude-ops.
Open the folder on GitHubat commit ee9c784
Ops Whatsapp Biz next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Ops Whatsapp Biz this skillLifecycle-Innovations-Limited/claude-ops | 542 | — | ~3.9k | Automated safety check: Notes | MIT | |
| Send User MessageTinyAGI/tinyagi | 3.6k | — | ~829 | Automated safety check: Pass | MIT | |
| MuseKevPH2026/muse-catch | 128 | — | ~1.6k | Automated safety check: Notes | AGPL-3.0 | |
| Executive Digestmgonto/executive-assistant-skills | 118 | — | ~2.6k | Automated safety check: Notes | None | |
| Ak Dev New Messaging Integrationyaalalabs/agent-kernel | 192 | — | ~4.6k | Automated safety check: Pass | Apache-2.0 | |
| Add Telegramsbusso/claudeclaw | 194 | — | ~1.7k | Automated safety check: Notes | MIT |
TinyAGI/tinyagi
Send a proactive message to a paired user via their channel (Discord, Telegram, or WhatsApp).
KevPH2026/muse-catch
Muse · Catch — AI 灵感捕手。浏览器插件 + 任意 Agent(Telegram/WhatsApp/Discord…)一键捕获灵感,AI自动提炼,Web Dashboard浏览。分级LLM路由:Agent内置LLM隐私分析 + TokenRouter云端分布式调用。当用户说「灵感」「捕获」「Muse」「Catch」「记下来」「收藏」「稍后读」时自动触发。
mgonto/executive-assistant-skills
Generate the daily executive digest — a single WhatsApp summary of everything needing attention: stalled scheduling, pending intros, unanswered emails, promised follow-ups, open Todoist tasks, and…
yaalalabs/agent-kernel
Step-by-step guide for adding a new messaging platform integration to Agent Kernel.
sbusso/claudeclaw
Add Telegram as a channel. An agent skill from sbusso/claudeclaw.
davepoon/buildwithclaude
Automate WhatsApp Business tasks via Rube MCP (Composio): send messages, manage templates, upload media, and handle contacts.
Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "ops dashboard", "pixel HQ", or…
Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "go to market", "GTM plan", or…
Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "klaviyo", "ads spend", or…
Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "tweet", "post to linkedin", or…
Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "yolo mode", "run the business today"…
Lifecycle-Innovations-Limited/claude-ops
OPS on-demand: This skill should be used when the user asks to "datadog", "APM alerts", or…
Works with
Categories
OPS on-demand: This skill should be used when the user asks to "whatsapp business", "template message"…. Ops Whatsapp Biz is an agent skill from Lifecycle-Innovations-Limited/claude-ops.
Ops Whatsapp Biz fits situations like: asks to whatsapp business; template message….
Run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a claude-code`. Or copy the skill folder (claude-ops/skills/ops-whatsapp-biz in Lifecycle-Innovations-Limited/claude-ops) into .claude/skills/ops-whatsapp-biz in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a codex`. Or copy the skill folder (claude-ops/skills/ops-whatsapp-biz in Lifecycle-Innovations-Limited/claude-ops) into .agents/skills/ops-whatsapp-biz in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-whatsapp-biz -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ops-whatsapp-biz, .gemini/skills/ops-whatsapp-biz, .github/skills/ops-whatsapp-biz and .opencode/skills/ops-whatsapp-biz in your project.
Going by SKILL.md and its folder, Ops Whatsapp Biz needs the command-line tools its instructions call (jq and curl) and credentials named WABA_TOKEN and WHATSAPP_BUSINESS_TOKEN. Our summary lists: A credential in WABA_TOKEN; A credential in WHATSAPP_BUSINESS_TOKEN. Its frontmatter pre-approves these tools: Bash, Read, Write, Grep, AskUserQuestion.
SKILL.md names 1 domain. In commands or code: graph.facebook.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Ops Whatsapp Biz is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.9k tokens (SKILL.md is roughly 16k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Ops Whatsapp Biz: Send User Message (TinyAGI/tinyagi, 3.6k stars), Muse (KevPH2026/muse-catch, 128 stars), Executive Digest (mgonto/executive-assistant-skills, 118 stars) and Ak Dev New Messaging Integration (yaalalabs/agent-kernel, 192 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Lifecycle-Innovations-Limited (a GitHub organization) maintains it in Lifecycle-Innovations-Limited/claude-ops, which has 542 GitHub stars. The repository holds 67 skills in this directory. The repository was last updated on October 10, 2026.
Source: Lifecycle-Innovations-Limited/claude-ops on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.