Adds src/channels/slack.ts (SlackChannel class implementing Channel interface)
Adds src/channels/slack.test.ts (46 unit tests)
Three-way merges Slack support into (multi-channel support, conditional channel creation)
src/index.ts
Three-way merges Slack config into src/config.ts (SLACK_ONLY export)
Three-way merges updated routing tests into src/routing.test.ts
Installs the @slack/bolt npm dependency
Updates .env.example with SLACK_BOT_TOKEN, SLACK_APP_TOKEN, and SLACK_ONLY
Records the application in .ghostclaw/state.yaml
If the apply reports merge conflicts, read the intent files:
modify/src/index.ts.intent.md — what changed and invariants for index.ts
modify/src/config.ts.intent.md — what changed for config.ts
modify/src/routing.test.ts.intent.md — what changed for routing tests
Validate code changes
npm test
npm run build
All tests must pass (including the new slack tests) and build must be clean before proceeding.
Phase 3: Setup
Create Slack App (if needed)
If the user doesn't have a Slack app, share SLACK_SETUP.md which has step-by-step instructions with screenshots guidance, troubleshooting, and a token reference table.
The container reads environment from data/env/env, not .env directly.
Build and restart
npm run build
launchctl kickstart -k gui/$(id -u)/com.ghostclaw
Phase 4: Registration
Get Channel ID
Tell the user:
Add the bot to a Slack channel (right-click channel → View channel details → Integrations → Add apps)
In that channel, the channel ID is in the URL when you open it in a browser: https://app.slack.com/client/T.../C0123456789 — the C... part is the channel ID
Alternatively, right-click the channel name → Copy link — the channel ID is the last path segment
The JID format for GhostClaw is: slack:C0123456789
Wait for the user to provide the channel ID.
Register the channel
Use the IPC register flow or register directly. The channel ID, name, and folder name are needed.
For a main channel (responds to all messages, uses the main folder):
Public channels — Bot must be added to the channel
Private channels — Bot must be invited to the channel
Direct messages — Users can DM the bot directly
Multi-channel — Can run alongside WhatsApp (default) or replace it (SLACK_ONLY=true)
Known Limitations
Threads are flattened — Threaded replies are delivered to the agent as regular channel messages. The agent sees them but has no awareness they originated in a thread. Responses always go to the channel, not back into the thread. Users in a thread will need to check the main channel for the bot's reply. Full thread-aware routing (respond in-thread) requires pipeline-wide changes: database schema, NewMessage type, Channel.sendMessage interface, and routing logic.
No typing indicator — Slack's Bot API does not expose a typing indicator endpoint. The setTyping() method is a no-op. Users won't see "bot is typing..." while the agent works.
Message splitting is naive — Long messages are split at a fixed 4000-character boundary, which may break mid-word or mid-sentence. A smarter split (on paragraph or sentence boundaries) would improve readability.
No file/image handling — The bot only processes text content. File uploads, images, and rich message blocks are not forwarded to the agent.
Channel metadata sync is unbounded — syncChannelMetadata() paginates through all channels the bot is a member of, but has no upper bound or timeout. Workspaces with thousands of channels may experience slow startup.
Workspace admin policies not detected — If the Slack workspace restricts bot app installation, the setup will fail at the "Install to Workspace" step with no programmatic detection or guidance. See SLACK_SETUP.md troubleshooting section.