Add Slack as a channel. Can replace WhatsApp entirely or run alongside it. Uses Socket Mode (no public URL needed).
This skill adds Slack support to NanoClaw, then walks through interactive setup.
Check if src/channels/slack.ts exists. If it does, skip to Phase 3 (Setup). The code changes are already in place.
Do they already have a Slack app configured? If yes, collect the Bot Token and App Token now. If no, we'll create one in Phase 3.
git remote -v
If slack is missing, add it:
git remote add slack https://github.com/qwibitai/nanoclaw-slack.git
git fetch slack main
git merge slack/main || {
git checkout --theirs package-lock.json
git add package-lock.json
git merge --continue
}
This merges in:
src/channels/slack.ts (SlackChannel class with self-registration via registerChannel)src/channels/slack.test.ts (46 unit tests)import './slack.js' appended to the channel barrel file src/channels/index.ts@slack/bolt npm dependency in package.jsonSLACK_BOT_TOKEN and SLACK_APP_TOKEN in .env.exampleIf the merge reports conflicts, resolve them by reading the conflicted files and understanding the intent of both sides.
npm install
npm run build
npx vitest run src/channels/slack.test.ts
All tests must pass (including the new Slack tests) and build must be clean before proceeding.
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.
Quick summary of what's needed:
xapp-...)message.channels, message.groups, message.imchat:write, channels:history, groups:history, im:history, channels:read, groups:read, users:readxoxb-...)Wait for the user to provide both tokens.
Add to .env:
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_APP_TOKEN=xapp-your-app-token
Channels auto-enable when their credentials are present — no extra configuration needed.
Sync to container environment:
mkdir -p data/env && cp .env data/env/env
The container reads environment from data/env/env, not .env directly.
npm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
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— theC...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 NanoClaw is:
slack:C0123456789
Wait for the user to provide the channel ID.
The channel ID, name, and folder name are needed. Use npx tsx setup/index.ts --step register with the appropriate flags.
For a main channel (responds to all messages):
npx tsx setup/index.ts --step register -- --jid "slack:<channel-id>" --name "<channel-name>" --folder "slack_main" --trigger "@${ASSISTANT_NAME}" --channel slack --no-trigger-required --is-main
For additional channels (trigger-only):
npx tsx setup/index.ts --step register -- --jid "slack:<channel-id>" --name "<channel-name>" --folder "slack_<channel-name>" --trigger "@${ASSISTANT_NAME}" --channel slack
Tell the user:
Send a message in your registered Slack channel:
- For main channel: Any message works
- For non-main:
@<assistant-name> hello(using the configured trigger word)The bot should respond within a few seconds.
tail -f logs/nanoclaw.log
SLACK_BOT_TOKEN and SLACK_APP_TOKEN are set in .env AND synced to data/env/envsqlite3 store/messages.db "SELECT * FROM registered_groups WHERE jid LIKE 'slack:%'"launchctl list | grep nanoclawmessage.channels, message.groups, message.im)By default, bots only see messages in channels they've been explicitly added to. Make sure to:
channels:history and/or groups:history scopesIf the bot logs missing_scope errors:
.envmkdir -p data/env && cp .env data/env/envlaunchctl kickstart -k gui/$(id -u)/com.nanoclawIf the channel ID is hard to find:
C... ID from the URLhttps://app.slack.com/client/TXXXXXXX/C0123456789curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" "https://slack.com/api/conversations.list" | jq '.channels[] | {id, name}'The Slack channel supports:
NewMessage type, Channel.sendMessage interface, and routing logic.setTyping() method is a no-op. Users won't see "bot is typing..." while the agent works.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.