feat: add Claude Code Channels support for real-time Slack messaging#23
feat: add Claude Code Channels support for real-time Slack messaging#23marciogranzotto wants to merge 25 commits intoslackapi:mainfrom
Conversation
Spec covers architecture (Bolt + MCP SDK), Socket Mode event delivery, headless operation with permission relay, pairing flow, and sender gating. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix 10 issues from two review rounds: - Remove pendingCodes from settings schema (in-memory only) - Define lastActiveContext for permission relay routing - Limit bootstrap to one active pairing code - Add pair_user action to manage_access tool - Document meta key constraints and name resolution caching - Define reaction event filter (bot messages only) - Defer workspace gating to Future Work - Add --dangerously-load-development-channels flag docs - Specify tool authorization via lastActiveContext check - Require user IDs in manage_access (resolve handles externally) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9 tasks covering project setup, settings, gating, MCP server, bridge, Slack module, entry point, integration tests, and README update. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements settings persistence with atomic writes, Zod schema validation, and graceful fallback to defaults on missing/corrupt/invalid settings files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Define 4 tools (reply, react, manage_access, manage_channels) and channel instructions for the Slack channel server. Set up MCP Server with claude/channel capabilities, request handlers delegating to Bridge, and permission_request notification relay. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bridge is the central coordinator that transforms events between Slack and MCP. Implements message handling with gating checks, permission relay with verdict parsing, tool call dispatch, bootstrap/pairing flows, and user/channel name resolution caching. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ssion relay, pairing flow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Correctness & security: - Add source: 'slack' to all notification meta (spec compliance) - Widen verdict regex to [a-km-z0-9] for future-proof ID matching - Add authorization check (require active context) on reply/react tools - Fetch reacted message text via conversations.history for context - Fix pair_user to DM target user via conversations.open - Restrict bootstrap pairing to DMs only (prevent public code echo) - Fix conversations.join ordering — join before adding to watch list - Use crypto.randomBytes for pairing codes instead of Math.random - Add isError: true to tool error responses (MCP protocol) - Fix resolveChannelName to return empty on failure (not raw ID) Cleanup: - Remove dynamic imports in writePairingCodeFile - Remove unused say parameter in slack.ts - Fix README: correct .mcp.json example and settings schema - Fix tsconfig.json: remove invalid bun-types reference - Add package.json metadata (name, version, type, scripts) Tests (14 new): - Reaction handling (bot filter, gating, notification format) - manage_access/manage_channels success paths - Mention gating, source attribute, reply/react auth, bootstrap DM Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Catch already_in_channel and missing_scope errors when joining channels, so watching still works if the bot is already a member - Add channels:join and channels:history to required scopes in setup docs and README Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace text-based "yes/no <id>" permission prompts with Slack Block Kit buttons. Clicking a button emits the verdict and updates the message to show the result. Text-based verdicts still work as a fallback. Also adds interactivity setup step to the Slack app setup docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLAUDE.md: add Channel Server section with tools, setup, and running - .claude-plugin/plugin.json: update description to mention channels, fix stale homepage URL - slack-messaging skill: correct reaction tool availability claim - .mcp.json: clear credentials from committed config Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Thanks for the contribution! Before we can merge this, we need @marciogranzotto to sign the Salesforce Inc. Contributor License Agreement. |
| "name": "slack", | ||
| "description": "Slack integration for searching messages, sending communications, managing canvases, and more", | ||
| "description": "Slack integration for searching messages, sending communications, managing canvases, and real-time bidirectional messaging via Channels", | ||
| "version": "1.0.0", |
There was a problem hiding this comment.
btw, version needs to be bumped after merging
There was a problem hiding this comment.
Pull request overview
Adds a local Bun-based “slack-channel” MCP server that implements Claude Code Channels for real-time Slack ↔ Claude bidirectional messaging (Socket Mode), including sender gating/pairing and permission-relay workflows.
Changes:
- Introduces a new channel server stack (
src/) that bridges Slack events tonotifications/claude/channel, and exposes tools (reply,react,manage_access,manage_channels) + permission relay. - Adds settings persistence + allowlist/pairing logic, plus extensive Bun unit/integration tests.
- Updates plugin/docs/skills to document Channels setup and usage.
Reviewed changes
Copilot reviewed 20 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Adds TS config for the new Bun/TS channel server and tests. |
| package.json | Defines Bun scripts and dependencies for the channel server. |
| bun.lock | Locks dependency versions for the new server. |
| src/index.ts | Entry point wiring settings, gating, Slack (Socket Mode), and MCP (stdio). |
| src/settings.ts | Zod-validated settings read/write with atomic persistence. |
| src/gating.ts | Allowlist + pairing-code lifecycle for sender gating. |
| src/mcp.ts | MCP server capabilities/tools + permission_request notification handler. |
| src/slack.ts | Slack Bolt app initialization + event/action handlers. |
| src/bridge.ts | Core transform layer: Slack events ↔ MCP notifications; tool dispatch; caching. |
| tests/settings.test.ts | Tests settings defaults, corruption handling, and atomic writes. |
| tests/gating.test.ts | Tests allowlist behavior + pairing code generation/expiry/consumption. |
| tests/mcp.test.ts | Verifies MCP tool schemas and channel instructions. |
| tests/bridge.test.ts | Validates event gating/transforms, verdict parsing, caching, and tool auth. |
| tests/integration.test.ts | Smoke-tests DM→notification→reply and permission relay flows end-to-end (mocked). |
| README.md | Documents Channels research-preview setup, config, and pairing. |
| CLAUDE.md | Documents the new channel server and its tools. |
| docs/slack-app-setup.md | Step-by-step Slack app configuration for Socket Mode + scopes/events. |
| docs/superpowers/specs/2026-03-26-slack-channels-design.md | Design spec for the channel server architecture and behavior. |
| docs/superpowers/plans/2026-03-26-slack-channels.md | Implementation plan/checklist for building the feature. |
| skills/slack-messaging/SKILL.md | Updates guidance to reflect the new react capability in the channel server. |
| .mcp.json | Adds the local slack-channel server entry alongside the remote Slack MCP server. |
| .gitignore | Ignores .env and node_modules/. |
| .claude-plugin/plugin.json | Updates plugin metadata to mention Channels + correct homepage URL. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Deep copy DEFAULT_SETTINGS in readSettings to prevent shared-reference
mutation of nested gating object and watchedChannels array
- Validate allowlist on permission button clicks — extract body.user.id
from Slack action payload and check gating before emitting verdict
- Show both slack and slack-channel entries in README .mcp.json snippet
to prevent users from overwriting existing remote server config
- Register event handlers before app.start() to avoid missing events
during the Socket Mode connection window
- Update spec regex to match implementation: [a-km-z0-9]{5}
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Super cool PR @marciogranzotto! 🤯 I've marked this as While we wait, I'll give the PR some early feedback 😄 |
There was a problem hiding this comment.
The docs/ changes look like an accidental commit. We typically reserve docs/ for the public documentation on https://docs.slack.dev, so these files should be removed.
There was a problem hiding this comment.
You're right — the docs/superpowers/ files (plans and specs) are development artifacts that shouldn't be in the repo. Removed in a3cf06f.
For docs/slack-app-setup.md, this is the Slack app setup guide for the Channels feature — it's user-facing documentation, not a dev artifact. Let me know if it should be moved elsewhere.
🤖 Generated with Claude Code
.mcp.json
Outdated
| } | ||
| }, | ||
| "slack-channel": { | ||
| "command": "bun", |
There was a problem hiding this comment.
question: Why bun? I don't think we can assume all developers have bun installed on their system.
There was a problem hiding this comment.
Good point. bun was chosen for its native TypeScript execution (no build step), but you're right that we can't assume it's available. Switched to npx tsx so only Node.js/npm is required. Fixed in bd6036b.
🤖 Generated with Claude Code
bun.lock
Outdated
There was a problem hiding this comment.
question: We'd need to discuss adding bun support to the project. I'd suggest removing this file
There was a problem hiding this comment.
Agreed — removed bun.lock and added it to .gitignore. The project now uses package-lock.json via npm. Fixed in bd6036b.
🤖 Generated with Claude Code
package.json
Outdated
| "version": "0.0.1", | ||
| "type": "module", | ||
| "scripts": { | ||
| "start": "bun src/index.ts", |
There was a problem hiding this comment.
suggestion: I'd suggest npx / npm instead of bun.
There was a problem hiding this comment.
Done — switched to npm-compatible tooling throughout:
"start": "tsx src/index.ts"(viatsxas a dependency)"test": "vitest run"(migrated all 5 test files frombun:testtovitest)- Replaced
@types/bunwith@types/node
🤖 Generated with Claude Code
README.md
Outdated
|
|
||
| Save the configuration. You will also see a connect button once added. Click that to authenticate into your Slack Workspace. | ||
|
|
||
| ## Channels (Research Preview) |
There was a problem hiding this comment.
suggestion: This plugin works with Cursor and Claude Code. So we should clarify that this is a Claude Code-specific feature.
There was a problem hiding this comment.
Good point. Updated the heading to "Channels for Claude Code (Research Preview)" to make it clear this is a Claude Code-specific feature. Fixed in 8323955.
🤖 Generated with Claude Code
Remove docs/superpowers/ planning and spec files that were accidentally committed. The docs/ directory is reserved for public documentation on docs.slack.dev. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace bun runtime with tsx for TypeScript execution and vitest for testing. This removes the bun dependency so only Node.js/npm is required. - Replace bun with npx tsx in .mcp.json and package.json - Replace bun test with vitest in package.json - Replace @types/bun with @types/node, tsx, vitest - Remove bun.lock, generate package-lock.json - Add bun.lock to .gitignore Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace bun:test imports with vitest across all 5 test files. Replace mock() with vi.fn() in bridge and integration tests. All matchers are API-compatible between bun:test and vitest. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update README heading to 'Channels for Claude Code (Research Preview)' to clarify this feature requires Claude Code. Replace all bun references with npx tsx in README, CLAUDE.md, and slack-app-setup.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Adds Claude Code Channels support to the Slack plugin, enabling real-time bidirectional messaging between Slack and Claude Code sessions via Socket Mode.
Closes #22
What it does
manage_channelstoolArchitecture
A single Bun process with three layers:
@slack/boltin Socket Mode) — receives events, sends replies@modelcontextprotocol/sdk) —claude/channel+claude/channel/permissioncapabilitiesNew files
Test coverage
62 tests across 5 files covering:
Test plan
bun test— 62/62)pair CODE→ access granted)conversations.joingracefully handles already-in-channel🤖 Generated with Claude Code