OPS on-demand: This skill should be used when the user asks to "send a message"…

MITAuto-check: warningsProductivity & Automation

Install Ops Comms

The automated check flagged lines worth reading first. See the safety section below.

skills CLI
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-comms -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-comms --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ 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-comms .claude/skills/ops-comms && rm -rf skills-src

Use ~/.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/

Facts

Skill name
ops-comms
GitHub stars
542
Token cost
~6.4k tokens
SKILL.md length
2,831 words
Files
2 (incl. references)
Skills in repo
67
Repo updated
First seen
Licence
MIT

At a glance

OPS on-demand: This skill should be used when the user asks to "send a message"…

  • Works in 3 steps: Daemon health: Read… → Ops memories: Before drafting any… → Preferences: Read…
  • Asks to send a message…
  • SKILL.md covers Runtime Context, Routing table, Send flow: send [message] to… and Outbound judgment: verify…, plus 3 more sections
  • Calls curl; reaches api.notion.com and discord.com; needs CLAIM_KEY and NOTION_API_KEY

What it does

Ops Comms is an agent skill from Lifecycle-Innovations-Limited/claude-ops. OPS on-demand: This skill should be used when the user asks to "send a message"…

Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/cli.md`).

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.

When your agent uses it

  • Asks to send a message…

Example prompts

  • “send a message”
  • “/ops-comms”

Requirements

  • Pre-approved tools (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

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Daemon health: Read ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/daemon-health.json
  2. Ops memories: Before drafting any message, check ${CLAUDE_PLUGIN_DATA_DIR}/memories/
  3. Preferences: Read ${CLAUDE_PLUGIN_DATA_DIR}/preferences.json for default_channels to determine which channel to prefer when multiple are…

What it can do on your machine

Read from SKILL.md and the folder at commit 1aa0928. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • 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

    …and 12 more on the same allowed-tools line.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • curl

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • api.notion.com
    • discord.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • CLAIM_KEY
    • NOTION_API_KEY
    • DISCORD_BOT_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ops Comms loads about 6.4k tokens when it runs, and up to ~7.2k if it reads all its reference files. Until then it costs about 23 tokens; SKILL.md has 2,831 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~23
When it runs · the whole SKILL.md, loaded when a task matches
~6.4k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~7.2k

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.

Safety

Auto-check: warnings

The automated check found patterns that need a careful read before installing.

  • WarningMentions a paste, webhook or tunnelling service often used to send data outSKILL.md:369
    GIN_ROOT}/bin/ops-discord send "https://discord.com/api/webhooks/<ID>/<TOKEN>" "<message>" --json
  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Bash, Read, Grep, Glob, Skill, AskUserQuestion, mcp__claude_ai_Gmail__search_threads, mcp__claude_ai

Automated 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.

SKILL.md

The full file from Lifecycle-Innovations-Limited/claude-ops at commit 1aa0928, republished under its MIT licence (© Lifecycle-Innovations-Limited). 2,831 words, ~6,419 tokens.

Download SKILL.mdSave it as .claude/skills/ops-comms/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
ops-comms
description
OPS on-demand: This skill should be used when the user asks to "send a message"…
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
argument-hint
[channel] | send [message] to [contact] | read [channel] | notion [search query]
effort
medium
maxTurns
40
context
fork

OPS ► COMMS

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).

Runtime Context

Before executing, load available context:

  1. Daemon health: Read ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/daemon-health.json

    • Check bridge liveness before any WhatsApp operation: lsof -i :8080 | grep LISTEN
    • If bridge not running, prompt user to restart: launchctl kickstart -k gui/$UID/com.${USER}.whatsapp-bridge
  2. Ops memories: Before drafting any message, check ${CLAUDE_PLUGIN_DATA_DIR}/memories/:

    • contact_*.md — load profile for the recipient
    • preferences.md — match user's communication style, language, and tone
    • donts.md — restrictions that must not appear in any draft
  3. Preferences: Read ${CLAUDE_PLUGIN_DATA_DIR}/preferences.json for default_channels to determine which channel to prefer when multiple are available for a contact.

Routing table

PatternAction
whatsappShow WhatsApp recent chats — offer to read or send
emailShow recent email threads via Gmail MCP
slackShow recent Slack activity
telegramShow Telegram recent chats
discordShow recent Discord channel activity (via bin/ops-discord)
notionSearch Notion workspace — pages, comments, tasks
voiceVoice / phone / video — routes to /ops:ops-voice (bin/ops-voice)
call * Native Phone.app call via bin/ops-voice phone
facetime *FaceTime audio/video via bin/ops-voice facetime
zoomStart an instant Zoom meeting via bin/ops-voice zoom start
send * to *Parse message and contact, determine best channel, send
read *Read the specified channel or contact's messages
home alarmPipe a Homey alarm event as a WhatsApp/Telegram alert — delegates to /ops:ops-home alarm --notify (only if home_automation is configured in $PREFS_PATH)
(empty)Show channel picker menu

Natural-language parsing:

  • send "deploy done" to #general on discord → bin/ops-discord send general "deploy done".
  • call <contact> / dial <contact> / phone <contact> → resolve number, then bin/ops-voice phone <E.164>.
  • facetime <contact> (with optional audio) → bin/ops-voice facetime <handle> [--audio].
  • start a zoom / new zoom meeting → bin/ops-voice zoom start.
  • join zoom <ID> → bin/ops-voice zoom join <ID>.
  • text <contact> "<body>" / sms <contact> "<body>" → bin/ops-voice twilio-sms <to> $TWILIO_FROM_NUMBER "<body>" (guarded by per-message approval).

Send flow: send [message] to [contact]

  1. Parse contact name and message from $ARGUMENTS.
  2. Determine channel by contact lookup:
    • Check WhatsApp: mcp__whatsapp__search_contacts {query: "[contact]"} 2>/dev/null
    • Check Slack: mcp__claude_ai_Slack__slack_search_users with query: "[contact]"
    • Check email: known from context or ask
  3. If multiple channels found, use AskUserQuestion: [WhatsApp] / [Slack] / [Email]
  4. Always preview before sending. Use 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.

  1. Send via the chosen channel. Confirm with: Sent to [contact] via [channel] ✓
WhatsApp send

CRITICAL — READ BEFORE SENDING: Before drafting ANY WhatsApp reply, you MUST:

  1. Read the full conversation: mcp__whatsapp__list_messages {chat_jid: "<JID>", limit: 20}
  2. Understand which messages have is_from_me: true (user sent) vs is_from_me: false (contact sent)
  3. Summarize what the conversation is about and what the contact is asking
  4. Only THEN draft a reply that addresses what the contact actually said

Never 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: Check bridge is running: lsof -i :8080 | grep LISTEN. If not running, restart: launchctl kickstart -k gui/$(id -u)/com.${USER}.whatsapp-bridge and wait 5s.

mcp__whatsapp__send_message {recipient: "[contact_jid]", message: "[message]"}
Slack send

Use mcp__claude_ai_Slack__slack_send_message with resolved channel/user ID.

Email send (draft)

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]

Outbound judgment: verify before you assert

Before drafting to a person, load relations for their brief, open commitments and the full-context draft order, and vip for their tier. A tier-1 recipient is drafted with extra care and never handled from a digest line. Neither skill can send; Rule 6 still owns the send.

Rule 6 governs whether a message may go out. This section governs whether the message is right. Every item below is a failure mode seen on a real run, where the approval gate held and the content was still wrong.

Research every load-bearing claim

Never state a fact in someone else's inbox from memory. A price, a date, an availability, a "who currently holds X" all get a cheap check first: a search, the actual thread, the calendar, the invoice.

Claims about the recipient's own access get probed, not inferred. Telling a colleague their access is broken is a claim about a system you can inspect. A wrong diagnosis sends a competent person chasing a non-problem, and they will believe you because you appear to hold the admin view. Sort each access item into fixed, never broken, or theirs, and say which. Telling someone "that already works" stops them building a workaround for a permission they already have.

Verify the join, not just the endpoints

The hardest fabrications are not invented facts, they are invented relationships between two real things that share a name, an entity, or a keyword. Each half is true, the sentence joining them is not, and it reads as diligence rather than a guess.

"X should be coordinated with Y" is itself a factual claim and needs its own evidence. A company or person appearing in two matters is weak evidence they are the same workstream and often strong evidence of a naming coincidence. Be especially suspicious of an advisory clause nobody asked for: the recipient asked a yes or no question, and a "let's just align with..." rider is exactly where invented linkage hides. When challenged on such a clause, probe and delete it rather than rewording it into something defensible.

Do not absorb the other party's job

An inbound message that mentions a task is not automatically a task for the user. When the sender owns the workstream, a heads-up about their own work in progress is not an instruction transferring that work.

Before staging any reply containing a first-person commitment ("I'll pick that up", "I'll clean that up"), check whose function it is, who has the access, and whether the commitment is even wanted. A message that only needs acknowledging gets acknowledgement. Volunteering labour reads as helpful and creates real obligations nobody tracks. When the work does need doing and the counterparty owns it, name it and hand it back rather than quietly taking it on.

Do not route a decision the counterparty already made

A narrow A/B to the user is right for a real trade-off and wrong when the counterparty already supplied the answer inside the message being triaged. An identifier a person gives for their own account (login, email, phone, handle, bank account) is authoritative. A conflict with the admin view means the estate is misconfigured, not that they misremembered their own account. Use the probing to shape the message, not to defer. Escalate only when the action is irreversible and expensive; two systems disagreeing is neither.

The tell that this rule was broken is a closing question to the user whose answer is already quoted verbatim in the inbound message.

A staged draft goes stale

A queue of drafts is researched at one moment and sent over hours. Any draft referencing a pending external process (a bank instruction, a signature, a shipment, a filing) must have that process re-checked immediately before the send, not just at research time. A draft that correctly said "still waiting, no news" became wrong when the counterparty's reply landed mid-queue.

Two consequences are easy to miss: the draft's central claim can flip outright, and new inbound often creates a second outbound that also needs drafting. Search results encountered mid-queue get triaged, not skimmed past.

A parallel session may have already sent it. Multiple agents can work the same inbox and send under the same identity. Treat any outbound from the user's own identity that this session did not write as another agent's work: verify its claims at the source, report the item closed with that evidence, and move on. Do not re-send, and do not assume it was correct just because it exists.

A counterparty's restatement of your position is not authoritative

When someone replies "which of these did you mean?" or summarises your position back before proceeding, do not pick the more plausible reading. Open what the user actually sent and read their own words. A partner who guesses wrong and proceeds on that guess can commit the user, in writing, to a different deal than the one they proposed. Their politeness is not evidence; a soft hedge from a competent counterparty is exactly where an unnoticed inversion lives.

When the user contradicts your draft, check before defending it

Low-confidence pushback ("check, I think we already signed", "I might have credentials too") is a hard stop and a research instruction, not a hedge to be reassured about. Re-probe the primary source and come back with what it says, including "partly, the mechanism is X not Y". Never defend a draft against the user's own recollection without checking first.

Do not trust an audit's verdict over primary evidence

A subagent audit is a research artifact, not a finding. Before acting on a cancel-or-delete verdict, open one paid invoice and read the SKU, quantity, billing address, and payment history. "No API key in the environment" does not mean "unused": no-code SaaS runs entirely in a web UI. A "paused" or free-tier notice may belong to an entirely different account than the paid plan.

Reply to their message, not your parallel checklist

When the user says "just reply", answer only the inbound ask. Do not bolt on extra forms, address updates, or multi-item checklists they did not ask for in that draft. Extra tracks get a separate message after the send if still needed. When the user corrects a draft to be shorter or more spoken, rewrite against their wording, not a re-packaged version of your own.

A work handover must match the tracker exactly

When a message tells someone what to work on, do not paraphrase the tracker. Re-run the query and enumerate every open item in board order with identifier, priority, and state. Vagueness is how items get silently dropped and how the recipient invents their own ordering. If something is deliberately excluded, say so and why rather than omitting it silently.

Show full SKILL.md (1,177 more words)Show less
Sequencing irreversible actions: preserve, verify, then destroy

When an action destroys an asset (a contact list, a mailbox, a dataset), order the work export, then verify the export is real, then destroy. "Verify" means row count and headers inspected against an expectation stated up front, so the check is falsifiable. An export returning a few hundred rows from a plan holding tens of thousands is a failed export that looks like a successful one. Split it across two approvals: the export can run autonomously, the destroy waits for the user.

Verify the send actually landed

Do not treat a send tool returning without an error as delivery. Confirm on the channel: the outbound row appears in the thread, or the message carries the SENT label. A DRAFT is not a delivery, and a broken sender alias can bounce seconds later. If verification fails, do not archive; an unverified send is an unanswered thread.

Post-reply disposition, in the same step as the send

Every thread you reply to gets a disposition immediately. There is no "leave it and see".

  • Ball in their court — archive once the send is verified.
  • User still owes something — snooze with a dated reminder naming the owed action and the thread, then archive. An unfulfilled commitment must never stay visible as a substitute for tracking it.
  • Unactionable or already answered — archive.

Only threads genuinely waiting on the user's own next action stay in the inbox.

Auto-resume the next staged outbound

After one item is approved, sent, verified, and dispositioned, stage the next queue item automatically without waiting for "go" or "next". Stop only for the per-draft approval itself, a real decision that is the user's to make, or a blocker only a human can clear.


Read flow: read [channel]

WhatsApp:

mcp__whatsapp__list_chats {sort_by: "last_active"}

Show last 10 chats with sender, preview, timestamp. Use mcp__whatsapp__list_messages {chat_jid, limit: 5} to preview each chat.

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 (multi-workspace):

Read the derived channels.slack.workspaces[] object from the pre-gathered bin/ops-unread output (NOT the raw preferences.json → slack_workspaces[], which has no available field — it only persists workspace metadata). The bin/ops-unread step resolves each workspace's token_env and emits available: true|false per entry. Iterate that array:

  • For each available: true entry, use mcp__claude_ai_Slack__slack_search_public_and_private with query: "in:channel" (NOT is:unread) if the MCP token matches, or direct curl for non-bound workspaces. To resolve the token for direct curl, the entry's token_env field is the name of the env var; validate it matches ^[A-Za-z_][A-Za-z0-9_]*$ before indirect expansion (${!token_env}) to avoid bash aborting on invalid identifiers.
  • Label results with the workspace name: Slack/<workspace_a>, Slack/<workspace_b>, etc.
  • channels.slack.multi_workspace == false / legacy mode: fall back to mcp__claude_ai_Slack__slack_search_public_and_private if channels.slack.available == true, otherwise report "Slack not configured".

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:

  • Fetch full page content with mcp__claude_ai_Notion__notion-fetch using the page URL/ID from search results
  • Get comments with mcp__claude_ai_Notion__notion-get-comments
  • Show page title, database name, last editor, and recent comments

Notion 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}'

Notion comment/reply

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]
Telegram send

Use mcp__claude_ops_telegram__send_message with chat_id (from list_chats) and text.

Discord send

Shell out to bin/ops-discord send. Three invocation shapes:

bash
# 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.

Voice / phone / video

All voice traffic flows through bin/ops-voice (full surface documented in the ops-voice skill). Native channels (Phone.app, FaceTime, Zoom start|join) need no credentials; programmatic channels (Twilio voice/SMS, Bland AI, Zoom schedule) follow the standard credential-resolution order.

bash
# Native — no creds
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice phone    "+1234567890" --json
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice facetime user@example.com --audio --json
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice zoom     start
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice zoom     join 1234567890 --pwd <password>

# Programmatic — gated by Rule 6 (per-message approval)
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice twilio-call "+1234567890" "$TWILIO_FROM_NUMBER" --twiml "<URL>" --json
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice twilio-sms  "+1234567890" "$TWILIO_FROM_NUMBER" "<body>" --json
${CLAUDE_PLUGIN_ROOT}/bin/ops-voice bland-call  "+1234567890" "<task prompt>" --json

Send-flow integration: when $ARGUMENTS looks like call <contact>, facetime <contact>, text <contact> "<body>", or have an AI call <contact> and ...:

  1. Resolve the contact's number/handle (mcp__whatsapp__search_contacts or preferences.json → contacts).
  2. For native calls (phone, facetime, zoom): preview [Place call via <channel> to <contact>] [Cancel] then invoke.
  3. For Twilio voice/SMS and Bland AI: stage the full draft (recipient, channel, body or task-prompt) and gate behind one AskUserQuestion per message (Rule 6). Never batch.

How the approval is actually enforced — see scripts/outbound-guard/README.md. One store, /tmp/.claude-outbound-guard.json, shared by every CLI. The owner arms it from their own shell with ! ok (1 message), ! ok 3, or ! ok all (10, capped). A message is identified by recipient plus content, so the same message crossing the PreToolUse hook and the MCP proxy costs one unit rather than two. A counter does not replace Rule 6: you still stage each draft and wait for a yes.

Three traps that have each caused a real bypass:

  • Never let a helper script do the sending. The Bash guard matches on the text of the command, so a send hidden inside a script is invisible to it. Print the command from a helper if you like, then run the real one inline.
  • A SENT label is not delivery. A send-as alias with bad SMTP credentials is stamped SENT and bounced by mailer-daemon seconds later in the same thread. Check for the bounce before reporting a message as delivered.
  • Match tool names by pattern. Multi-account installs expose mcp__whatsapp-<label>__send_message; an exact-string allowlist silently stops covering them while still appearing to run (Rule 8).
  1. If no credential resolves for a programmatic channel, prompt via AskUserQuestion with [Run /ops:ops-voice setup] / [Paste credential now] / [Try native instead] / [Skip] (Rule 3 — never silently skip).

Empty arguments — channel picker

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]
  [Make a call (voice)]
  [Send a message]

If all channels are configured, that's 6+ options — always batch. If only 3 channels are configured, "Read X" + "Read Y" + "Read Z" + "Send a message" = 4, fits in one call. The voice channel is configured iff preferences.json → channels.voice is present OR default_channels contains "voice".

Execute the selected action.


Ledger Integration

CLAIM_KEY by channel and message unit:

  • Slack thread: slack:thread:<channel>:<ts>
  • WhatsApp message: slack:thread:wa:<jid>:<ts> (reuse slack: namespace for threads)
  • Outbound draft (no inbound thread): comms:draft:<channel>:<YYYY-MM-DDTHH-MM>
Pre-flight skip-check
bash
CLAIM_KEY="slack:thread:<channel>:<ts>"   # adjust per channel
ledger query --claim-key "$CLAIM_KEY" --since=-PT24H

Skip any message/thread where a done or in_progress entry exists. Surface awaiting_user entries as "draft already staged — resend or edit?"

Claim + resolve
bash
# Claim before drafting
ledger write \
  --claim-key "$CLAIM_KEY" \
  --kind "draft" \
  --status "in_progress" \
  --title "Comms: <channel> — <brief description>" \
  --ttl-sec 3600

# After user approves + send fires
ledger write \
  --claim-key "$CLAIM_KEY" \
  --kind "send" \
  --status "done" \
  --title "Comms: <channel> — <brief description>" \
  --context "sent via <channel>"

Additional resources

CLI detail: references/cli.md.

© 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

Files

SKILL.md and 1 other file (references) in claude-ops/skills/ops-comms of Lifecycle-Innovations-Limited/claude-ops.

  • SKILL.md
  • references/cli.md

Open the folder on GitHubat commit 1aa0928

Compare with similar skills

Ops Comms 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.

Ops Comms compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ops Comms this skillLifecycle-Innovations-Limited/claude-ops542—~6.4kAutomated safety check: WarnMIT
Send User MessageTinyAGI/tinyagi3.6k—~829Automated safety check: PassMIT
MuseKevPH2026/muse-catch128—~1.6kAutomated safety check: NotesAGPL-3.0
Executive Digestmgonto/executive-assistant-skills118—~2.6kAutomated safety check: NotesNone
Ak Dev New Messaging Integrationyaalalabs/agent-kernel192—~4.6kAutomated safety check: PassApache-2.0
Add Telegramsbusso/claudeclaw194—~1.7kAutomated safety check: NotesMIT

Similar skills

  • Send User Message

    TinyAGI/tinyagi

    Send a proactive message to a paired user via their channel (Discord, Telegram, or WhatsApp).

    3.6k GitHub stars~829 tokensUpdated 6 mo ago
    Productivity & AutomationAuto-check passed
  • Muse

    KevPH2026/muse-catch

    Muse · Catch — AI 灵感捕手。浏览器插件 + 任意 Agent(Telegram/WhatsApp/Discord…)一键捕获灵感,AI自动提炼,Web Dashboard浏览。分级LLM路由:Agent内置LLM隐私分析 + TokenRouter云端分布式调用。当用户说「灵感」「捕获」「Muse」「Catch」「记下来」「收藏」「稍后读」时自动触发。

    128 GitHub stars~1.6k tokensUpdated 1 mo ago
    Productivity & AutomationAuto-check: notes
  • Executive Digest

    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…

    118 GitHub stars~2.6k tokensUpdated 7 mo ago
    Productivity & AutomationAuto-check: notes
  • Ak Dev New Messaging Integration

    yaalalabs/agent-kernel

    Step-by-step guide for adding a new messaging platform integration to Agent Kernel.

    192 GitHub stars~4.6k tokensUpdated today
    Productivity & AutomationAuto-check passed
  • Add Telegram

    sbusso/claudeclaw

    Add Telegram as a channel. An agent skill from sbusso/claudeclaw.

    194 GitHub stars~1.7k tokensUpdated 1 mo ago
    Productivity & AutomationAuto-check: notes
  • Whatsapp Automation

    davepoon/buildwithclaude

    Automate WhatsApp Business tasks via Rube MCP (Composio): send messages, manage templates, upload media, and handle contacts.

    3.6k GitHub starsUsed in 7 repos~2.1k tokens
    Productivity & AutomationAuto-check passed

More from Lifecycle-Innovations-Limited/claude-ops

All 67 skills in this repo
  • Ops Dash

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "ops dashboard", "pixel HQ", or…

    542 GitHub stars~4.7k tokensUpdated today
    Auto-check: notes
  • Ops Gtm

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "go to market", "GTM plan", or…

    542 GitHub stars~3.7k tokensUpdated today
    Auto-check: notes
  • Ops Marketing

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "klaviyo", "ads spend", or…

    542 GitHub stars~3.5k tokensUpdated today
    Auto-check: notes
  • Ops Socials

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "tweet", "post to linkedin", or…

    542 GitHub stars~3.6k tokensUpdated today
    Auto-check: notes
  • Ops Yolo

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "yolo mode", "run the business today"…

    542 GitHub stars~4k tokensUpdated today
    Auto-check: notes
  • Ops Monitor

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "datadog", "APM alerts", or…

    542 GitHub starsUsed in 1 repo~1.5k tokens
    Auto-check: notes

Works with

Questions about Ops Comms

What does Ops Comms do?

OPS on-demand: This skill should be used when the user asks to "send a message"…. Ops Comms is an agent skill from Lifecycle-Innovations-Limited/claude-ops.

When should I use Ops Comms?

Ops Comms fits situations like: asks to send a message….

How do I install Ops Comms in Claude Code?

Run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-comms -a claude-code`. Or copy the skill folder (claude-ops/skills/ops-comms in Lifecycle-Innovations-Limited/claude-ops) into .claude/skills/ops-comms in your project. Claude Code loads it when a task matches its description.

