# Slack App Manifest Guide This guide documents what the Slack app for `clisbot` needs right now, what is optional, and what can wait. It is based on the current code paths in `src/channels/slack/*` and the current docs as of 2026-04-27. The shipped `app-manifest.json` is a setup-friendly template, not a strict minimum-permission manifest. This guide is the truth source for separating core requirements from optional or future permissions. ## How To Read This - `Required now`: needed for current `clisbot` Slack behavior to work truthfully. - `Optional now`: not required for core operation; useful only for specific features or safer future expansion. - `Future`: not needed by the current code, but plausible long-term if Slack support gets broader. ## Non-Manifest Requirement Socket Mode also needs an app-level token: | Requirement | Type | Why it exists | If missing | Long-term need | | --- | --- | --- | --- | --- | | `xapp-...` app token with `connections:write` | App-level token | Lets Bolt connect through Slack Socket Mode | Slack runtime does not start | Required as long as `clisbot` keeps Slack on Socket Mode | This is not listed under bot scopes in the manifest, but it is still mandatory for the current runtime model. ## Required Bot Scopes | Scope | Why `clisbot` needs it now | Current feature path | If missing | Long-term view | | --- | --- | --- | --- | --- | | `app_mentions:read` | Receive explicit `@bot` mentions | Mention-driven inbound turns | Explicit mentions stop reaching the bot | Required | | `chat:write` | Post, update, and clear Slack replies in threads | Normal reply sending, streaming edits, delete path, status fallback | The bot cannot reply normally | Required | | `channels:history` | Read routed public-channel messages and recover thread context | Public channels, thread follow-up, attachment hydration | Public-channel flow becomes unreliable or dead | Required if public channels are supported | | `channels:read` | Resolve public-channel names for prompt context | `conversations.info` display enrichment | Prompts fall back to raw Slack channel ids | Required for readable public-channel context | | `groups:history` | Read routed private-channel or group messages and recover thread context | Private groups, thread follow-up, attachment hydration | Private-group flow becomes unreliable or dead | Required if private groups stay supported | | `groups:read` | Resolve private-channel names for prompt context | `conversations.info` display enrichment | Prompts fall back to raw Slack private-channel ids | Required for readable private-channel context | | `im:history` | Read DM messages and hydrate DM context | Slack DMs, pairing, DM follow-up | DM handling becomes unreliable | Required if DMs stay supported | | `im:read` | Resolve DM surface metadata when Slack exposes it through conversation lookup | `conversations.info` display enrichment | DM prompts keep provider ids without richer labels | Required for readable DM context | | `im:write` | Open a DM when operator CLI targets `user:U...` | `clisbot message send --channel slack --target user:...` | User-targeted DM send path fails | Useful now, likely still needed | | `mpim:history` | Read multi-person DM messages and recover thread context | MPIM/group-style Slack conversations | MPIM routes cannot work truthfully | Required if MPIM routes stay supported | | `mpim:read` | Resolve MPIM names for prompt context | `conversations.info` display enrichment | MPIM prompts fall back to raw Slack ids | Required for readable MPIM context | | `reactions:read` | Read reactions through operator CLI | `clisbot message reactions` | Reaction inspection fails | Optional for chat bot core, required for full message CLI | | `reactions:write` | Add or remove processing reactions | Ack reaction, typing reaction, message CLI react/unreact | Bot still works, but reaction-based feedback degrades | Strongly recommended | | `pins:read` | List pins through operator CLI | `clisbot message pins` | Pin inspection fails | Optional for chat bot core, required for full message CLI | | `pins:write` | Add or remove pins through operator CLI | `clisbot message pin` and `unpin` | Pin mutation fails | Optional for chat bot core, required for full message CLI | | `files:write` | Upload media through operator CLI | `clisbot message send --media ...` | Slack media send path fails | Useful now, likely still needed | | `users:read` | Resolve sender names and handles for prompt context | `users.info` display enrichment | Prompts fall back to raw Slack user ids | Required for readable sender context | ## Required Event Subscriptions | Event | Why `clisbot` needs it now | Current feature path | If missing | Long-term view | | --- | --- | --- | --- | --- | | `app_mention` | Receive explicit bot mentions | First contact in channel threads, mention-only routes | Mention flow breaks | Required | | `message.channels` | Receive non-mention public-channel messages | Natural thread follow-up in public channels | Bot looks silent on plain thread replies | Required if public channels are supported | | `message.groups` | Receive non-mention private-group messages | Natural thread follow-up in private groups | Private-group follow-up fails | Required if private groups stay supported | | `message.im` | Receive DM messages | Slack DMs and pairing | DM routing fails | Required if DMs stay supported | | `message.mpim` | Receive multi-person DM messages | MPIM routes | MPIM routing fails | Required if MPIM routes stay supported | ## Optional Now These are not required for the current baseline to work, but they are reasonable only if you want the related feature or want less friction later. | Scope or setting | Why you might keep it | Current reality | Long-term view | | --- | --- | --- | --- | | `assistant:write` | Slack assistant thread status may still accept it in some environments | `clisbot` already degrades if this is unavailable, and current docs treat `chat:write` as enough for the status path | Low to medium; keep only if live Slack behavior proves it still helps | | `files:read` | Likely useful for richer inbound file handling and safer Slack file access | Current code downloads inbound files from Slack private URLs and may still benefit from this scope depending on Slack behavior | Medium; recommended if inbound attachments matter a lot | `files:read` is the main inference in this guide: the code does not call `files.info`, but inbound attachment download may still rely on Slack granting access to private file URLs. ## Future Or Nice-To-Have These are not needed by the current code paths, but they make sense only if Slack support grows. | Scope or setting | What it would unlock later | Current need | Long-term priority | | --- | --- | --- | --- | | `commands` | Native Slack slash-command endpoint instead of typed message commands | Not used now | Medium if native Slack UX becomes a product goal | | Interactivity enabled | Buttons, menus, modal submits, richer Block Kit actions | Not used now | Medium to high if structured Slack UI ships | | `users.profile:read` | Profile-aware status or routing help | Not used now | Low | | `users:read.email` | Email-aware identity mapping | Not used now | Low unless enterprise mapping becomes important | | `team:read` | Workspace metadata in status or diagnostics | Not used now | Low | | `incoming-webhook` | Incoming webhook delivery path | Not used now | Low | ## Not Needed In Current Manifest These are broad or legacy-looking for the current `clisbot` Slack design and should not be in the minimal manifest. | Permission group | Why it is not part of the minimal current-state manifest | | --- | --- | | All `user` scopes such as `search:read`, `search:read.files`, `search:read.private`, `search:read.im`, `search:read.users`, `search:read.mpim`, `search:read.public` | Current Slack integration is bot-token-driven; these user-token permissions are not used by the runtime | | `channel_history_changed` event | Not consumed by current code | | `function_executed` event | Not consumed by current code | | `app_home.messages_tab_enabled` and related App Home surface config | Not required for current chat-routing behavior | | `org_deploy_enabled` | Not needed for the current local or workspace-level setup story | | `function_runtime` | Not needed for the current Slack Socket Mode bot | ## Practical Recommendation If the goal is current `clisbot` Slack support with the least permission surface: 1. Keep the manifest small and truth-based. 2. Treat `chat:write`, the `history` scopes, the prompt-context read scopes, `app_mentions:read`, and the routed `message.*` events as the real core. 3. Keep `reactions:*`, `pins:*`, `files:write`, and `im:write` only if you want the full operator `message` CLI and richer Slack workflow support. 4. Keep `assistant:write` and `files:read` as explicitly optional, not silently mandatory. 5. Add `commands` or interactivity only when `clisbot` actually ships native Slack slash commands, buttons, or structured actions. For long-term product direction, the most strategically likely additions are: 1. `commands` 2. interactivity 3. possibly `files:read` Everything else should need a concrete feature before it goes back into the manifest.