| name | slackctl |
| description | Slack automation CLI for AI agents. Use when:
- Reading a Slack message or thread (given a URL or channel+ts)
- Browsing recent channel messages / channel history
- Getting all unread messages across channels
- Searching Slack messages or files
- Sending, editing, or deleting a message; adding/removing reactions
- Uploading files/images to channels or threads (including stdin piping)
- Downloading Slack files and attachments to local paths
- Listing, inspecting, or deleting files
- Listing channels/conversations; creating channels and inviting users
- Fetching a Slack canvas as markdown
- Looking up Slack users
- Marking channels/DMs as read
- Opening DM or group DM channels
Triggers: "slack message", "slack thread", "slack URL", "read slack", "reply on slack", "search slack", "channel history", "recent messages", "mark as read", "unread messages", "unread", "what did I miss", "upload file", "send image", "download file", "slack file", "attach file"
|
Slack automation with slackctl
slackctl is a single-binary CLI on $PATH. Invoke directly (e.g. slackctl user get @alice).
Installation
slackctl is a single static binary with no runtime dependencies, available for macOS, Linux, and Windows (amd64 + arm64).
If slackctl is not found on $PATH, install it for the current OS:
- macOS / Linux (recommended) — Homebrew:
brew tap cluas/tap
brew install slackctl
- Windows (recommended) — Scoop:
scoop bucket add cluas https://github.com/cluas/scoop-bucket
scoop install slackctl
- Any OS with Go installed:
go install github.com/cluas/slackctl/cmd/slackctl@latest
- Manual (any OS): download the archive for your OS/arch from the releases page, extract it, and put
slackctl (or slackctl.exe on Windows) on your PATH.
CRITICAL: Bash command formatting rules
Claude Code's permission checker has security heuristics that force manual approval prompts. Avoid these patterns to keep commands auto-allowed.
- No
# anywhere in the command string. Use bare channel names (general not #general).
- No
'' (consecutive single quotes) or "" (consecutive double quotes). Triggers "potential obfuscation" check.
- Only
| jq for filtering — no python3, no other commands. jq with single-quote-only expressions (no " inside) is safe:
- RIGHT:
slackctl search messages "query" | jq '.messages[] | .ts'
- No
|| or && chains. Run multiple slackctl commands as separate Bash tool calls.
- No file redirects (
>, >>). Process JSON output directly, don't write to files.
Quick start (auth)
Auth auto-detection works on macOS, Linux, and Windows. It reads credentials
straight from local apps (no browser automation), trying Slack Desktop first,
then Chrome, then Firefox. Cookie decryption is handled per-platform: macOS
Keychain, Linux Secret Service (secret-tool), and Windows DPAPI.
Per-source platform support:
Source (auth import-*) | macOS | Linux | Windows |
|---|
import-desktop (Slack Desktop) | ✅ | ✅ | ✅ |
import-chrome | ✅ | ✅ | ✅ |
import-brave | ✅ | ✅ | ✅ |
import-firefox | ✅ | ✅ | ✅ |
Notes: On Linux, Chrome/Brave/Slack cookie decryption reads the key from the
desktop keyring via secret-tool (install libsecret-tools / libsecret),
falling back to the default peanuts password when no keyring is configured.
Firefox cookies.sqlite is plaintext on every platform.
If credentials aren't available, run one of:
- Slack Desktop import (macOS/Linux/Windows):
slackctl auth import-desktop
slackctl auth test
- Firefox fallback (macOS/Linux/Windows):
slackctl auth import-firefox
slackctl auth test
- Chrome fallback (macOS/Linux/Windows):
slackctl auth import-chrome
slackctl auth test
export SLACK_TOKEN="xoxc-..."
export SLACK_COOKIE_D="xoxd-..."
export SLACK_WORKSPACE_URL="https://myteam.slack.com"
slackctl auth test
slackctl auth add --workspace-url https://myteam.slack.com --xoxc xoxc-... --xoxd xoxd-...
slackctl auth test
Check configured workspaces:
slackctl auth whoami
Canonical workflow (given a Slack message URL)
- Fetch a single message:
slackctl message get "https://workspace.slack.com/archives/C123/p1700000000000000"
- If you need the full thread:
slackctl message list "https://workspace.slack.com/archives/C123/p1700000000000000" --thread-ts 1700000000.000000
Browse recent channel messages
slackctl message list "general" --limit 20
slackctl message list "C0123ABC" --limit 10
Get unread messages
List all channels with unread messages:
slackctl message unread --limit 20
Also fetch the actual unread message content:
slackctl message unread --fetch --max-per-channel 5
Note: For Enterprise Grid, use --workspace with the enterprise URL for unread counts:
slackctl message unread --workspace longbridge-group --fetch
Send, edit, delete, or react
slackctl message send "general" "here is the report"
slackctl message send U01AAAA "hello via DM"
slackctl message send "general" "threaded reply" --thread-ts 1700000000.000000
slackctl message edit "general" 1700000000.000000 "updated text"
slackctl message delete "general" 1700000000.000000
slackctl message react add "general" 1700000000.000000 "eyes"
slackctl message react remove "general" 1700000000.000000 "eyes"
Send to a user ID opens a DM automatically.
List channels + create/invite
slackctl channel list
slackctl channel list --limit 50
slackctl channel new "incident-war-room"
slackctl channel new "incident-leads" --private
slackctl channel invite "incident-war-room" "U01AAAA,U02BBBB"
Files (upload, download, list, info, delete)
Upload a file to a channel or thread:
slackctl file upload ./report.pdf "general" --title "Weekly Report" --message "Here is this week's report"
slackctl file upload ./screenshot.png "general" --thread-ts 1700000000.000000
slackctl file upload ./photo.jpg U01AAAA --message "Check this out"
Upload from stdin (pipe):
cat output.log | slackctl file upload - "general" --filename "build.log" --title "Build Log"
Download a file:
slackctl file download F0123ABCDEF --output ./downloaded.png
slackctl file download F0123ABCDEF --url-only
List, inspect, delete files:
slackctl file list --channel "general" --limit 10
slackctl file list --types images --limit 20
slackctl file info F0123ABCDEF
slackctl file delete F0123ABCDEF
Search (messages + files)
slackctl search messages "deploy failed" --limit 10
slackctl search files "report" --limit 5
Mark as read
slackctl channel mark "general" 1700000000.000000
Canvas
Fetch a Slack canvas and convert to Markdown:
slackctl canvas get "https://workspace.slack.com/docs/T123/F456"
slackctl canvas get F0123ABCDEF
Users
slackctl user list --limit 100
slackctl user get "@alice"
slackctl user get U01AAAA
Multi-workspace
If you have multiple workspaces, pass --workspace to disambiguate:
slackctl message list "general" --workspace "myteam" --limit 10
slackctl auth set-default https://myteam.slack.com
All output is JSON
All commands output JSON to stdout. Use | jq for filtering:
slackctl user get U01AAAA | jq '.email'
slackctl message list "general" --limit 5 | jq '.[].text'
References