npx skills add ...
npx skills add michaelliv/dotskills --skill slack-cli
Interact with Slack from the command line. Send messages, read channel history, list channels and users, upload files, manage reminders, and more. Use when the user wants to communicate with Slack, check messages, or automate Slack workflows.
npx skills add michaelliv/dotskills --skill slack-cli
Interact with Slack workspaces from the command line using slack-cli and direct Slack API calls.
Assume
slack-cliis already installed and configured. If theslackcommand is not found or returnsnot_inited, refer to references/INSTALLATION.md for setup instructions.
If slack is not available or not configured, see references/INSTALLATION.md for full setup instructions.
The token is stored at the path configured in the slack binary's etcdir variable (typically /opt/homebrew/etc/slack-cli/.slack on macOS). You can also use the SLACK_CLI_TOKEN environment variable.
Store the Slack token in the global psst vault:
For built-in commands, inject the token via psst:
For direct API calls, use inline psst get:
The slack CLI supports these commands natively:
All commands support:
--filter|-f <jq-filter> — Apply a jq filter to the JSON response--compact|-cp — Compact JSON output--monochrome|-m — No color in jq output--trace|-x — Enable bash trace for debuggingslack chat send 'msg' '@user' often fails with channel_not_found. Use the direct API pattern below instead.chat:write appear as the Slack App, not as your user. This is a Slack API limitation — even with a user token, the app identity is used.The slack CLI doesn't cover all Slack API methods. For anything beyond the built-in commands, call the Slack API directly using curl. Read the token from the CLI's config file.
The built-in slack chat send doesn't handle DMs well. Use the API directly:
Requires
im:writescope. Without it,conversations.openwill fail. If you don't haveim:write, you can work around it by finding an existing DM channel:
#name format for built-in commands, but direct API calls require channel IDs (e.g. CHANNEL_ID)--filter with any built-in command to extract specific fields via jq--filter '.ts + "\n" + .channel' to chain send/update/deletecursor and limit parameters — check response_metadata.next_cursor in the responsecurl -s -H "Authorization: Bearer $(psst --global get SLACK_CLI_TOKEN)" "https://slack.com/api/users.list" | jq -r '.members[] | select(.real_name | test("Name"; "i")) | {name, id, real_name}'https://<workspace>.slack.com/archives/<channel_id>/p<ts_without_dot> — remove the dot from the message timestamp (e.g. ts 1769935497.539749 becomes p1769935497539749)curl -s -H "Authorization: Bearer $(psst --global get SLACK_CLI_TOKEN)" "https://slack.com/api/..."# Send a message
slack chat send 'Hello world!' '#channel'
# Send with rich formatting
slack chat send --text 'text' --channel '#channel' --color good --title 'Title' --pretext 'Pretext'
# Pipe content as a message
echo "some output" | slack chat send --channel '#channel'
# Update a message (requires timestamp and channel)
slack chat update 'Updated text' 1405894322.002768 '#channel'
# Delete a message
slack chat delete 1405894322.002768 '#channel'
# Chain: send, capture ts+channel, then update
slack chat send 'hello' '#general' --filter '.ts + "\n" + .channel' | \
xargs -n2 slack chat update 'goodbye'# Upload a file
slack file upload README.md '#channel'
# Upload with metadata
slack file upload README.md '#channel' --comment 'See attached' --title 'README'
# Create a Slack post from markdown
slack file upload --file post.md --filetype post --title 'Post Title' --channels '#channel'
# List files
slack file list
slack file list --filter '[.files[] | {id, name, size}]'
# File info / delete
slack file info F2147483862
slack file delete F2147483862# Add a reminder
slack reminder add 'lunch' $(date -v +30M "+%s")
# List / complete / delete
slack reminder list
slack reminder complete Rm7MGABKT6
slack reminder delete Rm7MGABKT6slack snooze start 60 # Start snooze for 60 minutes
slack snooze info # Check your snooze status
slack snooze end # End snoozeslack presence active
slack presence away# Step 1: Open (or find) the DM channel with a user
DM_CHANNEL=$(curl -s -X POST \
-H "Authorization: Bearer $(psst --global get SLACK_CLI_TOKEN)" \
-H "Content-Type: application/json" \
-d '{"users":"USER_ID"}' \
"https://slack.com/api/conversations.open" | jq -r '.channel.id')
# Step 2: Send the message
curl -s -X POST \
-H "Authorization: Bearer $(psst --global get SLACK_CLI_TOKEN)" \
-H "Content-Type: application/json" \
-d "{\"channel\":\"${DM_CHANNEL}\",\"text\":\"Hello!\"}" \
"https://slack.com/api/chat.postMessage"