ClaudeCodeMod

All shelves / Skills

slack-cli

paymog/slack-cli · 7.2k installs · 0 stars

Skill

Marked External Downloads · Command Execution · Indirect Prompt Injection · Data Exfiltration · Credentials Unsafe

Install

In your shell
npx -y skills add paymog/slack-cli --skill slack-cli --agent claude-code

Run in a terminal. Claude loads the skill when a task calls for it. Check the repo's README before you run it.

Open the repo

Files

SKILL.md

Slack CLI

Invoke the slack-cli binary (install via brew install paymog/tap/slack-cli). Source of truth is paymog/slack-cli. It wraps the korotovsky/slack-mcp-server engine for behavior, but prints JSON by default (the underlying MCP server emits CSV) so output pipes cleanly into jq.

Output

Every successful command prints valid JSON by default. List/table commands (channels, messages, users, saved items, user groups) emit arrays of objects. Structured mutations expose their result fields directly; conversations add returns channel, optional thread_ts, and ts. Legacy plain-text statuses are wrapped as {"message":"…"}. Pipe directly into jq:

slack-cli channels list | jq -r '.[].Name'
slack-cli conversations history '#general' --limit 1d | jq -r '.[].Text'
slack-cli users search alice | jq -r '.[].DMChannelID'
slack-cli conversations add C123 --thread-ts 123.456 -t "hello" | jq -r .ts

Field values from CSV-backed tables are strings; use jq's tonumber for numeric comparisons. --raw prints the underlying CSV/text or legacy human-readable command output verbatim.

Auth (required before any command)

Provide exactly one credential set via env (the CLI also reads stored profiles):

export SLACK_MCP_XOXP_TOKEN=xoxp-...        # user OAuth — full features (recommended)
# or
export SLACK_MCP_XOXB_TOKEN=xoxb-...        # bot token — invited channels only, no search
# or
export SLACK_MCP_XOXC_TOKEN=xoxc-...        # browser session token  + cookie below
export SLACK_MCP_XOXD_TOKEN=xoxd-...        # browser cookie d (stealth mode)

Capability notes:

  • Search (conversations search, users_search real-time) and unreads work best with xoxp or browser (xoxc/xoxd). Bot tokens cannot search.
  • Saved items (saved …) require browser tokens (xoxc/xoxd) only.
  • --govslack / SLACK_MCP_GOVSLACK=true routes to slack-gov.com.

Stored profiles (alternative to env vars)

slack-cli auth login [name]        # prompts for mode + token(s); validates before saving
slack-cli auth list                # * marks default
slack-cli auth default <name>
slack-cli --profile <name> <cmd>   # use a profile for one command
slack-cli auth status              # show resolved source + mode
slack-cli auth logout <name> [-f]

Precedence: explicit --xoxp/--xoxc/... flags or SLACK_MCP_* env → --profile <name> → default profile. Explicit tokens + --profile is rejected as ambiguous. SLACK_CLI_PROFILE sets the profile via env.

Cache (do this first for name lookups)

#channel-name / @username lookups and channels list need a warm cache. The cache is on disk and shared across every invocation, so refresh once:

slack-cli cache refresh            # fetch users + channels, write cache to disk

Read commands auto-load the on-disk cache (and fetch on first run). Use --no-cache to skip it — then only raw IDs (C…, U…, D…) resolve, not names.

Channels / IDs

