← back to Claude Slack

README.md

42 lines

# claude-slack

Two-way Slack chat channel for Claude — the Slack sibling of `claude-mail`.
A launchd job polls configured channels every 10s, runs the local `claude` CLI
on any message addressed to the bot, and posts the reply **in-thread**.

- **Bot:** `dw_reports_bot` (`U0BC1PWB1SS`) in the Designerwallcoverings workspace.
- **Channels** (`SLACK_CHANNELS` in `.env`):
  - `slack-steve` → `#claude-programming` (`C09QUHKM20L`), `requireMention:false` — your 1:1 line; every message gets answered.
  - `slack-general` → `#general` (`C03T1SQNJBH`), `requireMention:true` — shared team channel; Claude only answers messages that say `claude …` / `@claude`.

## How it works
`poller.js` (one pass per launchd fire):
1. `auth.test` → resolve the bot's own user id (loop guard).
2. For each channel: `conversations.history` since a saved per-channel cursor.
   On **first sight** of a channel the cursor is anchored to "now" — it never
   replies to backlog.
3. `gate()` drops bot/own/system messages, off-allowlist authors, and (in
   `requireMention` channels) anything not addressed to Claude.
4. `runClaude()` runs `claude -p` headless with Slack-tuned rails.
5. Reply posted with `chat.postMessage` + `thread_ts`.

`health.js` pages Steve (CNCP + macOS notification + George email — all
independent of the Slack token) after 3 consecutive failed passes, and again
when it recovers.

## Go-live blockers (one-time, Steve)
The bot token is currently **send-only**. To enable two-way chat:
1. **Add scopes** at api.slack.com → your app → OAuth & Permissions → Bot Token Scopes:
   `channels:history` (public), `groups:history` (private), optionally `users:read`.
2. **Reinstall** the app to the workspace (re-issues the token). If the token
   changes, re-run the secrets route so `~/.claude.json` + this `.env` update.
3. **Invite the bot** into each channel: `/invite @dw_reports_bot` in
   `#claude-programming` and `#general` (reading history requires membership).
4. Verify: `node --env-file=.env probe.js` — every channel should read "OK".
5. Go live: `cp com.steve.claude-slack.plist ~/Library/LaunchAgents/ && \
   launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.steve.claude-slack.plist`

## Commands
- `npm run probe` — read-only auth + per-channel history/membership check.
- `npm run poll`  — run one pass by hand.