hivecode-mcp 0.14.1 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/HIVE_RULES.md +98 -98
  2. package/LICENSE +21 -21
  3. package/README.md +421 -421
  4. package/core.js +91 -91
  5. package/docs/ALWAYS_ON.md +310 -310
  6. package/docs/GITHUB_WORKFLOW.md +394 -394
  7. package/docs/HIVE_RULES.md +41 -41
  8. package/docs/MCP.md +157 -157
  9. package/docs/QUICKSTART.md +266 -266
  10. package/docs/SELF_HOSTING.md +256 -256
  11. package/docs/SLACK_SETUP.md +474 -474
  12. package/docs/TROUBLESHOOTING.md +106 -105
  13. package/hive-activity.js +336 -336
  14. package/hive-authors.js +46 -44
  15. package/hive-await.js +230 -230
  16. package/hive-branch.js +674 -607
  17. package/hive-busy.js +88 -88
  18. package/hive-coord.js +110 -110
  19. package/hive-gate.js +135 -135
  20. package/hive-github.js +3 -1
  21. package/hive-hook-install.js +179 -179
  22. package/hive-instructions.js +74 -74
  23. package/hive-land.js +709 -691
  24. package/hive-listen.js +81 -81
  25. package/hive-mailbox.js +520 -520
  26. package/hive-mcp-http.js +591 -591
  27. package/hive-mcp.js +92 -12
  28. package/hive-mux-proto.js +58 -58
  29. package/hive-mux.js +354 -351
  30. package/hive-notify.js +234 -233
  31. package/hive-obligations.js +247 -247
  32. package/hive-poll-proto.js +50 -50
  33. package/hive-pr-staleness.js +189 -189
  34. package/hive-pr.js +637 -512
  35. package/hive-privacy.js +327 -327
  36. package/hive-receipts.js +233 -233
  37. package/hive-relay-health.js +234 -234
  38. package/hive-repos.js +430 -430
  39. package/hive-room-key.js +210 -210
  40. package/hive-room-mode.js +1761 -1668
  41. package/hive-room-watcher.js +623 -561
  42. package/hive-secrets.js +89 -89
  43. package/hive-session.js +114 -114
  44. package/hive-setup.js +560 -560
  45. package/hive-slack-agent.js +408 -408
  46. package/hive-slack.js +2417 -2367
  47. package/hive-stdio.js +172 -172
  48. package/hive-stop-hook.js +293 -293
  49. package/hive-throttle.js +118 -118
  50. package/hive-time.js +71 -71
  51. package/hive-transport.js +617 -578
  52. package/hive-update.js +58 -58
  53. package/hive-version.js +110 -110
  54. package/hive-webhook.js +55 -54
  55. package/icr-merge.js +58 -58
  56. package/icr.js +856 -851
  57. package/lang-brace.js +305 -305
  58. package/lang-js.js +695 -651
  59. package/lang-json.js +211 -211
  60. package/lang-python.js +588 -588
  61. package/lang-ruby.js +230 -230
  62. package/lang-toml.js +136 -136
  63. package/lang-yaml.js +183 -183
  64. package/limits.js +413 -413
  65. package/package.json +11 -3
  66. package/reconcile.cjs +621 -621
  67. package/slack-app-manifest-agent.json +61 -61
  68. package/slack-app-manifest-inbound.json +36 -36
  69. package/slack-app-manifest.json +27 -27
  70. package/substrate.js +252 -252
  71. package/sync.js +434 -60
  72. package/token.js +201 -201
