一键导入
ops-comms
// Send and read messages across all channels. Routes based on arguments — whatsapp, email, slack, telegram, discord, notion, or natural language like "send [msg] to [contact]".
// Send and read messages across all channels. Routes based on arguments — whatsapp, email, slack, telegram, discord, notion, or natural language like "send [msg] to [contact]".
127 production skills across 10 categories (Security, Deployment, Dev, Business, Content, SEO, Marketing, Product, Automation, Core). Skills auto-load based on your task. Includes localhost dashboard with Agent Runner, Burn Report, and session diary.
Use TweetClaw as an OpenClaw plugin for X/Twitter automation: search tweets, search tweet replies, post tweets/replies, export followers, look up users, handle media, monitor tweets, deliver webhooks, run giveaway draws, and manage approval-gated visible actions.
Trigger when you would normally reach for pytest, gh, mypy, black, or other raw repo tooling. Redirect to `sm swab`, `sm scour`, `sm buff`, `sm sail`, `sm refit`, or `sm doctor` so remediation follows the established rails. Also trigger when filing issues about slop-mop friction — use `sm barnacle file` / `/slopmop:sm-barnacle`, never `gh issue create`.
Draft and publish AI-powered press releases — submit a URL + notes, get a live release page instantly. Free, no API key required.
Check claude-ops background daemon end-to-end and auto-fix common issues. Detects stale plist paths after plugin upgrades, missing service commands, dead processes, corrupt health files, and bash version mismatches.
Interactive pixel-art command center dashboard. Visual business HQ with instant hotkey navigation to all ops commands, live status indicators, fire alerts, C-suite reports, settings, sharing, and FAQ.
| name | ops-comms |
| description | Send and read messages across all channels. Routes based on arguments — whatsapp, email, slack, telegram, discord, notion, or natural language like "send [msg] to [contact]". |
| argument-hint | [channel] | send [message] to [contact] | read [channel] | notion [search query] |
| allowed-tools | ["Bash","Read","Grep","Glob","Skill","AskUserQuestion","mcp__claude_ai_Gmail__search_threads","mcp__claude_ai_Gmail__get_thread","mcp__claude_ai_Gmail__create_draft","mcp__claude_ai_Slack__slack_send_message","mcp__claude_ai_Slack__slack_read_channel","mcp__claude_ai_Slack__slack_search_users","mcp__claude_ai_Slack__slack_search_public_and_private","mcp__claude_ops_telegram__send_message","mcp__claude_ops_telegram__get_updates","mcp__claude_ops_telegram__list_chats","mcp__claude_ai_Notion__notion-search","mcp__claude_ai_Notion__notion-fetch","mcp__claude_ai_Notion__notion-get-comments","mcp__claude_ai_Notion__notion-create-comment","mcp__claude_ai_Notion__notion-update-page","mcp__claude_ai_Notion__notion-create-pages"] |
| effort | medium |
| maxTurns | 40 |
Before executing, load available context:
Daemon health: Read ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/daemon-health.json
wacli-sync status before any WhatsApp operation~/.wacli/.health — if not status=connected, surface auth issue before proceedingOps memories: Before drafting any message, check ${CLAUDE_PLUGIN_DATA_DIR}/memories/:
contact_*.md — load profile for the recipientpreferences.md — match user's communication style, language, and tonedonts.md — restrictions that must not appear in any draftPreferences: Read ${CLAUDE_PLUGIN_DATA_DIR}/preferences.json for default_channels to determine which channel to prefer when multiple are available for a contact.
Health file — check ~/.wacli/.health BEFORE any wacli command:
status=connected → proceedstatus=needs_auth or status=needs_reauth → prompt user for QR scan, do NOT run wacli commands| Command | Usage | Output |
|---|---|---|
wacli doctor --json | Check auth/connected/lock/FTS | {data: {authenticated, connected, lock_held, fts_enabled}} |
wacli chats list --json | All chats | {data: [{JID, Name, Kind, LastMessageTS}]} |
wacli messages list --chat "<JID>" --limit N --json | Messages for chat | {data: {messages: [{FromMe, Text, Timestamp, SenderName, ChatName}]}} |
wacli messages search --query "<text>" --json | FTS search | Same as above |
wacli contacts --search "<name>" --json | Contact lookup | Contact objects |
wacli send --to "<JID>" --message "<msg>" | Send text | Success/error |
| Command | Usage | Output |
|---|---|---|
gog gmail search "in:inbox" --max 50 -j --results-only --no-input | Search inbox | JSON array of threads |
gog gmail thread get <threadId> -j | Get full thread with all messages | Full message JSON |
gog gmail send --to "user@example.com" --subject "subj" --body "text" | Send new email | Send result |
gog gmail send --reply-to-message-id <msgId> --reply-all --body "text" | Reply all | Send result |
gog gmail send --to "a@b.com" --subject "subj" --body "text" --attach /path/file | With attachment | Send result |
gog gmail archive <messageId> ... --no-input --force | Archive messages | Archive result |
Parse $ARGUMENTS and route immediately:
| Pattern | Action |
|---|---|
whatsapp | Show WhatsApp recent chats — offer to read or send |
email | Show recent email threads via Gmail MCP |
slack | Show recent Slack activity |
telegram | Show Telegram recent chats |
discord | Show recent Discord channel activity (via bin/ops-discord) |
notion | Search Notion workspace — pages, comments, tasks |
send * to * | Parse message and contact, determine best channel, send |
read * | Read the specified channel or contact's messages |
| (empty) | Show channel picker menu |
Natural-language parsing: phrases like send "deploy done" to #general on discord or to #ops-alerts on Discord should resolve to the discord branch below. Extract the channel token (the word after #, case-insensitive) and pass it as the first arg to bin/ops-discord send.
send [message] to [contact]$ARGUMENTS.wacli contacts --search "[contact]" --json 2>/dev/nullmcp__claude_ai_Slack__slack_search_users with query: "[contact]"AskUserQuestion: [WhatsApp] / [Slack] / [Email]AskUserQuestion to confirm:Ready to send via [channel]:
To: [contact name] ([identifier])
Message: "[full message text]"
[Send now] [Edit message] [Cancel]
If user picks "Edit message", use AskUserQuestion with free-text to get the revised message, then re-preview.
Sent to [contact] via [channel] ✓CRITICAL — READ BEFORE SENDING: Before drafting ANY WhatsApp reply, you MUST:
wacli messages list --chat "<JID>" --limit 20 --jsonFromMe: true) vs the contactNever send a reply based on a single message. A message like "can you pull it from Klaviyo?" means nothing without knowing what "it" refers to from prior messages.
Pre-flight: Before any wacli command, check ~/.wacli/.health. If status=needs_auth or status=needs_reauth, prompt the user: "WhatsApp needs re-authentication. Run wacli auth in a separate terminal and scan the QR code, then type 'done'." Use AskUserQuestion: [Done — re-paired], [Skip WhatsApp]. On Done, restart daemon: launchctl kickstart -k gui/$(id -u)/com.claude-ops.wacli-keepalive, wait 5s.
wacli send --to "[contact]" --message "[message]"
Use mcp__claude_ai_Slack__slack_send_message with resolved channel/user ID.
Use mcp__claude_ai_Gmail__create_draft — always create draft first. Then use AskUserQuestion:
Draft created for [recipient]:
Subject: [subject]
Body: [preview]
[Send now] [Keep as draft] [Edit]
read [channel]WhatsApp:
wacli chats --limit 10 --json 2>/dev/null
Show last 10 chats with sender, preview, timestamp.
Email:
Use mcp__claude_ai_Gmail__search_threads with query: "in:inbox" (NOT is:unread — scan full inbox including read messages), show thread list.
Slack:
Use mcp__claude_ai_Slack__slack_search_public_and_private with query: "in:channel" (NOT is:unread — scan full recent activity).
Telegram:
Use mcp__claude_ops_telegram__get_updates (limit: 20) and mcp__claude_ops_telegram__list_chats.
Fall back to: telegram-cli --exec "dialog_list" 2>/dev/null || echo "Telegram MCP not configured"
Discord:
${CLAUDE_PLUGIN_ROOT}/bin/ops-discord read "<CHANNEL_ID>" --limit 20 --json — requires DISCORD_BOT_TOKEN (or credential-store discord/bot-token). Fall back to bin/ops-discord channels --json if the user doesn't know the channel ID and DISCORD_GUILD_ID is set.
Notion:
Use mcp__claude_ai_Notion__notion-search with the user's query (or query: "" sorted by last_edited_time for general browsing). For each result:
mcp__claude_ai_Notion__notion-fetch using the page URL/ID from search resultsmcp__claude_ai_Notion__notion-get-commentsNotion API fallback: If MCP tools fail and NOTION_API_KEY is set, use curl -s -H "Authorization: Bearer $NOTION_API_KEY" -H "Notion-Version: 2022-06-28" -X POST https://api.notion.com/v1/search -d '{"query":"<QUERY>","page_size":10}'
Use mcp__claude_ai_Notion__notion-create-comment with the page ID to reply to a comment thread. For creating new pages in a database, use mcp__claude_ai_Notion__notion-create-pages.
Always preview before commenting:
Ready to comment on Notion page:
Page: [page title]
Comment: "[comment text]"
[Post comment] [Edit] [Cancel]
Use mcp__claude_ops_telegram__send_message with chat_id (from list_chats) and text.
Shell out to bin/ops-discord send. Three invocation shapes:
# By channel alias (resolves DISCORD_WEBHOOK_<UPPER> or DISCORD_WEBHOOK_URL)
${CLAUDE_PLUGIN_ROOT}/bin/ops-discord send "<channel-alias>" "<message>" --json
# By channel snowflake (17-20 digit ID, routed through bot token)
${CLAUDE_PLUGIN_ROOT}/bin/ops-discord send "<CHANNEL_ID>" "<message>" --json
# By full webhook URL (useful when the URL is stored per-project)
${CLAUDE_PLUGIN_ROOT}/bin/ops-discord send "https://discord.com/api/webhooks/<ID>/<TOKEN>" "<message>" --json
If the script exits 1 with {"error":"no discord credential configured — run /ops:setup discord"}, prompt the user via AskUserQuestion (≤4 options per Rule 1): [Run /ops:setup discord] / [Paste webhook URL now] / [Skip]. Do NOT silently skip — that violates Rule 3.
Note: DISCORD_WEBHOOK_URL is shared with the ops-fires notification sink (scripts/ops-notify.sh). When pre-existing, prefer it as the default for /ops:comms discord send rather than asking the user to set a separate value.
Display the header, then use batched AskUserQuestion calls (max 4 options each):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
OPS ► COMMS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Before presenting options, read ${CLAUDE_PLUGIN_DATA_DIR}/preferences.json and check which channels are configured. Only show configured channels. If <=4 total options (configured channels + "Send a message"), present in a single call. If >4, batch:
AskUserQuestion call 1 — Read channels:
[Read WhatsApp]
[Read Email]
[Read Slack]
[More...]
AskUserQuestion call 2 (only if "More..."):
[Read Telegram]
[Send a message]
If all channels are configured, that's 5 options — always batch. If only 3 channels are configured, "Read X" + "Read Y" + "Read Z" + "Send a message" = 4, fits in one call.
Execute the selected action.