← All posts
·9 min read

Claude Code Slack Integration: 3 Ways to Connect

Claude CodeSlackIntegrationTeam Workflows
Claude Code Slack Integration Guide

Why connect Claude Code to Slack?

Most development teams live in Slack. Code reviews, deployment updates, incident alerts, and standups all flow through channels. But Claude Code runs in the terminal, disconnected from where your team communicates.

Bridging this gap means your AI coding sessions can notify teammates when deployments finish, flag code review findings in the right channel, and surface important decisions without anyone switching between tools.

The connection works through two mechanisms: MCP servers for direct Slack API access, and hooks for event-driven notifications. Neither requires building a custom Slack app from scratch. You configure them once, and they work automatically from that point forward.

Architecture overview

There are three ways to connect Claude Code to Slack, from simplest to most capable:

Method Complexity Capabilities
Webhook notifications Low Send messages to channels. One-direction only.
MCP server Medium Read and write messages, channels, reactions. Two-way.
Custom Slack app + hooks High Full Slack API access, interactive buttons, threads, slash commands.

Most teams should start with webhook notifications and upgrade to an MCP server when they need two-way communication. The custom app route is only necessary for advanced interactive workflows.

Method 1: Slack webhooks with hooks

This is the fastest way to get Claude Code notifications into Slack. It requires zero external dependencies - just a webhook URL and a Claude Code hook.

Setting up the webhook

  1. Go to api.slack.com/apps and create a new app (or use an existing one)
  2. Click Incoming Webhooks and toggle it on
  3. Click Add New Webhook to Workspace and select the target channel
  4. Copy the webhook URL - it looks like https://hooks.slack.com/services/T00/B00/xxxx

Creating the notification hook

Claude Code hooks run shell scripts at lifecycle events. Create a hook that fires after specific operations and sends a Slack message.

Add this to your .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "command": ".claude/hooks/slack-notify.sh"
      }
    ]
  }
}

Then create the notification script:

#!/bin/bash
# .claude/hooks/slack-notify.sh

WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
TOOL_NAME="$CLAUDE_TOOL_NAME"
PROJECT=$(basename "$(pwd)")

# Only notify on specific events
case "$TOOL_NAME" in
  "Bash")
    # Check if the command was a deploy or test
    if echo "$CLAUDE_TOOL_INPUT" | grep -qE "(git push|npm run deploy|npm test)"; then
      MESSAGE="*${PROJECT}*: \`${CLAUDE_TOOL_INPUT}\` completed"
      curl -s -X POST "$WEBHOOK_URL" \
        -H 'Content-type: application/json' \
        -d "{\"text\": \"$MESSAGE\"}"
    fi
    ;;
esac

Make it executable:

chmod +x .claude/hooks/slack-notify.sh

Now every time Claude Code runs a deploy or test command, your Slack channel gets a notification. No polling, no manual messages, no forgetting to update the team.

Filtering notifications

The script above filters to only deployment and test commands. You can customize the filter to match your workflow:

# Notify on git operations
if echo "$CLAUDE_TOOL_INPUT" | grep -qE "(git push|git merge|git tag)"; then

# Notify on file changes to specific paths
if echo "$CLAUDE_TOOL_INPUT" | grep -qE "(migrations/|schema\.)"; then

# Notify on any write to production config
if echo "$CLAUDE_TOOL_INPUT" | grep -qE "(\.env\.production|config/prod)"; then

The key is sending the right notifications. Too many and the channel becomes noise. Too few and the integration is useless. Start with deploys and test failures, then expand based on what your team actually wants to see.

Method 2: Slack MCP server

For two-way Slack communication, use an MCP server. This gives Claude Code the ability to read messages, post to threads, add reactions, and interact with Slack as a full participant.

Installing the Slack MCP server

Several community MCP servers exist for Slack. The most common approach uses the official Slack SDK wrapped in an MCP interface.

Add the server to your .mcp.json:

{
  "mcpServers": {
    "slack": {
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-slack"],
      "env": {
        "SLACK_BOT_TOKEN": "xoxb-your-bot-token",
        "SLACK_TEAM_ID": "T00000000"
      }
    }
  }
}

For details on how MCP servers work with Claude Code, see our dedicated guide.

