Slack Chat API CLI is a lightweight command-line interface designed to interact directly with the Slack Web API. It provides developers and IT professionals with a powerful toolset for automating tasks and scripting interactions within Slack, such as sending messages, managing channels, listing users, viewing message history, and searching through messages or files.
Key Features:
Direct API Access: Enables seamless integration with Slack’s Web API for automation and scripting.
Channel Management: Create, archive, modify topics, and invite users to channels.
Message Operations: Send, update, delete, and view message history in public and private channels.
User Interaction: List users, retrieve user information, and manage permissions.
Search Capabilities: Efficiently search through messages and files using user tokens for enhanced functionality.
Audience & Benefit:
Ideal for developers, DevOps engineers, and IT professionals seeking to automate Slack workflows. This tool streamlines team communication and operational efficiency by enabling script-driven interactions with Slack’s ecosystem, such as automating notifications or managing channel permissions directly from the command line.
Available via winget for easy installation, this CLI is a versatile addition to any automation toolkit.
README
slack-chat-cli
A lightweight command-line interface for interacting with the Slack Web API.
Not the Official Slack CLI
This project is not affiliated with Slack or Salesforce. If you're looking to build Slack apps with workflows, triggers, and datastores, check out the official Slack CLI.
go install github.com/open-cli-collective/slack-chat-api/cmd/slck@latest
Manual Build
git clone https://github.com/open-cli-collective/slack-chat-api.git
cd slack-chat-api
make build
Platform Support
Credentials are stored in the OS keyring via the shared cli-common/credstore
library:
Platform
Credential Storage
macOS
Keychain
Windows
Credential Manager
Linux
Secret Service (D-Bus); fails closed if a working keyring is locked. Encrypted-file backend only when there is no keyring at all, or by explicit opt-in (keyring.backend: file in config.yml).
Tokens are never written to a plaintext file. Non-secret config
(credential_ref, workspace) lives in ~/.config/slack-chat-api/config.yml.
Credential Resolution
At runtime the only source of a token is the OS keyring. Environment
variables are not read as credentials at runtime (per the Open CLI
Collective Secret-Handling Standard §1.11) — they are accepted only as
ingress during setup, e.g. slck init --bot-token-from-env SLACK_BOT_TOKEN
or op read ... | slck set-credential --key bot_token --stdin.
> Migrating from an older slck? On first run, any tokens from a previous
> version (old macOS Keychain items under service slck/slack-chat-api, or
> the legacy ~/.config/slack-chat-api/credentials file) are moved into the
> keyring automatically, once, then the originals are removed. A one-line
> notice is printed to stderr (and a _migration block to JSON output).
Extended manifest — every read scope slck can use, plus all writes (DMs, group DMs, file uploads, canvas CRUD, etc.)
Use this if you want maximum capability out of the box — reading DMs and group DMs, uploading file attachments to any channel/DM/group-DM, creating/editing/deleting canvases, resolving @subteam mentions, extended user profile data, etc. Every scope here is either needed by an existing slck command or unlocks a capability that commonly extends one (e.g. im:history so slck messages thread works on DMs, files:write for slck messages send --file, canvases:write for slck canvas create).
Upgrading an existing install? Paste the full manifest above into your app's Features → App Manifest tab (replacing the previous manifest), click Save Changes, then click Install App → Reinstall to Workspace to grant the new scopes. Copy the fresh xoxb-… token and run slck init (or slck set-credential).
Click Create → Install to Workspace → Allow
Copy the Bot User OAuth Token (starts with xoxb-)
Run the interactive setup:
slck init
# Paste your token when prompted (input is not echoed back)
Your token is stored in the OS keyring (Keychain / Credential Manager /
Secret Service). It is never written to a plaintext file.
NOTE: If you plan on sending messages or taking actions using your user token (See: Choosing Between Bot and User Tokens), you'll need to adjust the manifest above to have all the same scopes configured for your user as your bot (with the exception of the "channels:manage" scope, which only applies to bots).
Scripted / non-interactive setup
The token is read only from stdin or a named env var — never a flag or
positional value (so it can't leak via shell history or ps):
# From a pipe (preferred for automation):
op read 'op://Personal/slck/bot_token' | slck set-credential --key bot_token --stdin
# Or, during full init, from a named env var (the env var is consumed at
# setup time only; it is NOT read on subsequent runs):
slck init --bot-token-from-env SLACK_BOT_TOKEN --user-token-from-env SLACK_USER_TOKEN
1Password integration
Because the token lives in the keyring after setup, you do not wrap every
invocation in op. Stage it once:
op read 'op://Personal/slck/bot_token' | slck set-credential --key bot_token --stdin
op read 'op://Personal/slck/user_token' | slck set-credential --key user_token --stdin
Replace the op://… references with your own 1Password secret references.
Re-run only when the token rotates.
Required Scopes
The manifest above includes these scopes:
Scope
Purpose
channels:read
List public channels, get channel info
channels:history
Read message history from public channels
channels:manage
Create, archive, set topic/purpose, invite users
chat:write
Send, update, delete messages
emoji:read
List custom workspace emoji
files:read
Download files, get file info
groups:read
List private channels
groups:history
Read message history from private channels
reactions:write
Add/remove reactions
team:read
Get workspace info
users:read
List users, get user info
search:read
Search messages and files (user token only)
The extended manifest (see the collapsible section above) adds these capabilities on top of the default:
Scope
Unlocks
im:history / im:read / im:write
Read messages in DMs, list DMs, open new DMs to post to
mpim:history / mpim:read / mpim:write
Same for multi-person DMs (group DMs)
files:write
Upload files — slck messages send --file in any channel/DM/group-DM
OAuth & Permissions → User Token Scopes → Add search:read
Reinstall app to workspace (if already installed)
Copy the User OAuth Token (starts with xoxp-)
Setup-time env-var ingress (read once during slck init, never at runtime):
Flag
Description
slck init --bot-token-from-env NAME
Read the bot token from env var NAME at setup
slck init --user-token-from-env NAME
Read the user token from env var NAME at setup
Global Flags
These flags are available on all commands:
Flag
Short
Default
Description
--output
-o
text
Output format: text, json, or table
--no-color
false
Disable colored output
--as-user
false
Use user token
--as-bot
false
Use bot token
--version
-v
Show version information
--help
-h
Show help for any command
Choosing Between Bot and User Tokens
By default, all commands other than search use your bot token. You can set the SLCK_AS_USER env var to true to make your user token the default. You can also use flags to specify which token to use for any specific command (and this will override the default behavior set by your env var).
# Send a message as yourself (using user token)
slck messages send --as-user C1234567890 "Hey team!"
# Set default to user token via environment variable
export SLCK_AS_USER=true
slck messages send C1234567890 "Uses user token by default"
# If the default is user token, you can override back to bot token for a specific command
export SLCK_AS_USER=true
slck messages send --as-bot C1234567890 "Uses bot token"
Usage
Channels
# List all channels
slck channels list
# List with options
slck channels list --types public_channel,private_channel # Include private channels
slck channels list --limit 50 # Limit results
slck channels list --exclude-archived=false # Include archived channels
# Get channel info
slck channels get C1234567890
# Create a channel
slck channels create my-new-channel
slck channels create private-channel --private
# Archive/unarchive
slck channels archive C1234567890
slck channels unarchive C1234567890
# Set topic/purpose
slck channels set-topic C1234567890 "New topic"
slck channels set-purpose C1234567890 "Channel purpose"
# Invite users
slck channels invite C1234567890 U1111111111 U2222222222
Channels Command Reference
Command
Flags
Description
list
--types, --limit, --exclude-archived
List channels
get
Get channel details
create
--private
Create a channel
archive
--force
Archive a channel (prompts for confirmation)
unarchive
Unarchive a channel
set-topic
Set channel topic
set-purpose
Set channel purpose
invite ...
Invite users to channel
Users
# List all users
slck users list
slck users list --limit 50
# Get user info
slck users get U1234567890
# Search users
slck users search "john"
slck users search "john@company.com" --field email
slck users search "John Smith" --field display_name
slck users search "bot" --include-bots
Users Command Reference
Command
Flags
Description
list
--limit
List all users
get
Get user details
search
--limit, --field, --include-bots
Search users by name, email, or display name
Users Search Flags
Flag
Default
Description
--limit
1000
Maximum users to search through
--field
all
Search field: all, name, email, display_name
--include-bots
false
Include bot users in results
Messages
# Send a message (uses Block Kit formatting by default)
slck messages send C1234567890 "Hello, *world*!"
# Send using --channel flag (alternative to positional arg)
slck messages send --channel general "Hello team"
# Send from stdin (use "-" as text argument)
echo "Hello from stdin" | slck messages send C1234567890 -
cat message.txt | slck messages send C1234567890 -
# Send plain text (no formatting)
slck messages send C1234567890 "Plain text" --simple
# Send with custom Block Kit blocks
slck messages send C1234567890 "Fallback" --blocks '[{"type":"section","text":{"type":"mrkdwn","text":"*Bold*"}}]'
# Reply in a thread
slck messages send C1234567890 "Thread reply" --thread 1234567890.123456
# Upload files with a message
slck messages send C1234567890 "Here's the report" --file ./report.csv
slck messages send C1234567890 --file ./a.csv --file ./b.csv
# Update a message
slck messages update C1234567890 1234567890.123456 "Updated text"
slck messages update C1234567890 1234567890.123456 "Plain update" --simple
# Delete a message
slck messages delete C1234567890 1234567890.123456
# Get channel history
slck messages history C1234567890
slck messages history C1234567890 --limit 50
slck messages history C1234567890 --oldest 1234567890.000000 # After this time
slck messages history C1234567890 --latest 1234567890.000000 # Before this time
# Get thread replies
slck messages thread C1234567890 1234567890.123456
slck messages thread C1234567890 1234567890.123456 --limit 50
slck messages thread C1234567890 1234567890.123456 --since 1234567890.000000 # Only newer replies
# Add/remove reactions
slck messages react C1234567890 1234567890.123456 thumbsup
slck messages unreact C1234567890 1234567890.123456 thumbsup
Messages Command Reference
Command
Flags
Description
send
--thread, --blocks, --simple, --channel, --file
Send a message (use - for stdin)
update
--blocks, --simple
Update a message
delete
--force
Delete a message (prompts for confirmation)
history
--limit, --oldest, --latest
Get channel history
thread
--limit, --since
Get thread replies
react
Add reaction
unreact
Remove reaction
Search
> Note: Search requires a user token (xoxp-*). See Token Types.
These flags provide an alternative to using modifiers in the query string:
Flag
Description
--scope
Search scope: all, public, private, dm, mpim
--in
Filter by channel (e.g., #general or general)
--from
Filter by user (e.g., @alice or alice)
--after
Content after date (YYYY-MM-DD)
--before
Content before date (YYYY-MM-DD)
--has-link
Messages containing links
--has-reaction
Messages with reactions
--type
File type filter (files only, e.g., pdf, image)
--has-pin
Files that are pinned (files only)
Workspace
# Get workspace info
slck workspace info
Emoji
# List custom workspace emoji
slck emoji list
# Include aliases
slck emoji list --include-aliases
Emoji Command Reference
Command
Flags
Description
list
--include-aliases
List custom workspace emoji
Files
# Download a file by ID
slck files download F0AHF3NUSQK
# Download to a specific path
slck files download F0AHF3NUSQK --output report.pdf
# Download using a Slack file URL
slck files download "https://files.slack.com/files-pri/T.../F0AHF3NUSQK/file.csv"
> Note: Canvas commands require additional Slack app scopes not included in the default manifest. See Slack Canvas API docs for required scopes.
Identity
# Show authenticated identity (bot, user, workspace)
slck whoami
Config
# Guided interactive setup (bot + optional user token)
slck init
# Set one credential from stdin (scriptable; no value on the command line)
op read 'op://Personal/slck/bot_token' | slck set-credential --key bot_token --stdin
# Show current config status (backend, ref, which keys present — never values)
slck config show
# Delete stored token(s)
slck config delete-token
Set to true or 1 to default to user token instead of bot token
SLACK_CHAT_API_KEYRING_BACKEND
Force the keyring backend (e.g. file) — non-secret selector (§1.4)
SLACK_CHAT_API_KEYRING_PASSPHRASE
Passphrase for the encrypted-file backend (the one runtime secret-env exception, §1.4)
NO_COLOR
Disable colored output when set
XDG_CONFIG_HOME
Custom config directory (default: ~/.config)
> SLACK_API_TOKEN / SLACK_USER_TOKEN are no longer read at runtime
> (§1.11). Use slck init --bot-token-from-env / slck set-credential to
> stage a token into the keyring instead.
Known Limitations
Message Length Limits
Slack silently truncates messages exceeding 40,000 characters. slck validates message length before sending and returns an error with suggestions:
Upload as a file: slck messages send C123 --file ./content.txt
Create a canvas: slck canvas create --title "Title" --file ./content.md
Unarchiving Channels
Bot tokens (xoxb-) cannot unarchive channels due to a Slack API limitation. When a channel is archived, the bot is automatically removed from it, and bot tokens require membership to unarchive.