Slack
Comprehensive Slack control plane — channels, channel members, users, user-groups + memberships, messaging (post / update / delete / react / pin), files, scheduled messages, bots, and incident-channel inventory. Snapshot/diff/apply round-trip for the operator surface.
weave slack
Env: SLACK_BOT_TOKEN
Setup
Configure credentials via environment variables. We recommend sourcing them through 1Password or your secrets manager rather than committing them to the shell rc.
Official API reference
weave commands for this module are checked against the vendor's published API.
| Variable | Description | Status |
|---|---|---|
| SLACK_BOT_TOKEN | Required for authentication. | required |
| SLACK_USER_TOKEN | User token (xoxp-…) — falls back when SLACK_BOT_TOKEN can't reach an endpoint (some files / admin scopes) | optional |
Sanity-check the wiring:
weave secrets check weave slack --help weave doctor # reports SLACK_BOT_TOKEN status
Capabilities
What this module can do, by entity and verb. ✓
means a working CLI surface; · means
not (yet) wired.
| Entity | find | list | show | do | snapshot | diff | apply |
|---|---|---|---|---|---|---|---|
| bot | · | ✓ | · | · | · | · | · |
| channel | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| channel-member | · | ✓ | · | · | ✓ | ✓ | ✓ |
| emoji | · | ✓ | · | · | · | · | · |
| emoji-meta | · | · | · | · | ✓ | ✓ | · |
| file | · | ✓ | · | ✓ | · | · | · |
| incident | · | ✓ | · | · | · | · | · |
| message | · | · | · | ✓ | · | · | · |
| scheduled-message | · | ✓ | · | · | · | · | · |
| user | ✓ | ✓ | · | · | · | · | · |
| user-group | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ |
| user-group-channels | · | · | · | · | ✓ | ✓ | ✓ |
| user-group-members | · | · | ✓ | · | ✓ | ✓ | ✓ |
Commands
Every registered CLI command, grouped by verb. Each example uses placeholder arguments — substitute real values for your environment.
find (3)
find channel
readFind a channel by name.
weave slack find channel <name>
find user
readFind a Slack user by email or user_id.
weave slack find user <identifier>
find user-group
readFind a user-group by handle.
weave slack find user-group <handle>
list (9)
list bots
readList bot apps installed in the workspace.
weave slack list bots <arg>
list channel-members
readList members of a channel.
weave slack list channel-members <arg>
list channels
readList channels (public + private, paginated).
weave slack list channels <arg>
list emoji
readList custom emoji on the workspace.
weave slack list emoji <arg>
list files
readList uploaded files (paginated; filterable by channel/user).
weave slack list files <arg>
list incidents
readList currently-open incident channels (#incident-*).
weave slack list incidents <arg>
list scheduled-messages
readList messages scheduled for future delivery.
weave slack list scheduled-messages <arg>
list user-groups
readList user-groups in the workspace.
weave slack list user-groups <arg>
list users
readList workspace users (paginated).
weave slack list users <arg>
show (2)
show channel
readShow full detail for a channel.
weave slack show channel <channel>
show user-group-members
readShow member IDs of a user-group.
weave slack show user-group-members <handle-or-id>
do (24)
do add-to-usergroup
writeReplace a user-group's membership (Slack's API is full-replace).
weave slack do add-to-usergroup <handle-or-id>
do archive-channel
writeArchive a channel (irreversible-ish; admins can unarchive).
weave slack do archive-channel <channel>
do create-channel
writeCreate a channel (public or private).
weave slack do create-channel <name>
do create-user-group
writeCreate a new user-group (handle + name).
weave slack do create-user-group <handle>
do delete-file
writeDelete a file by id.
weave slack do delete-file <file-id>
do delete-message
writeDelete a message by ts.
weave slack do delete-message <arg>
do disable-user-group
writeDisable a user-group (members keep id-only assignments).
weave slack do disable-user-group <handle-or-id>
do enable-user-group
writeRe-enable a previously-disabled user-group.
weave slack do enable-user-group <handle-or-id>
do escalate-channel
writePost a structured incident escalation banner to a channel.
weave slack do escalate-channel <channel>
do invite
writeInvite a user to a channel.
weave slack do invite <arg>
do kick
writeKick a user from a channel.
weave slack do kick <arg>
do pin
writePin a message to the channel.
weave slack do pin <arg>
do post-ephemeral
writePost an ephemeral message only one user sees.
weave slack do post-ephemeral <arg>
do post-message
writePost a message to a channel.
weave slack do post-message <arg>
do react
writeAdd a reaction to a message.
weave slack do react <arg>
do remove-from-usergroup
writeRemove a user-group's membership entirely (resolves to setting users=).
weave slack do remove-from-usergroup <handle-or-id>
do rename-channel
writeRename a channel.
weave slack do rename-channel <channel>
do set-purpose
writeSet a channel's purpose.
weave slack do set-purpose <channel>
do set-topic
writeSet a channel's topic.
weave slack do set-topic <channel>
do unarchive-channel
writeUnarchive a previously-archived channel.
weave slack do unarchive-channel <channel>
do unpin
writeUnpin a message from the channel.
weave slack do unpin <arg>
do unreact
writeRemove a reaction from a message.
weave slack do unreact <arg>
do update-message
writeUpdate a previously-posted message by ts.
weave slack do update-message <arg>
do upload-file
writeUpload a file to a channel (uses files.getUploadURLExternal v2 flow).
weave slack do upload-file <path>
watch (1)
watch channel
writeTail new messages on a channel by polling conversations.history.
weave slack watch channel <channel>
snapshot → edit YAML →
diff → apply --yes (or confirm
interactively; apply --dry-run previews the same diff).
State kinds
Resources this module can snapshot and
diff; apply where the kind supports
live writes (see Round-trip per kind). Always run
diff before apply; use
--yes in automation after review. Files live under
.weave-state/slack/.
channels
Every public + private channel in the workspace (rename / topic / purpose / archive). Create/delete are kept as imperative `do` verbs.
State file skeleton
module: slack kind: channels items: - # <fields specific to this kind — see snapshot output>
channel-members
Membership of a single channel (apply invite/kick).
State file skeleton
module: slack kind: channel-members channel: <value> items: - # <fields specific to this kind — see snapshot output>
user-groups
Every user-group: handle, name, description, default channels. Apply creates and updates; disable uses the `do disable-user-group` verb.
State file skeleton
module: slack kind: user-groups items: - # <fields specific to this kind — see snapshot output>
user-group-members
Members of one user-group (Slack's API is full-replace; weave materializes the desired set and PUTs it once).
State file skeleton
module: slack kind: user-group-members user_group: <value> items: - # <fields specific to this kind — see snapshot output>
user-group-channels
Default channels announced to a user-group (full apply).
State file skeleton
module: slack kind: user-group-channels user_group: <value> items: - # <fields specific to this kind — see snapshot output>
emoji-meta
Custom emoji NAMES (snapshot + diff only — add/remove API requires admin-scope user tokens that weave does not request).
State file skeleton
module: slack kind: emoji-meta items: - # <fields specific to this kind — see snapshot output>
Workflows
End-to-end recipes from operators who already run this module in production. Copy, adapt, and put under change-control.
Onboard a new team to a project channel
Create the channel, invite users, set the topic — one transaction.
weave slack do create-channel platform-alpha --yes weave slack do set-topic #platform-alpha --topic 'Alpha rollout coordination' --yes weave slack do set-purpose #platform-alpha --purpose 'Cross-functional alpha launch channel' --yes weave slack do invite --channel #platform-alpha --user U01ALICE --yes weave slack do invite --channel #platform-alpha --user U01BOB --yes
Lockdown a compromised channel
Capture the membership for the postmortem, then archive.
weave slack list channel-members --channel #leaky-channel weave slack snapshot channel-members --channel #leaky-channel git add .weave-state/slack && git commit -m 'pre-archive snapshot' weave slack do archive-channel #leaky-channel --yes
Audit user-groups quarterly
Snapshot every user-group and its membership; diff next quarter.
weave slack snapshot user-groups
weave slack list user-groups --json | jq -r '.[].handle' \
| xargs -I{} weave slack snapshot user-group-members --user-group {}
git add .weave-state/slack && git commit -m 'user-group audit Q1'
# next quarter:
weave slack diff user-groups
weave slack diff user-group-members --user-group platform-oncall
Roll out a comms freeze
List every active channel, then broadcast a freeze notice with per-channel confirmation.
weave slack list channels --no-archived --json | jq -r '.[].id' > /tmp/channels
while read cid; do
weave slack do post-message --channel $cid \
--text ':snowflake: Comms freeze: no production changes until 17:00 UTC.' --yes
done < /tmp/channels
Tail an active incident channel
Stream real-time messages while you triage; Ctrl-C to stop.
weave slack list incidents weave slack watch channel #incident-2026-05-16 --interval 3
Terraform parity
For each Terraform resource in the canonical provider, here's the equivalent live-API verb in weave. Use this as a migration cheat-sheet, not a 1:1 contract — weave deliberately stays in the live-state lane, not the desired-state lane.
| Terraform resource | weave equivalent |
|---|---|
| slack_conversation | weave slack list/find/show channel + do create-channel/archive-channel/unarchive-channel/rename-channel/set-topic/set-purpose / snapshot channels |
| slack_conversation_members | weave slack list channel-members / do invite / do kick / snapshot channel-members |
| slack_user_group | weave slack list/find user-group / do create-user-group / do disable-user-group / do enable-user-group / snapshot user-groups |
| slack_usergroup_members | weave slack show user-group-members / do add-to-usergroup / snapshot user-group-members Slack's API is full-replace; weave materializes the desired set on apply. |
| slack_usergroup_channels | weave slack snapshot user-group-channels |
| (chat.postMessage / chat.postEphemeral) | weave slack do post-message / do post-ephemeral No TF resource — these are operator verbs. |
| (chat.update / chat.delete) | weave slack do update-message / do delete-message No TF resource — these are operator verbs. |
| (reactions.add / reactions.remove) | weave slack do react / do unreact No TF resource — these are operator verbs. |
| (pins.add / pins.remove) | weave slack do pin / do unpin No TF resource — these are operator verbs. |
| (files.list / files.upload / files.delete) | weave slack list files / do upload-file / do delete-file Upload uses Slack's modern files.getUploadURLExternal v2 flow. |
| (chat.scheduledMessages.list) | weave slack list scheduled-messages |
| (emoji.list / emoji.add / emoji.remove) | weave slack list emoji / snapshot emoji-meta Add/remove emoji require admin-scope user tokens — weave reads only. |
| (team.info / bot inventory) | weave slack list bots / list incidents / watch channel Operational verbs unique to weave — no Terraform equivalent. |
| (Enterprise Grid admin.* methods) | Not exposed Enterprise Grid scopes require workspace-org admin tokens; out of scope for weave. |
Troubleshooting & source
Run weave doctor — it reports which env
vars (including SLACK_BOT_TOKEN) are set
and which are blank.
Re-run weave slack diff <kind>
to confirm the controller's current state, then re-snapshot
before the next apply. The driver always re-snapshots
before diffing.
The module lives at https://github.com/andy-broyles/weavewhatever/tree/main/src/weave/modules/slack. File a bug or feature request at https://github.com/andy-broyles/weavewhatever/issues.