Getting a Slack bot token

  1. Go to api.slack.com/apps
  2. Create a new app or select your existing one
  3. Navigate to OAuth & Permissions
  4. Add the required bot token scopes:
    • chat:write - Post messages
    • channels:read - List channels
    • channels:history - Read channel messages
    • reactions:write - Add emoji reactions
    • files:write - Upload files (for code snippets)
  5. Install the app to your workspace
  6. Copy the Bot User OAuth Token (starts with xoxb-)

Using Slack tools in Claude Code

Once the MCP server is configured, Claude Code gains Slack-specific tools. You can use them in commands, agents, or interactive sessions:

Post a summary of today's code changes to #engineering

Claude Code will use the Slack MCP tools to compose and send the message. Because it has full context of the current session, the summary includes accurate details about what was changed and why.

Practical MCP workflows

Daily standup automation:

Create a custom command that generates and posts a standup:

---
description: Generate and post daily standup to Slack
allowed-tools:
  - Read
  - Bash(git:*)
  - mcp__slack__post_message
---

Generate a daily standup update:

1. Run `git log --since="yesterday" --author="$(git config user.name)"` to get recent commits
2. Read memory.md for current priorities and blockers
3. Format as a standup: Done / Doing / Blocked
4. Post to #daily-standup channel via Slack

Code review notifications:

---
description: Post code review findings to Slack
allowed-tools:
  - Read
  - Bash(git:*)
  - Grep
  - mcp__slack__post_message
---

Review the current PR and post findings:

1. Run `git diff main...HEAD` to see all changes
2. Review for security, performance, and quality issues
3. Post a summary to #code-review with:
   - PR title and link
   - Number of files changed
   - Key findings (critical, warnings, notes)
   - Overall assessment

Deployment alerts:

---
description: Deploy and notify team
allowed-tools:
  - Bash
  - mcp__slack__post_message
---

Deploy the current branch:

1. Run the test suite
2. If tests pass, push to the deployment branch
3. Post to #deployments:
   - What was deployed
   - Key changes included
   - Any manual steps needed
4. If tests fail, post to #engineering with the failure details

Method 3: Custom Slack app with interactive features

For teams that want interactive Slack workflows - buttons, modals, slash commands that trigger Claude Code sessions - you need a custom Slack app with a backend.

Architecture

Developer types /review in Slack
    -> Slack sends webhook to your server
    -> Server spawns Claude Code in headless mode
    -> Claude Code runs the review
    -> Results posted back to Slack via API

This requires a server to receive Slack events and spawn Claude Code processes. Common approaches:

  • n8n workflow - No-code automation that receives Slack webhooks and runs Claude Code
  • Simple Express server - Node.js app deployed on Railway, Render, or similar
  • AWS Lambda - Serverless function triggered by Slack events

Slash command example

Register a /claude-review slash command in your Slack app settings, pointing to your server endpoint:

// Express endpoint for Slack slash command
app.post('/slack/commands/review', async (req, res) => {
  // Acknowledge immediately (Slack requires response within 3 seconds)
  res.json({ text: 'Starting code review...' });

  const { channel_id, text } = req.body;

  // Run Claude Code in headless mode
  const result = await exec(
    `cd /path/to/repo && claude --print "Review the last commit for security and quality issues. Format as a brief summary."`
  );

  // Post results back to Slack
  await slack.chat.postMessage({
    channel: channel_id,
    text: result.stdout,
  });
});

Interactive buttons

Post messages with action buttons that trigger follow-up Claude Code operations:

await slack.chat.postMessage({
  channel: '#code-review',
  blocks: [
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: '*Code Review Complete*\nFound 2 security issues and 1 performance warning.'
      }
    },
    {
      type: 'actions',
      elements: [
        {
          type: 'button',
          text: { type: 'plain_text', text: 'Auto-fix Issues' },
          action_id: 'autofix',
          style: 'primary'
        },
        {
          type: 'button',
          text: { type: 'plain_text', text: 'Show Details' },
          action_id: 'details'
        }
      ]
    }
  ]
});

When a developer clicks "Auto-fix Issues," your server receives the action, spawns Claude Code with a fix command, and posts the results back to the thread.

Real-world integration patterns

Pattern 1: Deploy pipeline with Slack gates