How do I install Ops Comms in Codex?

Run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-comms -a codex`. Or copy the skill folder (claude-ops/skills/ops-comms in Lifecycle-Innovations-Limited/claude-ops) into .agents/skills/ops-comms in your project. Codex loads it when a task matches its description.

Can I use Ops Comms in Cursor, Gemini CLI or GitHub Copilot?

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-comms -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-comms, .gemini/skills/ops-comms, .github/skills/ops-comms and .opencode/skills/ops-comms in your project.

What does Ops Comms need to run?

Going by SKILL.md and its folder, Ops Comms needs the command-line tools its instructions call (curl) and credentials named CLAIM_KEY, NOTION_API_KEY and DISCORD_BOT_TOKEN. Its frontmatter pre-approves these 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.

Does Ops Comms access the network?

SKILL.md names 2 domains. In commands or code: api.notion.com and discord.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.

Is Ops Comms safe to install?

Our automated static check of SKILL.md flagged 1 warning(s): mentions a paste, webhook or tunnelling service often used to send data out. Read the flagged lines before installing; the check is not a guarantee either way.

What licence does Ops Comms use?

Ops Comms is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ops Comms use?

About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 749 tokens, read only when the agent opens those files.

What are the alternatives to Ops Comms?

Skills that share tags, products or a category with Ops Comms: 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.

Who maintains Ops Comms?

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 9, 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.