@@ -1,474 +1,474 @@
1
- # Slack Setup (Under 10 Minutes)
2
-
3
- Hivecode posts to Slack using **one thread per task** (for a live room) or **one thread per GitHub issue** (for the GitHub watcher). Only the opening message and the final outcome appear in the main channel; intermediate claims, gate checks, CI runs, and untasked room chatter stay inside threads so your channel is never flooded.
4
-
5
- ---
6
-
7
- ## 1. Create the Slack App from the Manifest (2 minutes)
8
-
9
- 1. Open [api.slack.com/apps](https://api.slack.com/apps) and click **Create New App** → **From a manifest**.
10
- 2. Pick your Slack workspace and switch the tab to **JSON**.
11
- 3. Paste the contents of [`slack-app-manifest.json`](../slack-app-manifest.json):
12
-
13
- ```json
14
- {
15
- "display_information": {
16
- "name": "Hivecode",
17
- "description": "One Slack thread per task or GitHub issue for Hivecode rooms.",
18
- "background_color": "#111318"
19
- },
20
- "features": {
21
- "bot_user": {
22
- "display_name": "Hivecode",
23
- "always_online": true
24
- }
25
- },
26
- "oauth_config": {
27
- "scopes": {
28
- "bot": [
29
- "chat:write",
30
- "channels:read",
31
- "groups:read"
32
- ]
33
- }
34
- },
35
- "settings": {
36
- "org_deploy_enabled": false,
37
- "socket_mode_enabled": false,
38
- "token_rotation_enabled": false
39
- }
40
- }
41
- ```
42
-
43
- 4. Click **Next** → **Create**, then click **Install to Workspace** and **Allow**.
44
- 5. In the left sidebar under **OAuth & Permissions**, copy the **Bot User OAuth Token** (`xoxb-…`). (After inviting `@Hivecode` to your channel in Step 2, run `SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack check --channel C0123456789` to verify the app end to end.)
45
-
46
- ---
47
-
48
- ## 2. Invite `@Hivecode` to Your Channel & Copy the Channel ID (1 minute)
49
-
50
- 1. In Slack, open the channel where you want threads posted and invite the bot:
51
- ```text
52
- /invite @Hivecode
53
- ```
54
- 2. Right-click the channel name (or click the channel header at the top) → **View channel details**.
55
- 3. Scroll to the bottom of the dialog and copy the **Channel ID** (looks like `C0123456789`).
56
- 4. Run **`slack check`** to prove your token, workspace, channel membership, scopes, and (when `SLACK_APP_TOKEN` is set) inbound Socket Mode event subscriptions work end to end before starting any workflow:
57
- ```bash
58
- SLACK_BOT_TOKEN=xoxb-… [SLACK_APP_TOKEN=xapp-…] npx -y hivecode-mcp@latest slack check --channel C0123456789
59
- ```
60
- *(This posts one message in `#your-channel` — `"Hivecode check: reply anything in this thread"` — and one reply in its thread once your reply arrives.)*
61
-
62
- ---
63
-
64
- ## 3. Run `slack check` First, Then Start
65
-
66
- Before starting a room bridge or the GitHub watcher, run **`slack check`** once. It verifies each piece of your Slack app in order (`token`, `workspace`, `channel`, `scopes`, `Socket Mode`), then posts `"Hivecode check: reply anything in this thread"` in `#your-channel` and waits up to 2 minutes for your reply so you know outbound posting **and** inbound event subscriptions actually work end to end.
67
-
68
- **macOS / Linux (bash, zsh):**
69
- ```bash
70
- # Outbound only (3-scope manifest):
71
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack check --channel C0123456789
72
-
73
- # Outbound + inbound stop/retry/replies (Socket Mode manifest):
74
- SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack check --channel C0123456789
75
-
76
- # Slack AI Agent surface + native stop button (Paid Slack plan manifest):
77
- SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack check --channel D0123456789 --agent
78
- ```
79
-
80
- **Windows (PowerShell):**
81
- ```powershell
82
- $env:SLACK_BOT_TOKEN="xoxb-…"
83
- $env:SLACK_APP_TOKEN="xapp-…" # optional: include when using inbound stop/retry/replies or --agent
84
- npx -y hivecode-mcp@latest slack check --channel C0123456789
85
- ```
86
-
87
- **What Each `slack check` Line Means & the One Fix When It Fails:**
88
-
89
- | Failing Step / Line | Cause | The One Fix |
90
- | :--- | :--- | :--- |
91
- | **`Q630 SLACK_BOT_TOKEN is missing` / `rejected by Slack (invalid_auth)`** | `SLACK_BOT_TOKEN` is unset, pasted from the wrong field, or revoked. | Copy the **Bot User OAuth Token** (`xoxb-…`) from **OAuth & Permissions** in your Slack app settings and export `SLACK_BOT_TOKEN` in the same terminal. |
92
- | **`Q634 Slack auth.test did not return a workspace team_id`** | Slack did not associate the token with a workspace. | Reinstall the app to your workspace under **OAuth & Permissions → Reinstall to Workspace**. |
93
- | **`Q631 @Hivecode is not a member of #channel`** | The bot has not been invited to the target channel. | Open `#channel` in Slack and run `/invite @Hivecode`. |
94
- | **`Q631 Slack channel … could not be accessed (missing_scope: needs groups:read)`** | Target channel is private, or the bot lacks the channel read scope (`needed` scope named in error). | Add the named scope (`groups:read` / `channels:read`) under **OAuth & Permissions → Bot Token Scopes** and click **Reinstall to Workspace**. |
95
- | **`Q634 SLACK_BOT_TOKEN is missing required inbound scope(s): users:read, channels:history`** | `SLACK_APP_TOKEN` is set for inbound `stop`/`retry`, but the app was created from the outbound-only manifest. | Recreate or update the app's manifest from [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) (Section 5 below) and click **Reinstall to Workspace**. |
96
- | **`Q634 SLACK_BOT_TOKEN is missing required agent scope(s): assistant:write, im:history`** | `--agent` (or `hive-slack-agent.js`) was started with a token from the outbound or inbound-only manifest. | Update the app's manifest from [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json) (Section 5 below) and click **Reinstall to Workspace**. |
97
- | **`Q634 SLACK_APP_TOKEN was rejected` / `Socket Mode did not open (no hello frame)`** | Socket Mode is disabled in the Slack app, or `SLACK_APP_TOKEN` (`xapp-…`) lacks `connections:write`. | Enable **Socket Mode** in your Slack app settings and generate a new App-Level Token (`xapp-…`) with `connections:write` under **Basic Information → App-Level Tokens**. |
98
- | **`Q634 Slack agents.sessions.setStatus returned warning missing_agent_session_stopped_event_subscription`** | `--agent` checked `agents.sessions.setStatus`, and Slack reported that `agent_session_stopped` is not subscribed (so the native stop button is not rendered). | Subscribe to `agent_session_stopped` by updating your app's manifest from [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json) and reinstalling. |
99
- | **`Q634 Slack agents.sessions.setStatus failed (feature_disabled)`** | The workspace is on a Free Slack plan or Agents & Assistants is disabled for the workspace. | Use [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) for typed `stop` / `retry` in channel threads (works on all Slack plans), or enable Agents & Assistants on a paid Slack plan. |
100
- | **`Q634 Slack agents.sessions.setStatus failed (thread_ts_required)`** | Slack rejected `agents.sessions.setStatus` because the DM session requires a valid `thread_ts`. | Run `slack check --channel <D…> --agent` on a DM or channel where `@Hivecode` can post a thread root message first. |
101
- | **`Q634 replies did not arrive. Event subscriptions are probably missing`** | You replied in the check thread, but Slack never sent the event (`message.channels` / `message.groups` / `message.im` not subscribed). | Update your app's manifest with [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) (or [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json) for `--agent`) and reinstall the app. |
102
- | **`Q635 Another process is already connected to Slack Socket Mode`** | Another running terminal or service is connected with the same `SLACK_APP_TOKEN` (e.g. `slack start`, `github start --slack-allow`, or `hive-slack-agent`). | Use a separate Slack app per process that reads Slack. If you recently stopped a bridge or watcher, wait a minute for Slack to release the socket and retry. |
103
-
104
- Once `slack check` passes, you can also run `--dry-run` on `slack start` or `github start` before launching:
105
-
106
- ### Option A — Bridge a Live Hivecode Room (`slack start`)
107
-
108
- > **Where do I get the `"wss://…|room-…"` link?** Running `npx -y hivecode-mcp@latest branch <name>` or `npx -y hivecode-mcp@latest setup` prints your room's `wss://…|room-…` link.
109
-
110
- **macOS / Linux (bash, zsh):**
111
- ```bash
112
- # 1. Verify token and channel membership first
113
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --dry-run
114
-
115
- # 2. Start the live bridge
116
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789
117
- ```
118
-
119
- **Windows (PowerShell):**
120
- ```powershell
121
- $env:SLACK_BOT_TOKEN="xoxb-…"
122
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --dry-run
123
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789
124
- ```
125
-
126
- **Windows (Command Prompt / `cmd.exe`):**
127
- ```cmd
128
- set SLACK_BOT_TOKEN=xoxb-…
129
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --dry-run
130
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789
131
- ```
132
-
133
- ---
134
-
135
- ### Option B — One Slack Thread per GitHub Issue (`github start --slack-channel`)
136
-
137
- When running the GitHub issue watcher (`docs/GITHUB_WORKFLOW.md`), pass `--slack-channel <id>` with `SLACK_BOT_TOKEN` set in your environment. Each labelled issue opens one Slack thread; PR ready for review, waiting on a person, and merged/closed are posted in the thread and broadcast to the channel (`reply_broadcast`), while run start, CI failures, the tester's verdict, fixes pushed to the PR, resumed, and stopped stay inside the thread only.
138
-
139
- If you also set `SLACK_APP_TOKEN=xapp-…` (see Section 5), replying `stop` in an issue's Slack thread stops that issue's run (and posts `/hivecode stop` on GitHub), and replying `retry` re-runs it for Slack user IDs listed in `--slack-allow <U123,U456>`.
140
-
141
- **macOS / Linux (bash, zsh):**
142
- ```bash
143
- # 1. Dry-run first (checks gh auth, repo, and Slack token/channel)
144
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789 --dry-run
145
-
146
- # 2. Start watching issues
147
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789
148
- ```
149
-
150
- **Windows (PowerShell):**
151
- ```powershell
152
- $env:SLACK_BOT_TOKEN="xoxb-…"
153
- npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789 --dry-run
154
- npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789
155
- ```
156
-
157
- **Windows (Command Prompt / `cmd.exe`):**
158
- ```cmd
159
- set SLACK_BOT_TOKEN=xoxb-…
160
- npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789 --dry-run
161
- npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789
162
- ```
163
-
164
- ---
165
-
166
- ## 4. What Gets Posted (and What Is Scrubbed)
167
-
168
- | Source | Shown in Channel | Inside the Thread Only |
169
- | :--- | :--- | :--- |
170
- | **GitHub Watcher (`--slack-channel`)** | Thread opening post (`#12 — Title`), plus thread replies broadcast to the channel (`reply_broadcast`): PR ready for review, waiting on a person (`hivecode:needs-human`), merged / closed | Run started, CI failed, the tester's verdict, resumed, stopped |
171
- | **Room Bridge (`slack start`)** | `task-open` and `task-done` | Gate pass/fail (`gate-pass`, `gate-fail`), task chat, and all untasked room chat (grouped inside one shared room thread so chatter never floods the channel) |
172
-
173
- - **What `slack start` announces, and when**: it watches the room's task list and gate results as well as its chat. A new task opens its thread (and appears in the channel); when the assignee completes it, the "done" reply is also broadcast to the channel. A gate pass or fail is posted inside the shared room thread. The first time a bridge ever attaches to a room it only records what is already there, so starting it never replays the room's history; what it has announced is kept in room state (`slack_seen`), so a restart does not repeat itself. A forced gate release is not posted as a gate result: it is already in room chat.
174
- - **Secret & Room Link Scrubbing**: Every message passes through `scrubSlack()` before leaving your machine. API keys, tokens, bearer headers, room capability links (`wss://…|room-…`), and room IDs (`room-…`) are stripped automatically.
175
- - **Rate Limits & Retries**: Slack's ~1 message/second per-channel pacing is enforced by a single outbound queue. HTTP `429` (`ratelimited`) responses are retried up to 5 times honouring `Retry-After`.
176
- - **Durable Thread State**: Thread timestamps (`thread_ts`) are stored in room state (`slack_threads` map) for `slack start` and in `.git/hivecode/github.json` for `github start --slack-channel`, so restarting the process continues posting into the existing Slack thread.
177
-
178
- ---
179
-
180
- ## 5. Stopping Agents & Replying from Slack (Optional — Socket Mode)
181
-
182
- By default, `slack-app-manifest.json` requests only the three outbound scopes (`chat:write`, `channels:read`, `groups:read`). If you also want to **stop/resume agents** or **reply in task threads** from Slack (with zero public webhook URL), enable **Socket Mode**:
183
-
184
- ### Privacy & Scope Notice
185
- Inbound Socket Mode requires adding `channels:history`, `groups:history`, and `users:read` to **Bot Token Scopes**, plus an **App-Level Token** (`SLACK_APP_TOKEN=xapp-…`) with `connections:write` and Event Subscriptions for `message.channels` and `message.groups`.
186
- > **Plain-spoken scope warning:** `channels:history` and `groups:history` let the bot read every message posted in the channels you invite it to. If you only want outbound thread feeds, keep the default 3-scope manifest above.
187
-
188
- <details>
189
- <summary><strong>Optional Inbound Manifest (Socket Mode enabled — <code>slack-app-manifest-inbound.json</code>)</strong></summary>
190
-
191
- Paste the contents of [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json):
192
-
193
- ```json
194
- {
195
- "display_information": {
196
- "name": "Hivecode",
197
- "description": "One Slack thread per task or GitHub issue, with inbound stop and thread replies.",
198
- "background_color": "#111318"
199
- },
200
- "features": {
201
- "bot_user": {
202
- "display_name": "Hivecode",
203
- "always_online": true
204
- }
205
- },
206
- "oauth_config": {
207
- "scopes": {
208
- "bot": [
209
- "chat:write",
210
- "channels:read",
211
- "groups:read",
212
- "channels:history",
213
- "groups:history",
214
- "users:read"
215
- ]
216
- }
217
- },
218
- "settings": {
219
- "event_subscriptions": {
220
- "bot_events": [
221
- "message.channels",
222
- "message.groups"
223
- ]
224
- },
225
- "org_deploy_enabled": false,
226
- "socket_mode_enabled": true,
227
- "token_rotation_enabled": false
228
- }
229
- }
230
- ```
231
- </details>
232
-
233
- ### Generating the App-Level Token (`SLACK_APP_TOKEN`)
234
- 1. In your Slack app settings, go to **Basic Information** and scroll down to **App-Level Tokens**.
235
- 2. Click **Generate Token and Scopes**.
236
- 3. Enter `socket-mode` as the **Token Name** (required by Slack), click **Add Scope**, select `connections:write`, and click **Generate**.
237
- 4. Copy the resulting `xapp-…` token and set it as `SLACK_APP_TOKEN`.
238
-
239
- ### Networks That Refuse WebSockets (Cloud VMs): `--inbound`
240
- Socket Mode is a WebSocket. Some networks refuse every WebSocket upgrade. One example is Antigravity's cloud VM, whose proxy answers `403 WebSocket upgrades are not allowed`. On such a network the bridge reads Slack over plain HTTPS instead: `conversations.history` for the channel and `conversations.replies` for the threads it tracks.
241
-
242
- | `--inbound` (or `HIVE_SLACK_INBOUND`) | What it does |
243
- | --- | --- |
244
- | `auto` (default) | Socket Mode when `SLACK_APP_TOKEN` is set. If the network refuses the upgrade with an HTTP status, it switches to HTTPS polling and prints `[hivecode] Slack replies are read over HTTPS every 3 s (...)`. Without `SLACK_APP_TOKEN`, it is outbound only, as before. |
245
- | `poll` | HTTPS polling only. **Needs no `SLACK_APP_TOKEN`**, just a bot token from [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) (`channels:history` or `groups:history`, plus `users:read`). |
246
- | `socket` | Socket Mode only. Never polls. |
247
-
248
- ```bash
249
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack check --channel C0123456789 --inbound poll
250
- SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack start "<relay|room>" --channel C0123456789 --allow U123 --inbound poll
251
- ```
252
-
253
- What to know about polling:
254
- - **Speed:** a reply reaches the room within about `HIVE_SLACK_POLL_MS` (default 3000 ms). Socket Mode is near-instant.
255
- - **Restarts:** where it stopped reading is kept in the room and on disk, so a restarted bridge neither replays old messages nor skips new ones. Two bridges on one room claim each message before acting, so a `stop` is acted on once.
256
- - **Downtime:** after the bridge has been offline, messages older than `HIVE_SLACK_CATCHUP_MS` (default 30 minutes) are **not acted on**. A two-hour-old `resume` should not fire. The bridge posts once in the room's thread with the offline window and the count, so nobody assumes they were handled. Send it again if it still matters.
257
- - **Rate limits:** two reads per poll, more while tracked threads are active. A `429` is honoured with Slack's `Retry-After`.
258
- - `--agent` (the native stop button) needs Socket Mode and cannot poll.
259
-
260
- ### Strict or Secured Rooms: the Bridge Needs a Human Token
261
- `stop` and `resume` from Slack change the room's controls, and the relay lets only a human change controls: an AI's write is reverted. The bridge acts for a named Slack person, so it joins as a human. On an open room this works with no token. On a **strict or secured room**, start the bridge with a human (or admin/maintainer) token in the link or `HIVE_TOKEN`. Otherwise the relay reverts the stop, so check the agents' state in the room after your first `stop`.
262
-
263
- ### Who May Act (`--allow` / `--slack-allow`) & No Impersonation
264
- - **STOP is fail-safe**: Any full member of your Slack workspace may type `stop`, `stop all`, or `stop <AgentName>` in a thread to pause agents (or stop an active GitHub issue run) immediately. If Slack's `users.info` endpoint fails during an outage, `stop` still succeeds and notes `(stopped; I could not confirm who you are)`.
265
- - **RESUME, RETRY, and thread replies require the allowlist (`--allow U123,U456` on `slack start`, or `--slack-allow U123,U456` on `github start`)**: Only Slack user IDs explicitly listed in the allowlist (find yours in Slack under **Profile → `⋯` → Copy member ID**) may resume agents (`resume`, `resume all`, `resume <AgentName>`), retry a GitHub issue run (`retry`), or send replies into the room. If the allowlist is omitted, inbound is **stop-only**.
266
- - **Guests & Slack Connect users are refused**: Single-channel/multi-channel guests (`is_restricted` / `is_ultra_restricted`) and external Slack Connect users from other workspaces (`team_id` mismatch via `users.info`) are refused for all actions (including `stop`) and receive a refusal reply in the thread.
267
- - **One Slack app per process (Socket Mode multi-connection guard)**: Each process that reads Slack (`slack start`, `github start --slack-allow`, or `hive-slack-agent`) requires its own dedicated Slack app and App-Level Token (`xapp-…`). Slack Socket Mode supports up to 10 connections per token and arbitrarily distributes incoming events across them without channel routing. Sharing an app token across two processes causes events (including `stop all` and thread replies) to split between the two processes (`Q635`).
268
- - **No impersonation (`slack:<handle>`)**: Every message delivered from Slack into the room is attributed as `slack:<handle>` (for example, `slack:ganesh`), never as a bare room member name (`Ganesh`), so a Slack display name cannot impersonate the room owner.
269
-
270
- ### Free vs Paid Slack Plans & the Slack AI Agent Surface (`hive-slack-agent.js`)
271
- - **Typed `stop` works on every Slack plan (including Free)**: Replying `stop`, `stop all`, `stop <AgentName>`, `resume <AgentName>`, or `retry` in a channel thread requires only standard channel events (`slack-app-manifest-inbound.json`) and works on **all Slack plans**. We keep `slack-app-manifest-inbound.json` separate from `slack-app-manifest-agent.json` so Free-plan workspaces can install inbound `stop`/`retry` without hitting `feature_disabled`.
272
- - **Native AI stop button & streamed plan cards (`hive-slack-agent.js`) require a paid Slack plan**: `hive-slack-agent.js` renders live room tasks as a streamed plan (`chat.startStream` / `chat.appendStream` / `chat.stopStream` with `task_display_mode: "plan"`) and enables Slack's native stop button via `agents.sessions.setStatus` (`status: "processing"` / `"active"`) and `agent_session_stopped`.
273
- - **Who may act on the agent surface (same rules as `slack start`)**: `hive-slack-agent.js` checks every sender with the same `makeSlackActorCheck` rules. Any full workspace member may `stop` / `stop all` (or press Slack's native stop button); if Slack's `users.info` is down it still stops, and says `(stopped; I could not confirm who you are)`. `resume` needs the sender's member ID in `--allow <U123,U456>` (or `SLACK_ALLOW`). Guests and users from other workspaces are refused for everything, `status` included, and are told so in the thread; the room's tasks are never streamed to them. At startup it needs your workspace id from `auth.test` (refused with `Q634` if Slack omits it). A typed message counts only in the configured `--channel` or in a DM with the app (each user's own assistant DM is answered in that DM); messages from any other channel the bot is in are ignored.
274
- - **Official Slack requirements for `hive-slack-agent.js`**:
275
- - **Bot Token Scopes**: `chat:write` ([`chat.startStream`](https://docs.slack.dev/reference/methods/chat.startStream)), `assistant:write` ([`agents.sessions.setStatus`](https://docs.slack.dev/reference/methods/agents.sessions.setStatus) and [`agent_session_stopped`](https://docs.slack.dev/reference/events/agent_session_stopped)), `im:history`, `im:read`, `im:write` ([Developing AI Apps](https://docs.slack.dev/ai/developing-ai-apps)), plus `channels:read`, `groups:read`, `channels:history`, `groups:history`, `users:read`.
276
- - **Bot Events**: `agent_session_stopped` ([`agent_session_stopped` event](https://docs.slack.dev/reference/events/agent_session_stopped)), `assistant_thread_started`, `assistant_thread_context_changed`, `message.im`, `message.channels`, `message.groups`.
277
- - **App Settings**: `features.assistant_view` (`assistant_description` and `suggested_prompts`) and `settings.socket_mode_enabled: true` ([Agent Sessions](https://docs.slack.dev/ai/agent-sessions)).
278
- - **Startup & `slack check --agent` verification**:
279
- - At startup, `hive-slack-agent.js` (`preflightSlackAgent`) checks `x-oauth-scopes` from `auth.test` via `checkAgentScopes` and refuses with `Q634` (naming missing scopes such as `assistant:write, im:history` and `slack-app-manifest-agent.json`) before opening Socket Mode.
280
- - Running `SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack check --channel D0123456789 --agent` verifies those scopes, posts a check message (`checkTs`), and calls `agents.sessions.setStatus({ status: 'processing', channel_id, thread_ts: checkTs })`. Per Slack's [`agent_session_stopped` docs](https://docs.slack.dev/reference/events/agent_session_stopped), if your app is not subscribed to `agent_session_stopped`, Slack returns a `missing_agent_session_stopped_event_subscription` warning (checked in both top-level `warning` and `response_metadata.warnings[]`) and renders a non-interactive spinner instead of the stop button; `slack check --agent` catches that warning (as well as `feature_disabled` and `thread_ts_required`) and refuses with `Q634`. On every exit path (pass, fail, timeout, or `Ctrl+C`), `slack check --agent` clears the session status back to `active` in a `finally` block so the DM is never left spinning.
281
- - *(Note: `features.assistant_view` and `suggested_prompts` control the top-bar split-view UI in Slack and cannot be probed via a Web API read call; installing from `slack-app-manifest-agent.json` configures them declaratively.)*
282
-
283
- **Starting the Agent Surface (`slack agent`):**
284
-
285
- macOS / Linux (bash, zsh):
286
- ```bash
287
- SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack agent "wss://hivecode-relay.onrender.com|room-abc123" --channel D0123456789 --allow U012ABCDEF
288
- ```
289
-
290
- Windows (PowerShell):
291
- ```powershell
292
- $env:SLACK_BOT_TOKEN="xoxb-…"
293
- $env:SLACK_APP_TOKEN="xapp-…"
294
- npx -y hivecode-mcp@latest slack agent "wss://hivecode-relay.onrender.com|room-abc123" --channel D0123456789 --allow U012ABCDEF
295
- ```
296
-
297
- <details>
298
- <summary><strong>Optional Paid-Plan AI Agent Surface Manifest (<code>slack-app-manifest-agent.json</code>)</strong></summary>
299
-
300
- Paste the contents of [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json):
301
-
302
- ```json
303
- {
304
- "display_information": {
305
- "name": "Hivecode",
306
- "description": "AI agent panel, native stop button, and one Slack thread per task or GitHub issue.",
307
- "background_color": "#111318"
308
- },
309
- "features": {
310
- "bot_user": {
311
- "display_name": "Hivecode",
312
- "always_online": true
313
- },
314
- "assistant_view": {
315
- "assistant_description": "Inspect live Hivecode rooms, stream task plans, and halt or resume AI agents from Slack.",
316
- "suggested_prompts": [
317
- {
318
- "title": "What is running?",
319
- "message": "status"
320
- },
321
- {
322
- "title": "Stop everything",
323
- "message": "stop all"
324
- },
325
- {
326
- "title": "What happened overnight?",
327
- "message": "what happened overnight"
328
- }
329
- ]
330
- }
331
- },
332
- "oauth_config": {
333
- "scopes": {
334
- "bot": [
335
- "chat:write",
336
- "assistant:write",
337
- "im:history",
338
- "im:read",
339
- "im:write",
340
- "channels:read",
341
- "groups:read",
342
- "channels:history",
343
- "groups:history",
344
- "users:read"
345
- ]
346
- }
347
- },
348
- "settings": {
349
- "event_subscriptions": {
350
- "bot_events": [
351
- "agent_session_stopped",
352
- "assistant_thread_started",
353
- "assistant_thread_context_changed",
354
- "message.im",
355
- "message.channels",
356
- "message.groups"
357
- ]
358
- },
359
- "org_deploy_enabled": false,
360
- "socket_mode_enabled": true,
361
- "token_rotation_enabled": false
362
- }
363
- }
364
- ```
365
- </details>
366
-
367
- **macOS / Linux (bash, zsh):**
368
- ```bash
369
- SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
370
- SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
371
- ```
372
-
373
- **Windows (PowerShell):**
374
- ```powershell
375
- $env:SLACK_BOT_TOKEN="xoxb-…"
376
- $env:SLACK_APP_TOKEN="xapp-…"
377
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
378
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
379
- ```
380
-
381
- **Windows (Command Prompt / `cmd.exe`):**
382
- ```cmd
383
- set SLACK_BOT_TOKEN=xoxb-…
384
- set SLACK_APP_TOKEN=xapp-…
385
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
386
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
387
- ```
388
-
389
- ### Slackbot Remote MCP Server (`hive-mcp-http.js`)
390
-
391
- If you connect Slackbot's remote MCP client over Streamable HTTP (`hive-mcp-http.js`), it exposes fast room inspection and control tools (`hive_status`, `hive_members`, `hive_tasks`, `hive_claims`, `hive_recent`, `hive_pause`, `hive_resume`, `hive_say`).
392
-
393
- - **Requires both `SLACK_SIGNING_SECRET` and `SLACK_BOT_TOKEN`**: In `--auth slack` mode (the default), `hive-mcp-http.js` refuses to start without `SLACK_SIGNING_SECRET` (`Q510`, copied from **Basic Information → App Credentials → Signing Secret**) **and** `SLACK_BOT_TOKEN` (`Q630`, `xoxb-…` with `users:read` scope so `users.info` can verify callers).
394
- - **Discovers your workspace (`team_id`) from Slack at startup**: When you start `hive-mcp-http.js` without `--team` (`SLACK_TEAM_ID`), it calls Slack's `auth.test` using `SLACK_BOT_TOKEN` before serving requests. If `auth.test` rejects the token (`Q630`) or does not return a `team_id` (`Q634`), startup is refused immediately so external Slack Connect workspace users can never slip through by default.
395
- - **Same access rules (`makeSlackActorCheck`)**:
396
- - **Every request is HMAC-verified first** (`X-Slack-Signature` + 5-minute replay window, `Q511`–`Q513`) before `_meta.slack.user_id` is read.
397
- - **Guests and other workspaces are refused** for all tools (`hive_pause`, `hive_resume`, `hive_say`).
398
- - **`hive_pause` (`stop`) is fail-safe** for any full member of your workspace (and fails open with `(stopped; I could not confirm who you are)` if `users.info` is unreachable during a Slack outage).
399
- - **`hive_resume` and `hive_say` require `--allow <U123,U456>`** (or `SLACK_ALLOW`). Messages sent via `hive_say` are recorded in room chat as `slack:<handle>`.
400
-
401
- **macOS / Linux (bash, zsh):**
402
- ```bash
403
- SLACK_SIGNING_SECRET=… SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack mcp-server "wss://hivecode-relay.onrender.com|room-abc123" --port 8790 --allow U012ABCDEF
404
- ```
405
-
406
- **Windows (PowerShell):**
407
- ```powershell
408
- $env:SLACK_SIGNING_SECRET="…"
409
- $env:SLACK_BOT_TOKEN="xoxb-…"
410
- npx -y hivecode-mcp@latest slack mcp-server "wss://hivecode-relay.onrender.com|room-abc123" --port 8790 --allow U012ABCDEF
411
- ```
412
-
413
- **What a First-Time User Sees Step by Step (`hive-mcp-http.js`):**
414
- 1. **If `SLACK_SIGNING_SECRET` is missing**: Process exits immediately (`code 2`) with:
415
- `Q510 --auth slack needs SLACK_SIGNING_SECRET. Use --auth none only on localhost.`
416
- 2. **If `SLACK_BOT_TOKEN` is missing**: Process exits immediately (`code 2`) with:
417
- `Q630 --auth slack needs SLACK_BOT_TOKEN. Set SLACK_BOT_TOKEN=xoxb-… in your environment (docs/SLACK_SETUP.md).`
418
- 3. **When both are set**: `hive-mcp-http.js` calls Slack `auth.test`, locks in your workspace `team_id`, joins the room, and prints:
419
- `[hive-mcp-http] room room-abc123 on :8790/ auth=slack`
420
- 4. **When someone asks Slackbot what is happening (`hive_status`)**: Returns the live room name, agent count, paused list, and task counts.
421
- 5. **When a coworker triggers `hive_pause`**: Pauses the named agent (or `all`) on its own client (`paused AgentA — it will finish its current step and then stop picking up work`), while a guest or Slack Connect user from another workspace gets `:no_entry: Refused: guests and external Slack Connect users cannot control or message this room.`
422
- 6. **When someone not in `--allow` triggers `hive_resume` or `hive_say`**: Refused with `:no_entry: Refused: only Slack user IDs listed in --allow may resume/retry agents or send replies into the room (your ID: U…). Any full workspace member may still type stop.` When a user listed in `--allow` calls `hive_say`, it lands in the room attributed as `slack:<handle>`.
423
-
424
- ---
425
-
426
- ## 6. How to Show It (Live Demo Walkthrough)
427
-
428
- > **Running from a local checkout before npm publish:** Until the latest release is published to npm (`npx -y hivecode-mcp@latest` on npm is `0.12.4` prior to release), replace `npx -y hivecode-mcp@latest` in the commands below with `node C:/Users/G1/Desktop/N-team/hive-mcp.js` (or `node ./hive-mcp.js` from your repo root).
429
-
430
- Use these 5 steps to demonstrate either **GitHub-to-Slack issue threads** (`github start --slack-channel --slack-allow`) or a **live room bridge** (`slack start --channel --allow`) end to end:
431
-
432
- 1. **Install the App & Copy Tokens**:
433
- - Create the Slack app from the **Optional Inbound Manifest** in Section 5 above and install it to your workspace.
434
- - Copy `SLACK_BOT_TOKEN` (`xoxb-…`) from **OAuth & Permissions**, and generate `SLACK_APP_TOKEN` (`xapp-…`, named `socket-mode` with `connections:write`) under **Basic Information → App-Level Tokens**.
435
- 2. **Invite `@Hivecode` & Copy IDs**:
436
- - In your Slack channel, run `/invite @Hivecode` and copy the **Channel ID** (`C…`) from channel details.
437
- - Copy your own **Slack Member ID** (`U…`) from your Slack profile (**Profile → `⋯` → Copy member ID**).
438
- 3. **Start the Watcher or Room Bridge**:
439
- - **Flow A — GitHub Issue Threads + Slack `stop` / `retry` (PowerShell):**
440
- ```powershell
441
- $env:SLACK_BOT_TOKEN="xoxb-…"
442
- $env:SLACK_APP_TOKEN="xapp-…"
443
- npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789 --slack-allow U012ABCDEF --dry-run
444
- npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789 --slack-allow U012ABCDEF
445
- ```
446
- - **Flow B — Live Room Bridge + Slack `stop` / `resume` / Thread Replies (PowerShell):**
447
- ```powershell
448
- $env:SLACK_BOT_TOKEN="xoxb-…"
449
- $env:SLACK_APP_TOKEN="xapp-…"
450
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
451
- npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
452
- ```
453
- 4. **Trigger a Thread**:
454
- - **In Flow A**: Add the `hivecode` label to a GitHub issue. Watch Slack open a single thread (`#12 — Title`) for that issue and post run progress inside it.
455
- - **In Flow B**: Assign a task in the room. Watch Slack open a thread for that task and post gate checks and task chat inside it.
456
- 5. **Control from the Slack Thread**:
457
- - **In Flow A (`github start`)**: Reply `stop` inside the issue's Slack thread to stop the active run (posts `/hivecode stop` on GitHub and ends the room). Reply `retry` (permitted because your ID is in `--slack-allow`) to post `/hivecode retry` and start a fresh run.
458
- - **In Flow B (`slack start`)**: Reply `stop all` (or `stop <AgentName>`) inside the thread to pause agents on their own clients (`controls` map -> `paused`). Reply `resume all` or reply with instructions (`@AgentName …`, delivered into the room as `slack:<your-handle>`).
459
-
460
- ---
461
-
462
- ## 7. Troubleshooting (`Q510` – `Q521`, `Q630` – `Q635`)
463
-
464
- | Code | Cause | Fix |
465
- | :--- | :--- | :--- |
466
- | **`Q510`** | `hive-mcp-http.js` started in `--auth slack` mode without `SLACK_SIGNING_SECRET`. | Copy your app's **Signing Secret** from **Basic Information → App Credentials** in Slack app settings and set `SLACK_SIGNING_SECRET` (or use `--auth none` on `localhost` only). |
467
- | **`Q511` – `Q513`** | HTTP request to `hive-mcp-http.js` is unsigned (`Q511`), outside the 5-minute replay window (`Q512`), or its HMAC signature does not match (`Q513`). | Ensure `SLACK_SIGNING_SECRET` matches the Slack app calling the endpoint and that the host clock is synced via NTP. |
468
- | **`Q514` - `Q521`** | `hive-mcp-http.js` answered a request it could not act on: `Q514` no participant of that name is in the room; `Q515` unknown tool; `Q516` a tool failed; `Q517` JSON-RPC method not supported; `Q518` the endpoint takes `POST` only; `Q519` request body too large; `Q520` body is not JSON; `Q521` refused by the Slack actor check (guest, other workspace, or not in `--allow`). | `Q514`: use a name from the "Here now" list in the same message. `Q515`/`Q517`: call a tool listed above (`hive_status`, `hive_members`, `hive_tasks`, `hive_claims`, `hive_recent`, `hive_pause`, `hive_resume`, `hive_say`). `Q518`/`Q520`: send a JSON-RPC `POST`. `Q519`: send a smaller body. `Q521`: add the Slack member ID to `--allow` (resume / say), or ask a full workspace member. `Q516`: read the message after it; it names the failure. |
469
- | **`Q630`** | `SLACK_BOT_TOKEN` is missing (required by `slack start` and by `hive-mcp-http.js` in `--auth slack` mode), invalid (`invalid_auth`), or revoked (`token_revoked`) when checked against Slack `auth.test`. | Copy the **Bot User OAuth Token** (`xoxb-…`) from **OAuth & Permissions** in your Slack app settings and set `SLACK_BOT_TOKEN` in the same terminal session. |
470
- | **`Q631`** | `--channel` is missing, `channel_not_found`, or `@Hivecode` has not been invited to the channel (`is_member: false` / `not_in_channel`). | Open the target channel in Slack and run `/invite @Hivecode`. If it is a private channel, ensure the app has `groups:read` scope and reinstall to workspace. |
471
- | **`Q632`** | Another `SlackBridge` with the same `--name` is already connected to this room. | Stop the existing `slack start` process before starting a new one so events are not posted twice. |
472
- | **`Q633`** | `--slack-channel` was passed to `github start`, but `SLACK_BOT_TOKEN` is not set in the environment. | Set `SLACK_BOT_TOKEN=xoxb-…` (or `$env:SLACK_BOT_TOKEN="xoxb-…"` in PowerShell) before running `github start --slack-channel`. |
473
- | **`Q634`** | Inbound Slack configuration cannot work safely: (1) `SLACK_APP_TOKEN` (`xapp-…`) is missing or rejected by `apps.connections.open`; (2) `--slack-allow` was passed to `github start` without `--slack-channel`, without `SLACK_APP_TOKEN`, or with usernames instead of member IDs (`U…`); or (3) Slack `auth.test` did not return a workspace `team_id` (in `github start` or `hive-mcp-http.js`), so external workspaces could not be refused. | Enable **Socket Mode** and set `SLACK_APP_TOKEN=xapp-…` (`connections:write` scope); pass Slack member IDs (`U…` from **Profile → `⋯` → Copy member ID**) to `--slack-allow` / `--allow`; or pass `--team <T…>` (`SLACK_TEAM_ID`) / reinstall the Slack app if `auth.test` omitted `team_id`. |
474
- | **`Q635`** | Another process is already connected to Slack Socket Mode with this `SLACK_APP_TOKEN` (Slack distributes incoming events across active connections, so messages or "stop" commands may go to the other process). | Ensure each process reading Slack (`slack start`, `github start --slack-allow`, `hive-slack-agent`) uses its own dedicated Slack app and App-Level Token. Check for another running terminal or service and stop it. If you just stopped a bridge or watcher, wait a minute for Slack to release the connection and start again. |
1
+ # Slack Setup (Under 10 Minutes)
2
+
3
+ Hivecode posts to Slack using **one thread per task** (for a live room) or **one thread per GitHub issue** (for the GitHub watcher). Only the opening message and the final outcome appear in the main channel; intermediate claims, gate checks, CI runs, and untasked room chatter stay inside threads so your channel is never flooded.
4
+
5
+ ---
6
+
7
+ ## 1. Create the Slack App from the Manifest (2 minutes)
8
+
9
+ 1. Open [api.slack.com/apps](https://api.slack.com/apps) and click **Create New App** → **From a manifest**.
10
+ 2. Pick your Slack workspace and switch the tab to **JSON**.
11
+ 3. Paste the contents of [`slack-app-manifest.json`](../slack-app-manifest.json):
12
+
13
+ ```json
14
+ {
15
+ "display_information": {
16
+ "name": "Hivecode",
17
+ "description": "One Slack thread per task or GitHub issue for Hivecode rooms.",
18
+ "background_color": "#111318"
19
+ },
20
+ "features": {
21
+ "bot_user": {
22
+ "display_name": "Hivecode",
23
+ "always_online": true
24
+ }
25
+ },
26
+ "oauth_config": {
27
+ "scopes": {
28
+ "bot": [
29
+ "chat:write",
30
+ "channels:read",
31
+ "groups:read"
32
+ ]
33
+ }
34
+ },
35
+ "settings": {
36
+ "org_deploy_enabled": false,
37
+ "socket_mode_enabled": false,
38
+ "token_rotation_enabled": false
39
+ }
40
+ }
41
+ ```
42
+
43
+ 4. Click **Next** → **Create**, then click **Install to Workspace** and **Allow**.
44
+ 5. In the left sidebar under **OAuth & Permissions**, copy the **Bot User OAuth Token** (`xoxb-…`). (After inviting `@Hivecode` to your channel in Step 2, run `SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack check --channel C0123456789` to verify the app end to end.)
45
+
46
+ ---
47
+
48
+ ## 2. Invite `@Hivecode` to Your Channel & Copy the Channel ID (1 minute)
49
+
50
+ 1. In Slack, open the channel where you want threads posted and invite the bot:
51
+ ```text
52
+ /invite @Hivecode
53
+ ```
54
+ 2. Right-click the channel name (or click the channel header at the top) → **View channel details**.
55
+ 3. Scroll to the bottom of the dialog and copy the **Channel ID** (looks like `C0123456789`).
56
+ 4. Run **`slack check`** to prove your token, workspace, channel membership, scopes, and (when `SLACK_APP_TOKEN` is set) inbound Socket Mode event subscriptions work end to end before starting any workflow:
57
+ ```bash
58
+ SLACK_BOT_TOKEN=xoxb-… [SLACK_APP_TOKEN=xapp-…] npx -y hivecode-mcp@latest slack check --channel C0123456789
59
+ ```
60
+ *(This posts one message in `#your-channel` — `"Hivecode check: reply anything in this thread"` — and one reply in its thread once your reply arrives.)*
61
+
62
+ ---
63
+
64
+ ## 3. Run `slack check` First, Then Start
65
+
66
+ Before starting a room bridge or the GitHub watcher, run **`slack check`** once. It verifies each piece of your Slack app in order (`token`, `workspace`, `channel`, `scopes`, `Socket Mode`), then posts `"Hivecode check: reply anything in this thread"` in `#your-channel` and waits up to 2 minutes for your reply so you know outbound posting **and** inbound event subscriptions actually work end to end.
67
+
68
+ **macOS / Linux (bash, zsh):**
69
+ ```bash
70
+ # Outbound only (3-scope manifest):
71
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack check --channel C0123456789
72
+
73
+ # Outbound + inbound stop/retry/replies (Socket Mode manifest):
74
+ SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack check --channel C0123456789
75
+
76
+ # Slack AI Agent surface + native stop button (Paid Slack plan manifest):
77
+ SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack check --channel D0123456789 --agent
78
+ ```
79
+
80
+ **Windows (PowerShell):**
81
+ ```powershell
82
+ $env:SLACK_BOT_TOKEN="xoxb-…"
83
+ $env:SLACK_APP_TOKEN="xapp-…" # optional: include when using inbound stop/retry/replies or --agent
84
+ npx -y hivecode-mcp@latest slack check --channel C0123456789
85
+ ```
86
+
87
+ **What Each `slack check` Line Means & the One Fix When It Fails:**
88
+
89
+ | Failing Step / Line | Cause | The One Fix |
90
+ | :--- | :--- | :--- |
91
+ | **`Q630 SLACK_BOT_TOKEN is missing` / `rejected by Slack (invalid_auth)`** | `SLACK_BOT_TOKEN` is unset, pasted from the wrong field, or revoked. | Copy the **Bot User OAuth Token** (`xoxb-…`) from **OAuth & Permissions** in your Slack app settings and export `SLACK_BOT_TOKEN` in the same terminal. |
92
+ | **`Q634 Slack auth.test did not return a workspace team_id`** | Slack did not associate the token with a workspace. | Reinstall the app to your workspace under **OAuth & Permissions → Reinstall to Workspace**. |
93
+ | **`Q631 @Hivecode is not a member of #channel`** | The bot has not been invited to the target channel. | Open `#channel` in Slack and run `/invite @Hivecode`. |
94
+ | **`Q631 Slack channel … could not be accessed (missing_scope: needs groups:read)`** | Target channel is private, or the bot lacks the channel read scope (`needed` scope named in error). | Add the named scope (`groups:read` / `channels:read`) under **OAuth & Permissions → Bot Token Scopes** and click **Reinstall to Workspace**. |
95
+ | **`Q634 SLACK_BOT_TOKEN is missing required inbound scope(s): users:read, channels:history`** | `SLACK_APP_TOKEN` is set for inbound `stop`/`retry`, but the app was created from the outbound-only manifest. | Recreate or update the app's manifest from [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) (Section 5 below) and click **Reinstall to Workspace**. |
96
+ | **`Q634 SLACK_BOT_TOKEN is missing required agent scope(s): assistant:write, im:history`** | `--agent` (or `hive-slack-agent.js`) was started with a token from the outbound or inbound-only manifest. | Update the app's manifest from [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json) (Section 5 below) and click **Reinstall to Workspace**. |
97
+ | **`Q634 SLACK_APP_TOKEN was rejected` / `Socket Mode did not open (no hello frame)`** | Socket Mode is disabled in the Slack app, or `SLACK_APP_TOKEN` (`xapp-…`) lacks `connections:write`. | Enable **Socket Mode** in your Slack app settings and generate a new App-Level Token (`xapp-…`) with `connections:write` under **Basic Information → App-Level Tokens**. |
98
+ | **`Q634 Slack agents.sessions.setStatus returned warning missing_agent_session_stopped_event_subscription`** | `--agent` checked `agents.sessions.setStatus`, and Slack reported that `agent_session_stopped` is not subscribed (so the native stop button is not rendered). | Subscribe to `agent_session_stopped` by updating your app's manifest from [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json) and reinstalling. |
99
+ | **`Q634 Slack agents.sessions.setStatus failed (feature_disabled)`** | The workspace is on a Free Slack plan or Agents & Assistants is disabled for the workspace. | Use [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) for typed `stop` / `retry` in channel threads (works on all Slack plans), or enable Agents & Assistants on a paid Slack plan. |
100
+ | **`Q634 Slack agents.sessions.setStatus failed (thread_ts_required)`** | Slack rejected `agents.sessions.setStatus` because the DM session requires a valid `thread_ts`. | Run `slack check --channel <D…> --agent` on a DM or channel where `@Hivecode` can post a thread root message first. |
101
+ | **`Q634 replies did not arrive. Event subscriptions are probably missing`** | You replied in the check thread, but Slack never sent the event (`message.channels` / `message.groups` / `message.im` not subscribed). | Update your app's manifest with [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) (or [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json) for `--agent`) and reinstall the app. |
102
+ | **`Q635 Another process is already connected to Slack Socket Mode`** | Another running terminal or service is connected with the same `SLACK_APP_TOKEN` (e.g. `slack start`, `github start --slack-allow`, or `hive-slack-agent`). | Use a separate Slack app per process that reads Slack. If you recently stopped a bridge or watcher, wait a minute for Slack to release the socket and retry. |
103
+
104
+ Once `slack check` passes, you can also run `--dry-run` on `slack start` or `github start` before launching:
105
+
106
+ ### Option A — Bridge a Live Hivecode Room (`slack start`)
107
+
108
+ > **Where do I get the `"wss://…|room-…"` link?** Running `npx -y hivecode-mcp@latest branch <name>` or `npx -y hivecode-mcp@latest setup` prints your room's `wss://…|room-…` link.
109
+
110
+ **macOS / Linux (bash, zsh):**
111
+ ```bash
112
+ # 1. Verify token and channel membership first
113
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --dry-run
114
+
115
+ # 2. Start the live bridge
116
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789
117
+ ```
118
+
119
+ **Windows (PowerShell):**
120
+ ```powershell
121
+ $env:SLACK_BOT_TOKEN="xoxb-…"
122
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --dry-run
123
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789
124
+ ```
125
+
126
+ **Windows (Command Prompt / `cmd.exe`):**
127
+ ```cmd
128
+ set SLACK_BOT_TOKEN=xoxb-…
129
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --dry-run
130
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789
131
+ ```
132
+
133
+ ---
134
+
135
+ ### Option B — One Slack Thread per GitHub Issue (`github start --slack-channel`)
136
+
137
+ When running the GitHub issue watcher (`docs/GITHUB_WORKFLOW.md`), pass `--slack-channel <id>` with `SLACK_BOT_TOKEN` set in your environment. Each labelled issue opens one Slack thread; PR ready for review, waiting on a person, and merged/closed are posted in the thread and broadcast to the channel (`reply_broadcast`), while run start, CI failures, the tester's verdict, fixes pushed to the PR, resumed, and stopped stay inside the thread only.
138
+
139
+ If you also set `SLACK_APP_TOKEN=xapp-…` (see Section 5), replying `stop` in an issue's Slack thread stops that issue's run (and posts `/hivecode stop` on GitHub), and replying `retry` re-runs it for Slack user IDs listed in `--slack-allow <U123,U456>`.
140
+
141
+ **macOS / Linux (bash, zsh):**
142
+ ```bash
143
+ # 1. Dry-run first (checks gh auth, repo, and Slack token/channel)
144
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789 --dry-run
145
+
146
+ # 2. Start watching issues
147
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789
148
+ ```
149
+
150
+ **Windows (PowerShell):**
151
+ ```powershell
152
+ $env:SLACK_BOT_TOKEN="xoxb-…"
153
+ npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789 --dry-run
154
+ npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789
155
+ ```
156
+
157
+ **Windows (Command Prompt / `cmd.exe`):**
158
+ ```cmd
159
+ set SLACK_BOT_TOKEN=xoxb-…
160
+ npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789 --dry-run
161
+ npx -y hivecode-mcp@latest github start --agent "claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode" --slack-channel C0123456789
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 4. What Gets Posted (and What Is Scrubbed)
167
+
168
+ | Source | Shown in Channel | Inside the Thread Only |
169
+ | :--- | :--- | :--- |
170
+ | **GitHub Watcher (`--slack-channel`)** | Thread opening post (`#12 — Title`), plus thread replies broadcast to the channel (`reply_broadcast`): PR ready for review, waiting on a person (`hivecode:needs-human`), merged / closed | Run started, CI failed, the tester's verdict, resumed, stopped |
171
+ | **Room Bridge (`slack start`)** | `task-open` and `task-done` | Gate pass/fail (`gate-pass`, `gate-fail`), task chat, and all untasked room chat (grouped inside one shared room thread so chatter never floods the channel) |
172
+
173
+ - **What `slack start` announces, and when**: it watches the room's task list and gate results as well as its chat. A new task opens its thread (and appears in the channel); when the assignee completes it, the "done" reply is also broadcast to the channel. A gate pass or fail is posted inside the shared room thread. The first time a bridge ever attaches to a room it only records what is already there, so starting it never replays the room's history; what it has announced is kept in room state (`slack_seen`), so a restart does not repeat itself. A forced gate release is not posted as a gate result: it is already in room chat.
174
+ - **Secret & Room Link Scrubbing**: Every message passes through `scrubSlack()` before leaving your machine. API keys, tokens, bearer headers, room capability links (`wss://…|room-…`), and room IDs (`room-…`) are stripped automatically.
175
+ - **Rate Limits & Retries**: Slack's ~1 message/second per-channel pacing is enforced by a single outbound queue. HTTP `429` (`ratelimited`) responses are retried up to 5 times honouring `Retry-After`.
176
+ - **Durable Thread State**: Thread timestamps (`thread_ts`) are stored in room state (`slack_threads` map) for `slack start` and in `.git/hivecode/github.json` for `github start --slack-channel`, so restarting the process continues posting into the existing Slack thread.
177
+
178
+ ---
179
+
180
+ ## 5. Stopping Agents & Replying from Slack (Optional — Socket Mode)
181
+
182
+ By default, `slack-app-manifest.json` requests only the three outbound scopes (`chat:write`, `channels:read`, `groups:read`). If you also want to **stop/resume agents** or **reply in task threads** from Slack (with zero public webhook URL), enable **Socket Mode**:
183
+
184
+ ### Privacy & Scope Notice
185
+ Inbound Socket Mode requires adding `channels:history`, `groups:history`, and `users:read` to **Bot Token Scopes**, plus an **App-Level Token** (`SLACK_APP_TOKEN=xapp-…`) with `connections:write` and Event Subscriptions for `message.channels` and `message.groups`.
186
+ > **Plain-spoken scope warning:** `channels:history` and `groups:history` let the bot read every message posted in the channels you invite it to. If you only want outbound thread feeds, keep the default 3-scope manifest above.
187
+
188
+ <details>
189
+ <summary><strong>Optional Inbound Manifest (Socket Mode enabled — <code>slack-app-manifest-inbound.json</code>)</strong></summary>
190
+
191
+ Paste the contents of [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json):
192
+
193
+ ```json
194
+ {
195
+ "display_information": {
196
+ "name": "Hivecode",
197
+ "description": "One Slack thread per task or GitHub issue, with inbound stop and thread replies.",
198
+ "background_color": "#111318"
199
+ },
200
+ "features": {
201
+ "bot_user": {
202
+ "display_name": "Hivecode",
203
+ "always_online": true
204
+ }
205
+ },
206
+ "oauth_config": {
207
+ "scopes": {
208
+ "bot": [
209
+ "chat:write",
210
+ "channels:read",
211
+ "groups:read",
212
+ "channels:history",
213
+ "groups:history",
214
+ "users:read"
215
+ ]
216
+ }
217
+ },
218
+ "settings": {
219
+ "event_subscriptions": {
220
+ "bot_events": [
221
+ "message.channels",
222
+ "message.groups"
223
+ ]
224
+ },
225
+ "org_deploy_enabled": false,
226
+ "socket_mode_enabled": true,
227
+ "token_rotation_enabled": false
228
+ }
229
+ }
230
+ ```
231
+ </details>
232
+
233
+ ### Generating the App-Level Token (`SLACK_APP_TOKEN`)
234
+ 1. In your Slack app settings, go to **Basic Information** and scroll down to **App-Level Tokens**.
235
+ 2. Click **Generate Token and Scopes**.
236
+ 3. Enter `socket-mode` as the **Token Name** (required by Slack), click **Add Scope**, select `connections:write`, and click **Generate**.
237
+ 4. Copy the resulting `xapp-…` token and set it as `SLACK_APP_TOKEN`.
238
+
239
+ ### Networks That Refuse WebSockets (Cloud VMs): `--inbound`
240
+ Socket Mode is a WebSocket. Some networks refuse every WebSocket upgrade. One example is Antigravity's cloud VM, whose proxy answers `403 WebSocket upgrades are not allowed`. On such a network the bridge reads Slack over plain HTTPS instead: `conversations.history` for the channel and `conversations.replies` for the threads it tracks.
241
+
242
+ | `--inbound` (or `HIVE_SLACK_INBOUND`) | What it does |
243
+ | --- | --- |
244
+ | `auto` (default) | Socket Mode when `SLACK_APP_TOKEN` is set. If the network refuses the upgrade with an HTTP status, it switches to HTTPS polling and prints `[hivecode] Slack replies are read over HTTPS every 3 s (...)`. Without `SLACK_APP_TOKEN`, it is outbound only, as before. |
245
+ | `poll` | HTTPS polling only. **Needs no `SLACK_APP_TOKEN`**, just a bot token from [`slack-app-manifest-inbound.json`](../slack-app-manifest-inbound.json) (`channels:history` or `groups:history`, plus `users:read`). |
246
+ | `socket` | Socket Mode only. Never polls. |
247
+
248
+ ```bash
249
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack check --channel C0123456789 --inbound poll
250
+ SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack start "<relay|room>" --channel C0123456789 --allow U123 --inbound poll
251
+ ```
252
+
253
+ What to know about polling:
254
+ - **Speed:** a reply reaches the room within about `HIVE_SLACK_POLL_MS` (default 3000 ms). Socket Mode is near-instant.
255
+ - **Restarts:** where it stopped reading is kept in the room and on disk, so a restarted bridge neither replays old messages nor skips new ones. Two bridges on one room claim each message before acting, so a `stop` is acted on once.
256
+ - **Downtime:** after the bridge has been offline, messages older than `HIVE_SLACK_CATCHUP_MS` (default 30 minutes) are **not acted on**. A two-hour-old `resume` should not fire. The bridge posts once in the room's thread with the offline window and the count, so nobody assumes they were handled. Send it again if it still matters.
257
+ - **Rate limits:** two reads per poll, more while tracked threads are active. A `429` is honoured with Slack's `Retry-After`.
258
+ - `--agent` (the native stop button) needs Socket Mode and cannot poll.
259
+
260
+ ### Strict or Secured Rooms: the Bridge Needs a Human Token
261
+ `stop` and `resume` from Slack change the room's controls, and the relay lets only a human change controls: an AI's write is reverted. The bridge acts for a named Slack person, so it joins as a human. On an open room this works with no token. On a **strict or secured room**, start the bridge with a human (or admin/maintainer) token in the link or `HIVE_TOKEN`. Otherwise the relay reverts the stop, so check the agents' state in the room after your first `stop`.
262
+
263
+ ### Who May Act (`--allow` / `--slack-allow`) & No Impersonation
264
+ - **STOP is fail-safe**: Any full member of your Slack workspace may type `stop`, `stop all`, or `stop <AgentName>` in a thread to pause agents (or stop an active GitHub issue run) immediately. If Slack's `users.info` endpoint fails during an outage, `stop` still succeeds and notes `(stopped; I could not confirm who you are)`.
265
+ - **RESUME, RETRY, and thread replies require the allowlist (`--allow U123,U456` on `slack start`, or `--slack-allow U123,U456` on `github start`)**: Only Slack user IDs explicitly listed in the allowlist (find yours in Slack under **Profile → `⋯` → Copy member ID**) may resume agents (`resume`, `resume all`, `resume <AgentName>`), retry a GitHub issue run (`retry`), or send replies into the room. If the allowlist is omitted, inbound is **stop-only**.
266
+ - **Guests & Slack Connect users are refused**: Single-channel/multi-channel guests (`is_restricted` / `is_ultra_restricted`) and external Slack Connect users from other workspaces (`team_id` mismatch via `users.info`) are refused for all actions (including `stop`) and receive a refusal reply in the thread.
267
+ - **One Slack app per process (Socket Mode multi-connection guard)**: Each process that reads Slack (`slack start`, `github start --slack-allow`, or `hive-slack-agent`) requires its own dedicated Slack app and App-Level Token (`xapp-…`). Slack Socket Mode supports up to 10 connections per token and arbitrarily distributes incoming events across them without channel routing. Sharing an app token across two processes causes events (including `stop all` and thread replies) to split between the two processes (`Q635`).
268
+ - **No impersonation (`slack:<handle>`)**: Every message delivered from Slack into the room is attributed as `slack:<handle>` (for example, `slack:ganesh`), never as a bare room member name (`Ganesh`), so a Slack display name cannot impersonate the room owner.
269
+
270
+ ### Free vs Paid Slack Plans & the Slack AI Agent Surface (`hive-slack-agent.js`)
271
+ - **Typed `stop` works on every Slack plan (including Free)**: Replying `stop`, `stop all`, `stop <AgentName>`, `resume <AgentName>`, or `retry` in a channel thread requires only standard channel events (`slack-app-manifest-inbound.json`) and works on **all Slack plans**. We keep `slack-app-manifest-inbound.json` separate from `slack-app-manifest-agent.json` so Free-plan workspaces can install inbound `stop`/`retry` without hitting `feature_disabled`.
272
+ - **Native AI stop button & streamed plan cards (`hive-slack-agent.js`) require a paid Slack plan**: `hive-slack-agent.js` renders live room tasks as a streamed plan (`chat.startStream` / `chat.appendStream` / `chat.stopStream` with `task_display_mode: "plan"`) and enables Slack's native stop button via `agents.sessions.setStatus` (`status: "processing"` / `"active"`) and `agent_session_stopped`.
273
+ - **Who may act on the agent surface (same rules as `slack start`)**: `hive-slack-agent.js` checks every sender with the same `makeSlackActorCheck` rules. Any full workspace member may `stop` / `stop all` (or press Slack's native stop button); if Slack's `users.info` is down it still stops, and says `(stopped; I could not confirm who you are)`. `resume` needs the sender's member ID in `--allow <U123,U456>` (or `SLACK_ALLOW`). Guests and users from other workspaces are refused for everything, `status` included, and are told so in the thread; the room's tasks are never streamed to them. At startup it needs your workspace id from `auth.test` (refused with `Q634` if Slack omits it). A typed message counts only in the configured `--channel` or in a DM with the app (each user's own assistant DM is answered in that DM); messages from any other channel the bot is in are ignored.
274
+ - **Official Slack requirements for `hive-slack-agent.js`**:
275
+ - **Bot Token Scopes**: `chat:write` ([`chat.startStream`](https://docs.slack.dev/reference/methods/chat.startStream)), `assistant:write` ([`agents.sessions.setStatus`](https://docs.slack.dev/reference/methods/agents.sessions.setStatus) and [`agent_session_stopped`](https://docs.slack.dev/reference/events/agent_session_stopped)), `im:history`, `im:read`, `im:write` ([Developing AI Apps](https://docs.slack.dev/ai/developing-ai-apps)), plus `channels:read`, `groups:read`, `channels:history`, `groups:history`, `users:read`.
276
+ - **Bot Events**: `agent_session_stopped` ([`agent_session_stopped` event](https://docs.slack.dev/reference/events/agent_session_stopped)), `assistant_thread_started`, `assistant_thread_context_changed`, `message.im`, `message.channels`, `message.groups`.
277
+ - **App Settings**: `features.assistant_view` (`assistant_description` and `suggested_prompts`) and `settings.socket_mode_enabled: true` ([Agent Sessions](https://docs.slack.dev/ai/agent-sessions)).
278
+ - **Startup & `slack check --agent` verification**:
279
+ - At startup, `hive-slack-agent.js` (`preflightSlackAgent`) checks `x-oauth-scopes` from `auth.test` via `checkAgentScopes` and refuses with `Q634` (naming missing scopes such as `assistant:write, im:history` and `slack-app-manifest-agent.json`) before opening Socket Mode.
280
+ - Running `SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack check --channel D0123456789 --agent` verifies those scopes, posts a check message (`checkTs`), and calls `agents.sessions.setStatus({ status: 'processing', channel_id, thread_ts: checkTs })`. Per Slack's [`agent_session_stopped` docs](https://docs.slack.dev/reference/events/agent_session_stopped), if your app is not subscribed to `agent_session_stopped`, Slack returns a `missing_agent_session_stopped_event_subscription` warning (checked in both top-level `warning` and `response_metadata.warnings[]`) and renders a non-interactive spinner instead of the stop button; `slack check --agent` catches that warning (as well as `feature_disabled` and `thread_ts_required`) and refuses with `Q634`. On every exit path (pass, fail, timeout, or `Ctrl+C`), `slack check --agent` clears the session status back to `active` in a `finally` block so the DM is never left spinning.
281
+ - *(Note: `features.assistant_view` and `suggested_prompts` control the top-bar split-view UI in Slack and cannot be probed via a Web API read call; installing from `slack-app-manifest-agent.json` configures them declaratively.)*
282
+
283
+ **Starting the Agent Surface (`slack agent`):**
284
+
285
+ macOS / Linux (bash, zsh):
286
+ ```bash
287
+ SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack agent "wss://hivecode-relay.onrender.com|room-abc123" --channel D0123456789 --allow U012ABCDEF
288
+ ```
289
+
290
+ Windows (PowerShell):
291
+ ```powershell
292
+ $env:SLACK_BOT_TOKEN="xoxb-…"
293
+ $env:SLACK_APP_TOKEN="xapp-…"
294
+ npx -y hivecode-mcp@latest slack agent "wss://hivecode-relay.onrender.com|room-abc123" --channel D0123456789 --allow U012ABCDEF
295
+ ```
296
+
297
+ <details>
298
+ <summary><strong>Optional Paid-Plan AI Agent Surface Manifest (<code>slack-app-manifest-agent.json</code>)</strong></summary>
299
+
300
+ Paste the contents of [`slack-app-manifest-agent.json`](../slack-app-manifest-agent.json):
301
+
302
+ ```json
303
+ {
304
+ "display_information": {
305
+ "name": "Hivecode",
306
+ "description": "AI agent panel, native stop button, and one Slack thread per task or GitHub issue.",
307
+ "background_color": "#111318"
308
+ },
309
+ "features": {
310
+ "bot_user": {
311
+ "display_name": "Hivecode",
312
+ "always_online": true
313
+ },
314
+ "assistant_view": {
315
+ "assistant_description": "Inspect live Hivecode rooms, stream task plans, and halt or resume AI agents from Slack.",
316
+ "suggested_prompts": [
317
+ {
318
+ "title": "What is running?",
319
+ "message": "status"
320
+ },
321
+ {
322
+ "title": "Stop everything",
323
+ "message": "stop all"
324
+ },
325
+ {
326
+ "title": "What happened overnight?",
327
+ "message": "what happened overnight"
328
+ }
329
+ ]
330
+ }
331
+ },
332
+ "oauth_config": {
333
+ "scopes": {
334
+ "bot": [
335
+ "chat:write",
336
+ "assistant:write",
337
+ "im:history",
338
+ "im:read",
339
+ "im:write",
340
+ "channels:read",
341
+ "groups:read",
342
+ "channels:history",
343
+ "groups:history",
344
+ "users:read"
345
+ ]
346
+ }
347
+ },
348
+ "settings": {
349
+ "event_subscriptions": {
350
+ "bot_events": [
351
+ "agent_session_stopped",
352
+ "assistant_thread_started",
353
+ "assistant_thread_context_changed",
354
+ "message.im",
355
+ "message.channels",
356
+ "message.groups"
357
+ ]
358
+ },
359
+ "org_deploy_enabled": false,
360
+ "socket_mode_enabled": true,
361
+ "token_rotation_enabled": false
362
+ }
363
+ }
364
+ ```
365
+ </details>
366
+
367
+ **macOS / Linux (bash, zsh):**
368
+ ```bash
369
+ SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
370
+ SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
371
+ ```
372
+
373
+ **Windows (PowerShell):**
374
+ ```powershell
375
+ $env:SLACK_BOT_TOKEN="xoxb-…"
376
+ $env:SLACK_APP_TOKEN="xapp-…"
377
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
378
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
379
+ ```
380
+
381
+ **Windows (Command Prompt / `cmd.exe`):**
382
+ ```cmd
383
+ set SLACK_BOT_TOKEN=xoxb-…
384
+ set SLACK_APP_TOKEN=xapp-…
385
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
386
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
387
+ ```
388
+
389
+ ### Slackbot Remote MCP Server (`hive-mcp-http.js`)
390
+
391
+ If you connect Slackbot's remote MCP client over Streamable HTTP (`hive-mcp-http.js`), it exposes fast room inspection and control tools (`hive_status`, `hive_members`, `hive_tasks`, `hive_claims`, `hive_recent`, `hive_pause`, `hive_resume`, `hive_say`).
392
+
393
+ - **Requires both `SLACK_SIGNING_SECRET` and `SLACK_BOT_TOKEN`**: In `--auth slack` mode (the default), `hive-mcp-http.js` refuses to start without `SLACK_SIGNING_SECRET` (`Q510`, copied from **Basic Information → App Credentials → Signing Secret**) **and** `SLACK_BOT_TOKEN` (`Q630`, `xoxb-…` with `users:read` scope so `users.info` can verify callers).
394
+ - **Discovers your workspace (`team_id`) from Slack at startup**: When you start `hive-mcp-http.js` without `--team` (`SLACK_TEAM_ID`), it calls Slack's `auth.test` using `SLACK_BOT_TOKEN` before serving requests. If `auth.test` rejects the token (`Q630`) or does not return a `team_id` (`Q634`), startup is refused immediately so external Slack Connect workspace users can never slip through by default.
395
+ - **Same access rules (`makeSlackActorCheck`)**:
396
+ - **Every request is HMAC-verified first** (`X-Slack-Signature` + 5-minute replay window, `Q511`–`Q513`) before `_meta.slack.user_id` is read.
397
+ - **Guests and other workspaces are refused** for all tools (`hive_pause`, `hive_resume`, `hive_say`).
398
+ - **`hive_pause` (`stop`) is fail-safe** for any full member of your workspace (and fails open with `(stopped; I could not confirm who you are)` if `users.info` is unreachable during a Slack outage).
399
+ - **`hive_resume` and `hive_say` require `--allow <U123,U456>`** (or `SLACK_ALLOW`). Messages sent via `hive_say` are recorded in room chat as `slack:<handle>`.
400
+
401
+ **macOS / Linux (bash, zsh):**
402
+ ```bash
403
+ SLACK_SIGNING_SECRET=… SLACK_BOT_TOKEN=xoxb-… npx -y hivecode-mcp@latest slack mcp-server "wss://hivecode-relay.onrender.com|room-abc123" --port 8790 --allow U012ABCDEF
404
+ ```
405
+
406
+ **Windows (PowerShell):**
407
+ ```powershell
408
+ $env:SLACK_SIGNING_SECRET="…"
409
+ $env:SLACK_BOT_TOKEN="xoxb-…"
410
+ npx -y hivecode-mcp@latest slack mcp-server "wss://hivecode-relay.onrender.com|room-abc123" --port 8790 --allow U012ABCDEF
411
+ ```
412
+
413
+ **What a First-Time User Sees Step by Step (`hive-mcp-http.js`):**
414
+ 1. **If `SLACK_SIGNING_SECRET` is missing**: Process exits immediately (`code 2`) with:
415
+ `Q510 --auth slack needs SLACK_SIGNING_SECRET. Use --auth none only on localhost.`
416
+ 2. **If `SLACK_BOT_TOKEN` is missing**: Process exits immediately (`code 2`) with:
417
+ `Q630 --auth slack needs SLACK_BOT_TOKEN. Set SLACK_BOT_TOKEN=xoxb-… in your environment (docs/SLACK_SETUP.md).`
418
+ 3. **When both are set**: `hive-mcp-http.js` calls Slack `auth.test`, locks in your workspace `team_id`, joins the room, and prints:
419
+ `[hive-mcp-http] room room-abc123 on :8790/ auth=slack`
420
+ 4. **When someone asks Slackbot what is happening (`hive_status`)**: Returns the live room name, agent count, paused list, and task counts.
421
+ 5. **When a coworker triggers `hive_pause`**: Pauses the named agent (or `all`) on its own client (`paused AgentA — it will finish its current step and then stop picking up work`), while a guest or Slack Connect user from another workspace gets `:no_entry: Refused: guests and external Slack Connect users cannot control or message this room.`
422
+ 6. **When someone not in `--allow` triggers `hive_resume` or `hive_say`**: Refused with `:no_entry: Refused: only Slack user IDs listed in --allow may resume/retry agents or send replies into the room (your ID: U…). Any full workspace member may still type stop.` When a user listed in `--allow` calls `hive_say`, it lands in the room attributed as `slack:<handle>`.
423
+
424
+ ---
425
+
426
+ ## 6. How to Show It (Live Demo Walkthrough)
427
+
428
+ > **Running from a local checkout before npm publish:** Until the latest release is published to npm (`npx -y hivecode-mcp@latest` on npm is `0.12.4` prior to release), replace `npx -y hivecode-mcp@latest` in the commands below with `node C:/Users/G1/Desktop/N-team/hive-mcp.js` (or `node ./hive-mcp.js` from your repo root).
429
+
430
+ Use these 5 steps to demonstrate either **GitHub-to-Slack issue threads** (`github start --slack-channel --slack-allow`) or a **live room bridge** (`slack start --channel --allow`) end to end:
431
+
432
+ 1. **Install the App & Copy Tokens**:
433
+ - Create the Slack app from the **Optional Inbound Manifest** in Section 5 above and install it to your workspace.
434
+ - Copy `SLACK_BOT_TOKEN` (`xoxb-…`) from **OAuth & Permissions**, and generate `SLACK_APP_TOKEN` (`xapp-…`, named `socket-mode` with `connections:write`) under **Basic Information → App-Level Tokens**.
435
+ 2. **Invite `@Hivecode` & Copy IDs**:
436
+ - In your Slack channel, run `/invite @Hivecode` and copy the **Channel ID** (`C…`) from channel details.
437
+ - Copy your own **Slack Member ID** (`U…`) from your Slack profile (**Profile → `⋯` → Copy member ID**).
438
+ 3. **Start the Watcher or Room Bridge**:
439
+ - **Flow A — GitHub Issue Threads + Slack `stop` / `retry` (PowerShell):**
440
+ ```powershell
441
+ $env:SLACK_BOT_TOKEN="xoxb-…"
442
+ $env:SLACK_APP_TOKEN="xapp-…"
443
+ npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789 --slack-allow U012ABCDEF --dry-run
444
+ npx -y hivecode-mcp@latest github start --agent 'claude -p --output-format json --allowedTools Bash Edit Write Read Glob Grep mcp__hivecode' --slack-channel C0123456789 --slack-allow U012ABCDEF
445
+ ```
446
+ - **Flow B — Live Room Bridge + Slack `stop` / `resume` / Thread Replies (PowerShell):**
447
+ ```powershell
448
+ $env:SLACK_BOT_TOKEN="xoxb-…"
449
+ $env:SLACK_APP_TOKEN="xapp-…"
450
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF --dry-run
451
+ npx -y hivecode-mcp@latest slack start "wss://hivecode-relay.onrender.com|room-abc123" --channel C0123456789 --allow U012ABCDEF
452
+ ```
453
+ 4. **Trigger a Thread**:
454
+ - **In Flow A**: Add the `hivecode` label to a GitHub issue. Watch Slack open a single thread (`#12 — Title`) for that issue and post run progress inside it.
455
+ - **In Flow B**: Assign a task in the room. Watch Slack open a thread for that task and post gate checks and task chat inside it.
456
+ 5. **Control from the Slack Thread**:
457
+ - **In Flow A (`github start`)**: Reply `stop` inside the issue's Slack thread to stop the active run (posts `/hivecode stop` on GitHub and ends the room). Reply `retry` (permitted because your ID is in `--slack-allow`) to post `/hivecode retry` and start a fresh run.
458
+ - **In Flow B (`slack start`)**: Reply `stop all` (or `stop <AgentName>`) inside the thread to pause agents on their own clients (`controls` map -> `paused`). Reply `resume all` or reply with instructions (`@AgentName …`, delivered into the room as `slack:<your-handle>`).
459
+
460
+ ---
461
+
462
+ ## 7. Troubleshooting (`Q510` – `Q521`, `Q630` – `Q635`)
463
+
464
+ | Code | Cause | Fix |
465
+ | :--- | :--- | :--- |
466
+ | **`Q510`** | `hive-mcp-http.js` started in `--auth slack` mode without `SLACK_SIGNING_SECRET`. | Copy your app's **Signing Secret** from **Basic Information → App Credentials** in Slack app settings and set `SLACK_SIGNING_SECRET` (or use `--auth none` on `localhost` only). |
467
+ | **`Q511` – `Q513`** | HTTP request to `hive-mcp-http.js` is unsigned (`Q511`), outside the 5-minute replay window (`Q512`), or its HMAC signature does not match (`Q513`). | Ensure `SLACK_SIGNING_SECRET` matches the Slack app calling the endpoint and that the host clock is synced via NTP. |
468
+ | **`Q514` - `Q521`** | `hive-mcp-http.js` answered a request it could not act on: `Q514` no participant of that name is in the room; `Q515` unknown tool; `Q516` a tool failed; `Q517` JSON-RPC method not supported; `Q518` the endpoint takes `POST` only; `Q519` request body too large; `Q520` body is not JSON; `Q521` refused by the Slack actor check (guest, other workspace, or not in `--allow`). | `Q514`: use a name from the "Here now" list in the same message. `Q515`/`Q517`: call a tool listed above (`hive_status`, `hive_members`, `hive_tasks`, `hive_claims`, `hive_recent`, `hive_pause`, `hive_resume`, `hive_say`). `Q518`/`Q520`: send a JSON-RPC `POST`. `Q519`: send a smaller body. `Q521`: add the Slack member ID to `--allow` (resume / say), or ask a full workspace member. `Q516`: read the message after it; it names the failure. |
469
+ | **`Q630`** | `SLACK_BOT_TOKEN` is missing (required by `slack start` and by `hive-mcp-http.js` in `--auth slack` mode), invalid (`invalid_auth`), or revoked (`token_revoked`) when checked against Slack `auth.test`. | Copy the **Bot User OAuth Token** (`xoxb-…`) from **OAuth & Permissions** in your Slack app settings and set `SLACK_BOT_TOKEN` in the same terminal session. |
470
+ | **`Q631`** | `--channel` is missing, `channel_not_found`, or `@Hivecode` has not been invited to the channel (`is_member: false` / `not_in_channel`). | Open the target channel in Slack and run `/invite @Hivecode`. If it is a private channel, ensure the app has `groups:read` scope and reinstall to workspace. |
471
+ | **`Q632`** | Another `SlackBridge` with the same `--name` is already connected to this room. | Stop the existing `slack start` process before starting a new one so events are not posted twice. |
472
+ | **`Q633`** | `--slack-channel` was passed to `github start`, but `SLACK_BOT_TOKEN` is not set in the environment. | Set `SLACK_BOT_TOKEN=xoxb-…` (or `$env:SLACK_BOT_TOKEN="xoxb-…"` in PowerShell) before running `github start --slack-channel`. |
473
+ | **`Q634`** | Inbound Slack configuration cannot work safely: (1) `SLACK_APP_TOKEN` (`xapp-…`) is missing or rejected by `apps.connections.open`; (2) `--slack-allow` was passed to `github start` without `--slack-channel`, without `SLACK_APP_TOKEN`, or with usernames instead of member IDs (`U…`); or (3) Slack `auth.test` did not return a workspace `team_id` (in `github start` or `hive-mcp-http.js`), so external workspaces could not be refused. | Enable **Socket Mode** and set `SLACK_APP_TOKEN=xapp-…` (`connections:write` scope); pass Slack member IDs (`U…` from **Profile → `⋯` → Copy member ID**) to `--slack-allow` / `--allow`; or pass `--team <T…>` (`SLACK_TEAM_ID`) / reinstall the Slack app if `auth.test` omitted `team_id`. |
474
+ | **`Q635`** | Another process is already connected to Slack Socket Mode with this `SLACK_APP_TOKEN` (Slack distributes incoming events across active connections, so messages or "stop" commands may go to the other process). | Ensure each process reading Slack (`slack start`, `github start --slack-allow`, `hive-slack-agent`) uses its own dedicated Slack app and App-Level Token. Check for another running terminal or service and stop it. If you just stopped a bridge or watcher, wait a minute for Slack to release the connection and start again. |