Two-way Slack ↔ Claude Code bridge. Chat with Claude from Slack DMs and channels, just like you'd chat in the terminal. Per-thread session isolation, hash-chained tamper-evident audit journal with optional per-channel Slack projection, policy-gated tools, five-layer prompt-injection defense.
Links: Gist One-Pager · GitHub Pages · Release Notes
Research Preview — Channels require Claude Code v2.1.80+ and
claude.ailogin.
Slack workspace (cloud)
↕ WebSocket (Socket Mode — outbound only, no public URL)
server.ts (local MCP server, spawned by Claude Code)
↕ stdio (MCP transport)
Claude Code session
Socket Mode means no public URL needed — works behind firewalls, NAT, anywhere.
- Go to api.slack.com/apps → Create New App → From scratch
- Socket Mode: Settings → Socket Mode → Enable → Generate App-Level Token (
xapp-...) withconnections:writescope - Event Subscriptions: Enable → Subscribe to bot events:
message.im— DMsmessage.channels— public channelsmessage.groups— private channelsapp_mention— @ mentions
- Bot Token Scopes (OAuth & Permissions):
chat:write— send messageschannels:history— read public channelsgroups:history— read private channelsim:history— read DMsreactions:write— add reactionsfiles:read— download shared filesfiles:write— upload filesusers:read— resolve display names
- Install to Workspace → Copy Bot Token (
xoxb-...)
/slack-channel:configure xoxb-your-bot-token xapp-your-app-tokenPick your runtime:
bun install
# Current (claude-code-plugins marketplace):
claude --channels plugin:slack-channel@claude-code-plugins
# Future (after upstream approval):
# claude --channels plugin:slack-channel@claude-plugins-officialnpm install
# In .mcp.json, change command to: "npx", args: ["tsx", "server.ts"]
claude --channels plugin:slack-channel@claude-code-pluginsdocker build -t claude-slack-channel .
# In .mcp.json, change command to: "docker", args: ["run", "--rm", "-i", "-v", "~/.claude/channels/slack:/state", "claude-slack-channel"]
claude --channels plugin:slack-channel@claude-code-plugins- DM the bot in Slack — you'll get a 6-character pairing code
- In your terminal:
/slack-channel:access pair <code> - You're connected. Chat away.
Author rules in access.json.policy to automate permission decisions for Claude Code tool calls. Three rule effects, first-applicable ordering:
{
"policy": [
{
"id": "safe-reads-in-ops",
"effect": "auto_approve",
"match": { "tool": "Read", "channel": "C_OPS_DOCS" }
},
{
"id": "no-shell",
"effect": "deny",
"match": { "tool": "Bash" },
"reason": "Shell execution is not permitted."
},
{
"id": "dangerous-writes",
"effect": "require_approval",
"match": { "tool": "Write", "channel": "C_DEPLOY" },
"approvers": 2,
"ttlMs": 300000
}
]
}auto_approve— skip the Block Kit prompt; the tool call runs immediately and apolicy.allowevent is journaled.deny— the reason is posted back into the originating thread and the call is rejected.policy.denyis journaled.require_approval— route through human approver(s).approvers: 2requires two distinct Slackuser_ids (NIST two-person integrity; the same user cannot double-satisfy quorum by clicking twice). A single deny from any allowlisted user rejects the request immediately regardless of quorum count.- Successful approvals grant a TTL window scoped to
(rule, channel, thread)so a chain of similar calls doesn't re-prompt. - Parse errors in
access.json.policyare fatal at boot — policy is safety-critical, silent degradation is not offered. Missing or emptypolicyis fine (first-install path).
Full schema reference: ACCESS.md. Decision procedure: 000-docs/policy-evaluation-flow.md. Release scope and what was deliberately deferred: 000-docs/v0.6.0-release-plan.md.
See ACCESS.md for the full schema.
/slack-channel:access policy allowlist # Only pre-approved users
/slack-channel:access add U12345678 # Add a user
/slack-channel:access remove U12345678 # Remove a user
/slack-channel:access channel C12345678 # Opt in a channel
/slack-channel:access channel C12345678 --mention # Require @mention
/slack-channel:access status # Show current configChannels can opt in to cross-bot message delivery by listing trusted bot user IDs in allowBotIds. Useful when multiple Claude Code instances (or other bots you operate) need to coordinate in a shared channel — e.g., an ops-monitor agent and an engineering agent in #incidents. Default is no cross-bot delivery: every bot message is dropped at the gate. See ACCESS.md for the full schema and security tradeoffs.
Example access.json entry:
{
"channels": {
"C_INCIDENTS": {
"requireMention": false,
"allowFrom": ["U_OPS_BOT", "U_ENG_BOT", "U_HUMAN"],
"allowBotIds": ["U_OPS_BOT", "U_ENG_BOT"]
}
}
}Self-echoes from this bot are always filtered regardless of allowBotIds. Peer bots cannot approve permission prompts — the permission relay gates on the top-level allowFrom, not the channel policy.
- Sender gating: Every inbound message hits a gate. Ungated messages are silently dropped before reaching Claude.
- Outbound gate: Replies only work to channels that passed the inbound gate.
- File exfiltration guard: Cannot send
.env,access.json, or other state files through the reply tool. - Prompt injection defense: System instructions explicitly tell Claude to refuse pairing/access requests from Slack messages.
- Bot filtering:
bot_idmessages are dropped by default. Channels that host multiple cooperating agents can opt in to specific peers viaallowBotIds; self-echoes are always filtered viabot_id/bot_profile.app_id/usertriple-check. - Link unfurling disabled: All outbound messages set
unfurl_links: false, unfurl_media: false. - Token security:
.envischmod 0o600, never logged, never in tool results. - Static mode: Set
SLACK_ACCESS_MODE=staticto freeze access at boot (no runtime mutation).
# Dev mode (bypasses plugin allowlist):
claude --dangerously-load-development-channels server:slackFull project one-pager and operator-grade system analysis
- @jeremylongshore — author, maintainer
- @maui-99 — security hardening review (v0.3.0)
- @jinsung-kang — clean shutdown on client disconnect (v0.3.1)
- @CaseyMargell — event deduplication fix (v0.3.1), cross-bot delivery via
allowBotIds(v0.4.0)
MIT