<channel> accepts an ID (C123…), a name (#general), or a DM (@username).

Read commands

# Channels (JSON array; fields: ID,Name,Topic,Purpose,MemberCount,Cursor)
slack-cli channels list [--types public_channel,private_channel,im,mpim] [--query foo] [--query-targets name,topic,purpose] [--sort popularity] [--limit 100] [--cursor C]
slack-cli channels me                      # channels you belong to

# Conversation history & threads
slack-cli conversations history <channel> [--limit 1d|1w|30d|<count>] [--cursor C] [--activity]
slack-cli conversations replies <channel> <thread_ts>
# Pagination: read the Cursor field of the last element, then pass --limit='' --cursor <value>.
# Unlisted Slack apps: 1 req/min and 15 msgs/page on history/replies. The CLI waits
# Retry-After and shares the slot across processes. Set SLACK_MCP_UNLISTED_HISTORY=1
# to force that cap. Default --timeout is 2m. Do not hammer these in a loop.

# Search (needs xoxp or browser token; not bot)
slack-cli conversations search [query] \
  [--in-channel #general] [--in-dm @user] [--with @user] [--from @user] \
  [--before YYYY-MM-DD] [--after YYYY-MM-DD] [--on YYYY-MM-DD] [--during July] \
  [--threads-only] [--limit 20] [--cursor C]
# A full Slack message URL as the query returns just that message.

# Unreads, prioritized DMs > partner > internal (best with xoxp/browser)
slack-cli conversations unreads [--types all|dm|group_dm|partner|internal] [--mentions-only] [--max-channels 50] [--max-messages-per-channel 10] [--include-muted]

# Users (JSON array incl. DMChannelID for quick messaging)
slack-cli users search <query> [--limit 10]

# User groups
slack-cli usergroups list [--include-users] [--include-disabled]
slack-cli usergroups me <list|join|leave> [--usergroup-id S123]

# Saved items (browser tokens only)
slack-cli saved list [--filter saved|completed|archived] [--limit 50]

# Attachments (download a file by ID; always available, no env var needed).
slack-cli attachments get <file_id> [-o path]   # Fxxxxxxxxxx, max 5MB

Write / sensitive commands (opt-in)

Disabled by default — each needs an env var set in the same invocation, so an agent never posts or mutates by accident. The allowlist forms (C123,D456, or !C123 for all-except) restrict which channels are writable.

SLACK_MCP_ADD_MESSAGE_TOOL=true  slack-cli conversations add <channel> -t "hello" [--thread-ts 123.456] [--content-type text/mrkdwn|text/markdown|text/plain]
SLACK_MCP_ADD_MESSAGE_TOOL=true  slack-cli conversations add <channel> --text-file /tmp/reply.txt --content-type text/mrkdwn
SLACK_MCP_ADD_MESSAGE_TOOL=true  slack-cli conversations add <channel> --blocks '<Block Kit JSON array>'
SLACK_MCP_MARK_TOOL=true         slack-cli conversations mark <channel> [--ts 123.456]
SLACK_MCP_REACTION_TOOL=true     slack-cli reactions add <channel> <timestamp> --emoji rocket
SLACK_MCP_REACTION_TOOL=true     slack-cli reactions remove <channel> <timestamp> --emoji rocket
slack-cli usergroups create --name "Eng" [--handle eng] [--description ...] [--channels C1,C2]
slack-cli usergroups update <usergroup_id> [--name ...] [--handle ...] [--channels ...]
slack-cli usergroups users-update <usergroup_id> --users U1,U2,U3
slack-cli saved update <item_id> <ts> [--mark completed] [--date-due <unix>]
slack-cli saved clear-completed

Critical: multi-line / formatted posts

Default for conversational replies: native Slack message text, read from a file.

Write the body to a UTF-8 file with your file-writing tool, using actual line breaks. Then pass only its path to the shell:

SLACK_MCP_ADD_MESSAGE_TOOL=C123 slack-cli conversations add C123 \
  --thread-ts 123.456 --text-file /tmp/reply.txt --content-type text/mrkdwn
  • --text-file preserves newlines, backticks, dollar signs, and literal \n examples without shell interpolation. It cannot be combined with --text.
  • text/mrkdwn posts ordinary Slack-formatted text without Block Kit. Use *bold*, _italic_, <https://example.com|label>, and backticks for code; use bullets rather than Markdown tables or # headings.
  • The default text/markdown converts GitHub-style Markdown into Block Kit; it is not native Slack text. text/plain disables formatting.
  • Reserve --blocks for interactive or deliberately structured UI. Newlines, bullets, and code alone do not require blocks.
  • Inline -t is fine for simple one-liners. Do not embed multiline bodies in shell commands: -t "first\nsecond" sends literal \n, not a line break.
  • Keep answers concise; split long answers at paragraph boundaries. Native text avoids section-block collapse, but Slack can still collapse long messages.

Delete a botched post

slack-cli has no delete command. Use Slack's Web API with the resolved xoxp token:

TOKEN=$(slack-cli auth token | jq -r .SLACK_MCP_XOXP_TOKEN)
# chat.delete needs channel + message ts (e.g. 1783603079.714919 from replies)
curl -s -X POST https://slack.com/api/chat.delete \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"channel":"C061WRT6XM5","ts":"1783603079.714919"}'

Only works for messages your token is allowed to delete (your own user messages with xoxp, or bot messages with the bot token).

Verify before walking away

After posting multi-line content, re-read the thread and check for:

  • bullets stuck on one line
  • missing newlines after headers/code fences
  • truncated or shell-error fragments (command not found, half-eaten backticks)

If any of those appear, fix the source file, delete via chat.delete, and repost with --text-file … --content-type text/mrkdwn.

Recipes

# Triage unread DMs and mentions
slack-cli cache refresh
slack-cli conversations unreads --types dm
slack-cli conversations unreads --mentions-only

# Find a thread, then read its replies
slack-cli conversations search "deploy rollback" --in-channel #incidents --after 2024-06-01
slack-cli conversations replies C0123456789 1718000000.123456

# Who is someone, then DM them (needs SLACK_MCP_ADD_MESSAGE_TOOL)
slack-cli users search alice            # note DMChannelID, e.g. D0123
SLACK_MCP_ADD_MESSAGE_TOOL=D0123 slack-cli conversations add D0123 -t "ping"

# Last day of a channel as JSON, extract message text with jq
slack-cli conversations history #general --limit 1d | jq -r '.[].Text'

# Download an image (or any binary) attachment to a file. -o writes the decoded
# bytes and keeps stdout to a small metadata JSON — use it for images/binaries so
# a multi-MB base64 blob doesn't flood the terminal.
slack-cli attachments get F0123ABCD -o avatar.png
# Without -o the bytes come back inline, base64-encoded under .content — decode with:
slack-cli attachments get F0123ABCD | jq -r .content | base64 --decode > avatar.png

Common issues

  • no Slack credentials — set SLACK_MCP_XOXP_TOKEN (or xoxb, or xoxc+xoxd) or run slack-cli auth login.
  • users cache is not ready / empty channels list / #name not found — run slack-cli cache refresh first, or pass IDs with --no-cache.
  • conversations_add_message tool is disabled / reactions / mark disabled — set the matching env var (SLACK_MCP_ADD_MESSAGE_TOOL, SLACK_MCP_REACTION_TOOL, SLACK_MCP_MARK_TOOL) in the same command. (attachments get needs no env var.)
  • search / saved / unreads return nothing or error — bot tokens (xoxb) can't search and lack edge APIs; use xoxp or browser tokens. saved needs browser tokens.
  • slow first run — the initial cache refresh (or first read with no cache) crawls the whole workspace; subsequent calls read the cached file.
  • multi-line post looks mangled (literal \n / backticks executed) — the shell received escaped or interpolated content. Write actual newlines to a file with your file tool, then use --text-file … --content-type text/mrkdwn. Delete the bad message with chat.delete, then repost.
  • need to delete a message — no CLI subcommand; call https://slack.com/api/chat.delete with the xoxp token from slack-cli auth token (see recipe above).

Facts

Kind
Skill
Repo
paymog/slack-cli
Group
Uncategorized
Installs
7.2k
Stars
0

More on this shelf

  1. 1find-skillsvercel-labs/skillsHelps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.3.8M
  2. 2grill-memattpocock/skillsA relentless interview to sharpen a plan or design.1.3M
  3. 3grill-with-docsmattpocock/skillsA relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.1.1M
  4. 4agent-browservercel-labs/agent-browserBrowser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.1.1M
  5. 5improve-codebase-architecturemattpocock/skillsScan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.1.1M
  6. 6tddmattpocock/skillsTest-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.1.1M