
Agent Slack
- 2.7k installs
- 520 repo stars
- Updated July 20, 2026
- stablyai/agent-slack
agent-slack is a Slack CLI for agents to read, search, draft, and explicitly send messages, channels, and attachments.
About
agent-slack exposes a CLI for agents to interact with Slack workspaces through read-heavy commands and guarded write operations. Installation uses a curl install script or npm global install requiring Node 22.5 or newer. Safety rules allow free read and search but block send, edit, delete, react, invite, create channels, mark read, schedule, upload, or cancel unless the user explicitly requests those actions, preferring message draft for composition. Auth flows cover whoami, import-desktop, import-brave, import-chrome, and import-firefox with auth test verification. Common commands fetch thread URLs, list channel history, search messages and files, draft and send with attachments, schedule sends, list unreads and later items, and open DMs. Multi-workspace support uses --workspace or SLACK_WORKSPACE_URL. Bundled references document command maps, URL versus channel targeting rules, and JSON output shapes for programmatic parsing.
- CLI for Slack read, search, draft, and explicit send operations.
- Safety gate: no writes unless user explicitly requests them.
- Auth import from desktop, Brave, Chrome, or Firefox sessions.
- Thread URL, channel history, search, and scheduled send commands.
- Multi-workspace targeting and bundled reference command maps.
Agent Slack by the numbers
- 2,726 all-time installs (skills.sh)
- +115 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #160 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
agent-slack capabilities & compatibility
- Capabilities
- slack url and channel message retrieval · message and file search across channels · draft first message composition · explicit send, schedule, and attachment upload · multi workspace auth and targeting
- Works with
- slack
- Use cases
- orchestration · email · research
- Platforms
- macOS · Linux · Windows
- Runs
- Runs locally
- Pricing
- Free
What agent-slack says it does
Do not send, edit, delete, react, invite, create channels, mark read, schedule, upload, or cancel scheduled messages unless explicitly asked.
npx skills add https://github.com/stablyai/agent-slack --skill agent-slackAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.7k |
|---|---|
| repo stars | ★ 520 |
| Security audit | 1 / 3 scanners passed |
| Last updated | July 20, 2026 |
| Repository | stablyai/agent-slack ↗ |
How can an agent safely read Slack threads and draft replies without unsolicited sends?
Read, search, draft, and explicitly send Slack messages, channels, threads, and attachments via the agent-slack CLI.
Who is it for?
Agents automating Slack research, thread summarization, and user-approved message drafting.
Skip if: Skip for Slack app OAuth development, bot framework backends, or unsolicited messaging.
When should I use this skill?
User needs Slack URL parsing, channel search, message drafts, or explicitly approved sends and schedules.
What you get
Authenticated CLI reads and searches with draft-first composition and explicit-send guardrails.
- slack messages read
- thread replies posted
- verified workspace credentials
Files
agent-slack
CLI on $PATH: agent-slack .... If missing, prefer:
curl -fsSL https://raw.githubusercontent.com/stablyai/agent-slack/main/install.sh | shFallback: npm i -g agent-slack (Node >= 22.5).
Safety: read/search freely. Do not send, edit, delete, react, invite, create channels, mark read, schedule, upload, or cancel scheduled messages unless explicitly asked. Prefer message draft.
Auth: agent-slack auth whoami; if needed auth import-desktop, auth import-brave, auth import-chrome, or auth import-firefox, then auth test.
Common commands:
agent-slack message get "SLACK_URL"
agent-slack message list "SLACK_URL"
agent-slack message list "general" --limit 20
agent-slack search messages "query" --channel "general"
agent-slack message draft "general" "text"
agent-slack message send "URL_OR_CHANNEL" "text" --attach ./file.md
agent-slack message send "general" "text" --schedule-in "3h"
agent-slack message scheduled list
agent-slack message scheduled cancel "SCHEDULED_ID" --channel "CHANNEL_ID"
agent-slack unreads
agent-slack later list
agent-slack canvas get "CANVAS_URL"
agent-slack workflow list "general"
agent-slack user list
agent-slack channel list
agent-slack user dm-open @alice @bobWith multiple workspaces, pass --workspace "team" or set SLACK_WORKSPACE_URL. Attachments include local path in JSON.
For non-trivial usage, read the bundled references:
- references/commands.md: command map and flags
- references/targets.md: URL vs channel targeting rules
- references/output.md: JSON shapes and download paths
agent-slack command map (reference)
Run agent-slack --help (or agent-slack <command> --help) for the full option list.
Auth
agent-slack auth whoami— show configured workspaces + token sources (secrets redacted)agent-slack auth test [--workspace <url-or-unique-substring>]— verify credentials (auth.test)agent-slack auth import-desktop— import browser-style creds from Slack Desktop (macOS/Windows)agent-slack auth import-brave— import creds from Brave (macOS; requires View → Developer → Allow JavaScript from Apple Events)agent-slack auth import-chrome— import creds from Chrome (macOS)agent-slack auth import-firefox— import creds from Firefox profile storage (macOS/Linux)agent-slack auth parse-curl— read a copied Slack cURL command from stdin and save credsagent-slack auth add --workspace-url <url> [--token <xoxb/xoxp> | --xoxc <xoxc> --xoxd <xoxd>]agent-slack auth set-default <workspace-url>agent-slack auth remove <workspace-url>
Messages / threads
agent-slack message get <target><target>: Slack message URL OR#channel/channel/channel id (C...) (seetargets.md)- Options:
--workspace <url-or-unique-substring>(required when using a channel _name_ across multiple workspaces)--ts <seconds>.<micros>(required when targeting a channel)--thread-ts <seconds>.<micros>(optional hint for thread permalinks)--max-body-chars <n>(default8000,-1unlimited)--include-reactions--resolve-users(attach resolved user profiles inreferenced_users)--refresh-users(implies--resolve-usersand forces a cache refresh)
agent-slack message list <target>- Lists recent channel messages (channel history), or fetches all thread replies
- Channel history (default when targeting a channel without
--thread-ts): agent-slack message list "general"— latest 25 messagesagent-slack message list "general" --limit 50— latest 50 messages- Thread mode (when
--thread-tsor--tsis provided, or target is a message URL): agent-slack message list "<url>"— all replies in that threadagent-slack message list "general" --thread-ts "1770165109.000001"— thread replies- Options:
--workspace <url-or-unique-substring>(same rules as above)--thread-ts <seconds>.<micros>(switches to thread mode; fetches replies)--ts <seconds>.<micros>(resolve a message to its thread)--limit <n>(default25, max200; channel history mode only)--oldest <ts>(only messages after this ts; channel history mode)--latest <ts>(only messages before this ts; channel history mode)--with-reaction <emoji>(repeatable; include only messages that have this reaction; channel history mode; requires--oldest)--without-reaction <emoji>(repeatable; include only messages that do not have this reaction; channel history mode; requires--oldest)--max-body-chars <n>(default8000,-1unlimited)--include-reactions--resolve-users(attach resolved user profiles inreferenced_users)--refresh-users(implies--resolve-usersand forces a cache refresh)
agent-slack message draft <target> [text]- Opens a Slack-like WYSIWYG editor in the browser for composing and sending a message.
- Formatting toolbar: bold, italic, strikethrough, links, numbered/bulleted lists, quotes, inline code, code blocks.
- Toggle between rich-text editing and raw mrkdwn source view.
- After sending, shows a "View in Slack" permalink to the posted message.
- If
<target>is a Slack message URL, the draft will reply in that thread. - Options:
--workspace <url-or-unique-substring>(needed for channel _names_ across multiple workspaces)--thread-ts <seconds>.<micros>(optional, channel mode only)
agent-slack message send <target> [text]- If
<target>is a Slack message URL, replies in that message’s thread. - Otherwise posts to the channel/DM.
[text]is optional when uploading files with--attach; when present, it becomes the initial comment on the first uploaded file.- Bullet lists (
-,*,•,1., etc.) are automatically converted to Slack’s native rich text format, so recipients see real editable bullets instead of plain-text dashes. Inline mentions, broadcasts, emoji shortcodes, and<#C...>channel references inside those lists are preserved as Slack elements. - Example:
agent-slack message send "general" "Coverage report" --attach ./report.md - Example:
agent-slack message send "general" "Monday launch checklist" --schedule-in "monday 9am" - Options:
--workspace <url-or-unique-substring>(needed for channel _names_ across multiple workspaces)--thread-ts <seconds>.<micros>(optional, channel mode only)--attach <path>(repeatable; upload local files as attachments)--blocks <path>raw Block Kit blocks from a JSON file (or-for stdin). Bypasses markdown-to-rich-text conversion; enables header/divider/section/table blocks. Cannot be combined with--attach.--reply-broadcastwhen replying in a thread, also post the reply to the parent channel. For channel targets, pair with--thread-ts; for URL targets, the thread context is derived from the message. Not supported for DM targets; cannot be combined with--attach.--schedule <time>schedule delivery at an ISO 8601 timestamp with explicit timezone (or Unix timestamp). Must be in the future and within Slack's 120-day scheduled-send limit. Compatible with--blocks,--thread-ts, and--reply-broadcast; cannot be combined with--attach.--schedule-in <duration>schedule delivery after a duration or simple future phrase (30m,3h,2d,tomorrow 9am,monday 9am; phrases use your local timezone). Mutually exclusive with--schedule; cannot be combined with--attach.
agent-slack message scheduled list- Lists pending scheduled messages from Slack's server-side scheduled message queue.
- Options:
--workspace <url-or-unique-substring>(defaults to configured workspace)--channel <channel>filter to a channel/DM id or channel name--oldest <unix-ts>only messages scheduled after this time--latest <unix-ts>only messages scheduled before this time--cursor <cursor>fetch the next page--limit <n>max messages to return
agent-slack message scheduled cancel <scheduled_message_id>- Cancels a pending scheduled message before it is sent.
- Options:
--channel <channel>required channel/DM id or channel name for the scheduled message--workspace <url-or-unique-substring>(needed for channel _names_ across multiple workspaces)
agent-slack message edit <target> <text>- URL target edits that exact message.
- Channel target requires
--ts. - Inline formatting is sent as text; bullet/numbered lists are converted to Slack native rich text. Inline mentions, broadcasts, emoji shortcodes, and
<#C...>channel references inside those lists are preserved as Slack elements. - Options:
--workspace <url-or-unique-substring>(needed for channel _names_ across multiple workspaces)--ts <seconds>.<micros>(required for channel targets)
agent-slack message delete <target>- URL target deletes that exact message.
- Channel target requires
--ts. - Options:
--workspace <url-or-unique-substring>(needed for channel _names_ across multiple workspaces)--ts <seconds>.<micros>(required for channel targets)
agent-slack message react add <target> <emoji>agent-slack message react remove <target> <emoji>- Options (channel mode):
--workspace <url-or-unique-substring>(needed for channel _names_ across multiple workspaces)--ts <seconds>.<micros>(required for channel targets)
Channels
agent-slack channel list [--workspace <url-or-unique-substring>] [--user <U...|@handle|handle> | --all] [--limit <n>] [--cursor <cursor>]- Default mode calls
users.conversationsfor the current user. --userresolves handles/ids and lists conversations for that user.--allswitches toconversations.list(mutually exclusive with--user).- Returns one page and optional
next_cursor; pass--cursorto continue. agent-slack channel new --name <name> [--private] [--workspace <url-or-unique-substring>]agent-slack channel invite --channel <id|name> --users "<U...,@handle,email,...>" [--workspace <url-or-unique-substring>]- Internal invite (default): resolves users (
U...,@handle,handle,email) and usesconversations.invite - External invite: add
--external(email targets only) to useconversations.inviteShared - Optional:
--allow-external-user-invitessetsexternal_limited=falsefor external invites agent-slack channel mark <target> [--ts <seconds>.<micros>] [--workspace <url-or-unique-substring>]- Marks a channel/DM as read up to the given message timestamp (
conversations.mark) - URL target extracts channel, ts, and workspace automatically;
--tsoptionally overrides the URL timestamp;--workspaceis rejected - Channel name/ID target requires
--ts
Later
agent-slack later list— list saved-for-later messages (default: in-progress)- Options:
--workspace <url-or-unique-substring>(defaults to configured workspace)--state <state>(filter:in_progress(default),archived,completed,all)--limit <n>(max items, default20)--max-body-chars <n>(max content chars per message, default4000,-1unlimited)--counts-only(only show counts per state)
agent-slack later complete <target>— mark a saved message as completedagent-slack later archive <target>— archive a saved messageagent-slack later reopen <target>— move back to in-progress (from completed or archived)agent-slack later save <target>— save a message for lateragent-slack later remove <target>— remove from Later entirely- All accept Slack message URL or channel ID with
--ts - Options:
--workspace <url-or-unique-substring>,--ts <seconds>.<micros>
agent-slack later remind <target> --in <duration>— set a reminder on a saved item--inaccepts:30m,1h,3h,2d,tomorrow,monday, or a unix timestamp- Options:
--workspace <url-or-unique-substring>,--ts <seconds>.<micros>
Unreads
agent-slack unreads— show all unread messages across channels, DMs, and threads- Options:
--workspace <url-or-unique-substring>(defaults to configured workspace)--counts-only(only show unread counts, skip message content)--max-messages <n>(max unread messages per channel, default10)--max-body-chars <n>(max content chars per message, default4000,-1unlimited)--include-system(include system messages like joins, leaves, topic changes; excluded by default)
Search
agent-slack search all <query>— messages + files (default)agent-slack search messages <query>agent-slack search files <query>
Common options:
--workspace <url-or-unique-substring>(recommended when using channel names across multiple workspaces)--channel <channel...>repeatable (#name,name, or id)--user <@name|name|U...>--after YYYY-MM-DD--before YYYY-MM-DD--content-type any|text|image|snippet|file--limit <n>(default20)--max-content-chars <n>(default4000,-1unlimited; messages only)--resolve-users(attach resolved user profiles inreferenced_users; applies tosearch messages/search all)--refresh-users(implies--resolve-usersand forces a cache refresh)
Canvas
agent-slack canvas get <canvas-url-or-id>- Options:
--workspace <url-or-unique-substring>(required when passing an id and multiple workspaces)--max-chars <n>(default20000,-1unlimited)
Workflows
agent-slack workflow list <channel> [--workspace <url-or-unique-substring>]— list workflows bookmarked or featured in a channelagent-slack workflow preview <trigger-id> [--workspace <url-or-unique-substring>]— get workflow metadata from a trigger ID (no side effects)agent-slack workflow get <id> [--workspace <url-or-unique-substring>]— get workflow definition including form fields and steps (acceptsFt...orWf...)agent-slack workflow run <trigger-id> --channel <id-or-name> [--workspace <url-or-unique-substring>]— trip a workflow trigger
Users
agent-slack user list [--workspace <url-or-unique-substring>] [--limit <n>] [--cursor <cursor>] [--include-bots]agent-slack user get <U...|@handle|handle> [--workspace <url-or-unique-substring>]agent-slack user dm-open <users...> [--workspace <url-or-unique-substring>]— get DM or group DM channel ID for one or more users (max 8)
Output + downloads (reference)
Output format
All commands print JSON to stdout.
- Empty values are pruned (
null,[],{}are removed where possible). auth whoamiredacts secrets in its output.
Message shapes (high-level)
message getreturns:message: { ... }thread?: { ts, length }(summary only; present when threaded)referenced_users?: { [user_id]: { id, name?, real_name?, display_name?, ... } }
message listreturns:messages: [ ... ](the full thread)referenced_users?: { [user_id]: { id, name?, real_name?, display_name?, ... } }- Messages are compact and omit redundant fields on each item where possible.
message sendreturns:ok: truechannel_id: "C..." | "D..."ts?: "<seconds>.<micros>"— the posted message's ts; absent on file-attachment sendsthread_ts?: "<seconds>.<micros>"— present only when the send was into an existing threadpermalink?: "https://.../archives/..."— present whentsis known and a workspace URL was resolvablescheduled_message_id?: "Q..."— present for--schedule/--schedule-insendspost_at?: <unix-seconds>— present for scheduled sends
message scheduled listreturns:scheduled_messages: [{ id, channel_id, post_at, date_created?, text? }]next_cursor?: "<cursor>"
message scheduled cancelreturns:ok: truechannel_id: "C..." | "D..."scheduled_message_id: "Q..."
Message payload fields keep canonical user IDs (for example author.user_id, reaction users[], and @U... mentions in rendered content). referenced_users provides display metadata for those IDs. The cache is per-workspace with a 24-hour per-entry TTL. This behavior is opt-in and requires passing the --resolve-users flag (or --refresh-users to bypass the cache).
Use --max-body-chars to cap message bodies for token budget control.
Later shape (high-level)
later listreturns:counts: { in_progress, archived, completed, total }items: [{ channel_id, channel_name, ts, state, date_saved, message? }]messageincludesauthor,content,thread_ts,reply_count- Items sorted by most recently saved first
- With
--counts-only,itemsis omitted
later complete/archive/reopen/save/removereturns{ ok: true }later remindreturns{ ok: true, remind_at }
Unreads shape (high-level)
unreadsreturns:channels: [{ channel_id, channel_name, channel_type, unread_count, mention_count, messages? }]threads?: { has_unreads, mention_count }(present when there are unread thread replies)channel_typeis one of:"channel","dm","mpim","group"- Channels sorted by mention count (desc), then unread count (desc)
- System messages (joins, leaves, topic changes) are excluded by default; use
--include-systemto include them - With
--counts-only,messagesis omitted
Search shapes (high-level)
search messages|allreturnsmessages: [ ... ]search messages|allmay includereferenced_users?: { [user_id]: { id, name?, real_name?, display_name?, ... } }search files|allreturnsfiles: [ ... ]
Use --max-content-chars (messages) and --limit to control size.
Channel shapes (high-level)
channel listreturns:channels: [ ... ]next_cursor?: string(present when more pages are available)
channel newreturns:channel: { id, name, is_private }
channel invitereturns:- Internal invite mode:
channel_idinvited_user_ids: [ ... ]already_in_channel_user_ids?: [ ... ]unresolved_users?: [ ... ]- External invite mode (
--external): channel_idexternal: trueexternal_limited: booleaninvited_emails: [ ... ]already_invited_emails?: [ ... ]invalid_external_targets?: [ ... ]
channel markreturns:ok: booleanchannel: string(resolved channel ID)ts: string
File fields in compact messages
When messages include file attachments, each file object contains:
name— the original filename (e.g."report.pdf"), omitted if unavailablemimetype— MIME type (e.g."application/pdf")mode— Slack file mode (e.g."hosted","snippet")path— absolute local path to the downloaded file
Only files with a successful download are included.
Attachment downloads
Attachments are downloaded to an agent-friendly temp directory.
- Successful downloads are returned as absolute paths in output.
message get/listpreserves failed attachment downloads withmessage.files[].errorand keepsmessage.files[].pathpointing to a local.download-error.txtfile.- Message results from
search messages|allpreserve failed attachment downloads withmessages[].files[].errorand keepmessages[].files[].pathpointing to a local.download-error.txtfile. search filesskips files whose download fails and continues returning the remaining matches.
Default download root:
~/.agent-slack/tmp/downloads/
If XDG_RUNTIME_DIR is set, downloads live under:
$XDG_RUNTIME_DIR/agent-slack/tmp/downloads/
Targets: URL vs channel (reference)
agent-slack accepts either a Slack message URL (preferred) or a channel reference.
Preferred: Slack message URL
Use the message permalink whenever you have it:
https://<workspace>.slack.com/archives/<channel_id>/p<digits>[?thread_ts=...]Examples:
agent-slack message get "<url>"agent-slack message list "<url>"agent-slack message send "<url>" "reply text"agent-slack message edit "<url>" "updated text"agent-slack message delete "<url>"agent-slack message react add "<url>" "eyes"agent-slack channel mark "<url>"
Channel targets (when you don’t have a URL)
Channel references can be:
- channel name:
general(bare name, without#prefix) - channel id:
C...(orG.../D...)
message get by channel + --ts
agent-slack message get "general" --ts "1770165109.628379"message list by channel + --thread-ts (or --ts to resolve)
agent-slack message list "general" --thread-ts "1770165109.000001"
agent-slack message list "general" --ts "1770165109.628379"
agent-slack message list "general" --without-reaction dart --oldest "1770165109.000000" --limit 20Reactions by channel + --ts
agent-slack message react add "general" "eyes" --ts "1770165109.628379"Edit/delete by channel + --ts
agent-slack message edit "general" "updated text" --ts "1770165109.628379"
agent-slack message delete "general" --ts "1770165109.628379"Mark as read by channel + --ts
agent-slack channel mark "general" --ts "1770165109.628379"
agent-slack channel mark "D0A04PB2QBW" --ts "1770165109.628379"Channel admin by id/name
agent-slack channel invite --channel "general" --users "@alice,bob@example.com"
agent-slack channel invite --channel "C0123ABCDEF" --users "U01234567"
agent-slack channel invite --channel "shared-room" --users "partner@vendor.com" --external
agent-slack channel invite --channel "shared-room" --users "partner@vendor.com" --external --allow-external-user-invitesMulti-workspace ambiguity (channel names only)
If you have multiple workspaces configured and your target is a channel name (e.g. general), you must disambiguate:
- pass
--workspace "https://myteam.slack.com"(or a unique substring like--workspace "myteam"), or - set
SLACK_WORKSPACE_URLto the same selector format
Channel IDs (C.../G.../D...) do not require --workspace.
Related skills
FAQ
Can the agent send messages automatically?
No. Sends, edits, deletes, and reactions require explicit user request; prefer message draft otherwise.
How do I authenticate?
Run agent-slack auth whoami; if needed import from desktop or browser then auth test.
How are multiple workspaces handled?
Pass --workspace with the team name or set SLACK_WORKSPACE_URL for the target workspace.
Is Agent Slack safe to install?
skills.sh reports 1 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.