# agent-slack Slack automation CLI for AI agents (TypeScript + Bun). Guiding principle: - **Token-efficient** — (compact JSON, minimal duplication, and empty/null fields pruned) so LLMs can consume results cheaply. - **Zero-config auth** — Auth just works if you have Slack Desktop (with fallbacks available). No Python dependency. - **Human-in-the-loop** — When appropriate (not in CI environments), loop humans in. Ex: `message draft` image ## Getting started Install via Bun (recommended): ```bash curl -fsSL https://raw.githubusercontent.com/stablyai/agent-slack/main/install.sh | sh ``` OR npm global install (requires Node >= 22.5): ```bash npm i -g agent-slack ``` OR run via Nix flake: ```bash nix run github:stablyai/agent-slack ``` ## At a glance - **Read**: fetch a message, browse channel history, list full threads - **Search**: messages + files (with filters) - **Artifacts**: auto-download snippets/images/files to local paths for agents - **Write**: send now or schedule delivery, edit/delete messages, add reactions (bullet lists auto-render as native Slack rich text) - **Channels**: list conversations, create channels, and invite users by id/handle/email - **Canvas**: fetch Slack canvases as Markdown ## Agent skill This repo ships an agent skill at `skills/agent-slack/` compatible with Claude Code, Codex, Cursor, etc **Install via [skills.sh](https://skills.sh)** (recommended): ```bash npx skills add stablyai/agent-slack ```
Manual installation ```bash bash ./scripts/install-skill.sh ```
## Command map (high level) ```text agent-slack ├── update # self-update (detects npm/bun/binary) ├── auth │ ├── whoami │ ├── test │ ├── import-desktop │ ├── import-brave │ ├── import-chrome │ ├── import-firefox │ └── parse-curl ├── message │ ├── get # fetch 1 message (+ thread meta ) │ ├── list # fetch thread or recent channel messages │ ├── send [text] # send / reply / schedule (supports --attach, --blocks) │ ├── scheduled │ │ ├── list # list pending scheduled messages │ │ └── cancel # cancel a pending scheduled message │ ├── draft [text] # open Slack-like editor in browser │ ├── edit # edit a message │ ├── delete # delete a message │ └── react │ ├── add │ └── remove ├── channel │ ├── list # list conversations (user-scoped or all) │ ├── new # create channel │ └── invite # invite users to channel ├── user │ ├── list │ └── get ├── search │ ├── all # messages + files │ ├── messages │ └── files ├── workflow │ ├── list # workflows bookmarked in a channel │ ├── preview # trigger metadata (no side effects) │ ├── get # workflow definition + form fields │ └── run # trip a workflow trigger └── canvas └── get # canvas → markdown ``` Notes: - Output is **always JSON** and aggressively pruned (`null`/empty fields removed). - Attached files are auto-downloaded and returned as absolute local paths. ## Authentication (no fancy setup) On macOS and Windows, authentication happens automatically: - Default: reads Slack Desktop local data (no need to quit Slack) - Fallbacks: if that fails, tries Chrome/Brave/Firefox extraction (macOS) You can also run manual imports: ```bash agent-slack auth whoami agent-slack auth import-desktop agent-slack auth import-brave agent-slack auth import-chrome agent-slack auth import-firefox agent-slack auth test ``` > [!NOTE] > `import-brave` / `import-chrome` read tokens from a logged-in Slack tab via AppleScript. Both browsers ship with **Allow JavaScript from Apple Events** disabled by default — enable it in **View → Developer** before running these commands. macOS will prompt for your password the first time. Alternatively, set env vars: ```bash export SLACK_TOKEN="xoxc-..." # browser token export SLACK_COOKIE_D="xoxd-..." # cookie d agent-slack auth test ``` Or use a standard Slack token (xoxb/xoxp): ```bash export SLACK_TOKEN="xoxb-..." agent-slack auth test ``` ## Targets: URL or channel `message get` / `message list` accept either a Slack message URL or a channel reference: - URL: `https://workspace.slack.com/archives//p[?thread_ts=...]` - Channel: `#general` (or bare `general`) or a channel ID like `C0123...` In practice: ```bash # Get a single message by channel + ts agent-slack message get "#general" --ts "1770165109.628379" # List a full thread by channel + thread root ts agent-slack message list "#general" --thread-ts "1770165109.000001" ``` If you have multiple workspaces configured and you use a channel **name** (`#channel` / `channel`), you must pass `--workspace` (or set `SLACK_WORKSPACE_URL`). `--workspace` accepts a full URL or a unique substring selector: ```bash agent-slack message get "#general" --workspace "https://stablygroup.slack.com" --ts "1770165109.628379" agent-slack message get "#general" --workspace "stablygroup" --ts "1770165109.628379" ``` ## Examples > [!TIP] > You should probably just use the skill for your agent instead of reading below. ### Read messages / threads ```bash # Single message (+ thread summary if threaded) agent-slack message get "https://workspace.slack.com/archives/C123/p1700000000000000" # Full thread for a message agent-slack message list "https://workspace.slack.com/archives/C123/p1700000000000000" # Recent channel messages (browse channel history) agent-slack message list "#general" --limit 20 # Recent channel messages that are marked with :eyes: agent-slack message list "#general" --with-reaction eyes --oldest "1770165109.000000" --limit 20 # Recent channel messages that do not have :dart: agent-slack message list "#general" --without-reaction dart --oldest "1770165109.000000" --limit 20 ``` Optional: ```bash # Include reactions + which users reacted agent-slack message get "https://workspace.slack.com/archives/C123/p1700000000000000" --include-reactions ``` ### Draft a message (browser editor) Opens a Slack-like WYSIWYG editor in your browser for composing messages with full formatting support (bold, italic, strikethrough, links, lists, quotes, code, code blocks). ```bash # Open editor for a channel agent-slack message draft "#general" # Open editor with initial text agent-slack message draft "#general" "Here's my update" # Reply in a thread agent-slack message draft "https://workspace.slack.com/archives/C123/p1700000000000000" ``` After sending, the editor shows a "View in Slack" link to the posted message. ### Reply, edit, delete, and react ```bash agent-slack message send "https://workspace.slack.com/archives/C123/p1700000000000000" "I can take this." agent-slack message send "#alerts-staging" "here's the report" --attach ./report.md agent-slack message send "#announcements" "Deploy starts at 6pm." --schedule "" agent-slack message send "U05BRPTKL6A" "Heads up before standup" --schedule-in "monday 9am" agent-slack message edit "https://workspace.slack.com/archives/C123/p1700000000000000" "I can take this today." agent-slack message delete "https://workspace.slack.com/archives/C123/p1700000000000000" agent-slack message react add "https://workspace.slack.com/archives/C123/p1700000000000000" "eyes" agent-slack message react remove "https://workspace.slack.com/archives/C123/p1700000000000000" "eyes" ``` Channel mode requires `--ts`: ```bash agent-slack message edit "#general" "Updated text" --workspace "myteam" --ts "1770165109.628379" agent-slack message delete "#general" --workspace "myteam" --ts "1770165109.628379" ``` `message send` and `message edit` convert bullet/numbered lists to Slack native rich text. Inline mentions, broadcasts, emoji shortcodes, and `<#C...>` channel references inside those lists are preserved as Slack elements. Send options for `message send`: - `--attach ` upload a local file (repeatable; `` is optional when attaching files) - `--blocks ` send raw [Block Kit](https://docs.slack.dev/block-kit/) blocks from a JSON file (or `-` for stdin). Bypasses the automatic markdown-to-rich-text conversion, unlocking header/divider/section/table blocks and other structured layouts. Cannot be combined with `--attach`. - `--reply-broadcast` when replying in a thread, also post the reply to the parent channel (Slack's "Also send to #channel" checkbox). 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