Developer runs /deploy in Claude Code
  -> Hook sends "Deploy starting" to #deployments
  -> Tests run
  -> Hook sends test results to Slack
  -> If tests pass: deploy executes
  -> Hook sends "Deploy complete" with changes summary
  -> If tests fail: hook sends failure details + suggests fixes

Pattern 2: Incident response

Alert fires in #incidents
  -> Developer triggers /incident-triage via Slack command
  -> Claude Code analyzes recent changes, logs, and error patterns
  -> Findings posted to incident thread
  -> Suggested fixes include file paths and code snippets
  -> Developer applies fix, Claude Code posts confirmation

Pattern 3: Async code review

PR opened on GitHub
  -> GitHub webhook triggers n8n workflow
  -> n8n spawns Claude Code review
  -> Review findings posted to #code-review with PR link
  -> Developers discuss in Slack thread
  -> Approval/rejection tracked via emoji reactions

Security considerations

Token storage

Never hardcode Slack tokens in your hook scripts or MCP configuration files that get committed to git. Use environment variables or a secrets manager:

# In .zshrc (personal machine)
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
export SLACK_BOT_TOKEN="xoxb-..."
// In .mcp.json (reference env vars, don't commit tokens)
{
  "env": {
    "SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}"
  }
}

Channel permissions

Scope your Slack bot to specific channels rather than giving it workspace-wide access. In your Slack app settings:

  • Only install to channels where notifications are needed
  • Use private channels for sensitive notifications (security findings, deployment errors)
  • Separate channels for different notification types so people can mute what they don't need

Rate limiting

Slack's API has rate limits (roughly 1 message per second per channel). If your hooks fire frequently, batch notifications or add debouncing:

# Simple debounce: only notify if last notification was more than 30 seconds ago
LOCKFILE="/tmp/slack-notify-${PROJECT}.lock"
if [ -f "$LOCKFILE" ]; then
  LAST=$(stat -f %m "$LOCKFILE" 2>/dev/null || stat -c %Y "$LOCKFILE" 2>/dev/null)
  NOW=$(date +%s)
  if [ $((NOW - LAST)) -lt 30 ]; then
    exit 0  # Skip notification
  fi
fi
touch "$LOCKFILE"

Troubleshooting

Messages not appearing in Slack

  • Verify the webhook URL is correct (test with a manual curl command)
  • Check that the bot has been invited to the target channel (/invite @your-bot)
  • Ensure the hook script is executable (chmod +x)
  • Check Claude Code hook logs for errors

MCP server not connecting

  • Verify the bot token starts with xoxb- (not xoxp- which is a user token)
  • Check that required OAuth scopes are added and the app is reinstalled after scope changes
  • Ensure the MCP server package is accessible (npx can reach the registry)
  • Look at Claude Code's MCP server status with the /hooks command

Messages are too noisy

Start with fewer notification triggers and add more over time. A common mistake is notifying on every file write or command execution. Focus on workflow boundaries: deploy started, deploy finished, review complete, tests failed. These are the events your team actually wants to know about.

Frequently asked questions

Can Claude Code respond to messages in Slack directly?

With an MCP server configured, Claude Code can read and post messages to Slack channels during an active session. However, Claude Code does not run as a persistent service - it requires an active terminal session. For always-on Slack responses, you need a backend server that receives Slack events and spawns Claude Code in headless mode (claude --print). The MCP approach works for session-driven workflows where a developer is actively working and wants to push updates to Slack.

Do I need a paid Slack plan for this integration?

No. Slack's free plan supports incoming webhooks, bot tokens, and the full API. The webhook approach works entirely on free Slack. MCP servers and custom apps also work on free plans. The only Slack features that require paid plans (channels, user groups, advanced permissions) are unrelated to the Claude Code integration.

How do I prevent sensitive code from being posted to Slack?

Add filtering to your hook scripts or MCP commands. Before posting any content to Slack, strip or redact sensitive patterns: API keys, database connection strings, internal URLs, and credentials. You can use a simple grep filter in your hook script, or add a dedicated sanitization step. For MCP-based workflows, include explicit instructions in your command files: "Never include API keys, tokens, passwords, or connection strings in Slack messages. Summarize findings without quoting sensitive values."

Get Claudify - Pre-built hooks, MCP configurations, and team workflows. Install with npx create-claudify.

More like this

Ready to upgrade your Claude Code setup?

Get Claudify
Featured on Dofollow.Tools AI Toolz Dir