ccth
v0.0.7
Published
Claude Code session messages to Slack thread notifier
Readme
CCTH - Claude Code to Slack Thread Hook
A CLI tool that sends Claude Code session messages to Slack threads. Designed to be used as a hook in Claude Code for real-time session monitoring and collaboration.

Features
- 🔄 Real-time session message forwarding to Slack
- 🧵 Automatic thread management per session
- 📝 Rich message formatting with proper context
- 🔧 Configurable via environment variables or CLI options
- 🧪 Comprehensive test coverage
- 🚀 Built with TypeScript for type safety
Installation
From npm (recommended)
npm install -g ccth
# or
pnpm add -g ccth
# or
yarn global add ccthFrom source
# Clone the repository
git clone https://github.com/mkusaka/ccth.git
cd ccth
# Install dependencies
pnpm install
# Build the project
pnpm run build
# Link globally
pnpm link --globalUsage
As a Claude Code Hook
- Set up environment variables:
export SLACK_BOT_TOKEN="xoxb-your-slack-bot-token"
export SLACK_CHANNEL="C1234567890" # Your Slack channel ID- Configure Claude Code hooks in your settings file (
~/.claude/settings.jsonor project-specific.claude/settings.json):
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
]
}
}This configuration will:
- Send user prompts to Slack when submitted (
UserPromptSubmit) - Send tool execution results to Slack after completion (
PostToolUse)
Note: UserPromptSubmit doesn't require a matcher since it's not tool-specific.
CLI Options
ccth [options]
Options:
-c, --channel <channel> Slack channel ID or name (env: SLACK_CHANNEL)
-t, --token <token> Slack bot token (env: SLACK_BOT_TOKEN)
-d, --debug Enable debug logging and event storage
--dry-run Process messages without sending to Slack
--thread-timeout <seconds> Thread inactivity timeout in seconds (default: 3600)
-V, --version output the version number
-h, --help display help for commandDebug Mode and Event Logging
When running with the -d, --debug flag, ccth will save raw hook events to disk for debugging purposes:
~/.ccth/
└── {session_id}/
├── thread.json # Session metadata
└── events.jsonl # Raw hook events in chronological orderThis is useful for debugging and analyzing Claude Code session activity.
Example Hook Input
The tool expects Claude Code hook event JSON via stdin:
# UserPromptSubmit event
echo '{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/home/user/project",
"hook_event_name": "UserPromptSubmit",
"prompt": "Help me write a function"
}' | ccth
# PostToolUse event
echo '{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/home/user/project",
"hook_event_name": "PostToolUse",
"tool_name": "Write",
"tool_input": {"file_path": "/test.txt", "content": "Hello"},
"tool_response": {"success": true}
}' | ccth
# Dry run mode for testing
echo '{...}' | ccth --dry-run --debugSlack Bot Setup
Step 1: Create a Slack App
- Go to Slack API Apps page
- Click "Create New App"
- Choose "From scratch"
- Enter:
- App Name:
CCTH Bot(or your preferred name) - Pick a workspace: Select your Slack workspace
- App Name:
- Click "Create App"
Step 2: Configure Bot Token Scopes
- In your app's dashboard, navigate to "OAuth & Permissions" in the left sidebar
- Scroll down to "Scopes" section
- Under "Bot Token Scopes", click "Add an OAuth Scope"
- Add the following scopes:
chat:write- Required for sending messageschat:write.public- Required if posting to public channelschannels:read- Optional: To list channelsgroups:read- Optional: To access private channels
- Save your changes
Step 3: Install App to Workspace
- Scroll to the top of the "OAuth & Permissions" page
- Click "Install to Workspace"
- Review the permissions and click "Allow"
- You'll be redirected back to the OAuth & Permissions page
Step 4: Copy Bot Token
- After installation, you'll see a "Bot User OAuth Token" starting with
xoxb- - Click "Copy" to copy the token
- Save this token securely - you'll need it for the
SLACK_BOT_TOKENenvironment variable
Step 5: Find Your Channel ID
Method 1: From Slack App
- Right-click on the channel name in Slack
- Select "View channel details"
- Scroll to the bottom
- The Channel ID starts with
C(e.g.,C1234567890)
Method 2: From Slack Web
- Open Slack in your browser
- Navigate to the channel
- The URL will contain the channel ID:
https://app.slack.com/client/T[TEAM_ID]/C[CHANNEL_ID]
Step 6: Add Bot to Channel
- In Slack, go to the channel where you want the bot to post
- Type
/invite @CCTH Bot(or your bot's name) - Press Enter to invite the bot
Step 7: Set Environment Variables
# Add to your shell profile (~/.bashrc, ~/.zshrc, etc.)
export SLACK_BOT_TOKEN="xoxb-your-bot-token-here"
export SLACK_CHANNEL="C1234567890" # Your channel ID
# Or create a .env file in your project
echo 'SLACK_BOT_TOKEN="xoxb-your-bot-token-here"' >> ~/.env
echo 'SLACK_CHANNEL="C1234567890"' >> ~/.envTroubleshooting
Bot can't post to channel
- Ensure the bot is invited to the channel
- For private channels, the bot needs to be a member
- Check that you have the correct channel ID
Invalid token error
- Verify the token starts with
xoxb- - Ensure you copied the entire token
- Check if the app is still installed in your workspace
Permission errors
- Verify all required scopes are added
- Reinstall the app after adding new scopes
- For public channels, ensure
chat:write.publicscope is added
Development
# Run in development mode
pnpm run dev
# Run tests
pnpm test
# Run tests with coverage
pnpm run test:coverage
# Type checking
pnpm run typecheck
# Linting
pnpm run lint
# Format code
pnpm run formatComplete Setup Guide
Prerequisites
- Node.js 18+ installed
- A Slack workspace where you have permissions to create apps
- Claude Code installed
Quick Setup (5 minutes)
1. Install CCTH
npm install -g ccth
# or
pnpm add -g ccth
# or
yarn global add ccth2. Create Slack Bot
Follow the Slack Bot Setup section above to:
- Create a new Slack app
- Add required bot token scopes (
chat:write,chat:write.public) - Install the app to your workspace
- Copy the bot token (starts with
xoxb-) - Get your channel ID
- Invite the bot to your channel
3. Configure Environment
# Option 1: Export in your shell profile (~/.bashrc, ~/.zshrc, etc.)
export SLACK_BOT_TOKEN="xoxb-your-bot-token-here"
export SLACK_CHANNEL="C1234567890"
# Option 2: Create a .env file in your home directory
cat > ~/.env << EOF
SLACK_BOT_TOKEN="xoxb-your-bot-token-here"
SLACK_CHANNEL="C1234567890"
EOF
# Load the environment variables
source ~/.env4. Configure Claude Code
Create or edit ~/.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
]
}
}5. Test Your Setup
# Test with a dry run
echo '{"session_id": "test", "hook_event_name": "UserPromptSubmit", "prompt": "Test message"}' | ccth --dry-run --debug
# If successful, test actual Slack posting
echo '{"session_id": "test", "hook_event_name": "UserPromptSubmit", "prompt": "Hello from CCTH!"}' | ccthYou should see a message appear in your Slack channel!
Advanced Configuration
Monitor All Events
For comprehensive session monitoring, add all supported events:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
]
}
}Project-Specific Configuration
Create .claude/settings.json in your project directory for project-specific hooks:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "ccth --channel C0987654321"
}
]
}
]
}
}Multiple Workspaces
Use different channels for different projects:
# Personal projects
alias ccth-personal='ccth --channel C1111111111'
# Work projects
alias ccth-work='ccth --channel C2222222222'Then update your Claude Code settings to use the aliases.
See examples/ directory for more configuration examples.
Hook Events Supported
Core Events (Recommended)
UserPromptSubmit: Captures user prompts when submitted
- Shows user input with timestamp
- Essential for tracking conversation flow
PostToolUse: Captures tool execution results
- Shows tool name, input parameters, and response
- Helps track what actions Claude is performing
Additional Events
Stop: Triggered when Claude completes its response
- Shows session completion status
- Useful for tracking when Claude finishes tasks
- Includes
stop_hook_activeflag if stop hook is preventing completion
Notification: System notifications from Claude Code
- Permission requests (e.g., "Claude needs your permission to use Bash")
- Idle notifications (e.g., "Claude is waiting for your input")
- Automatically categorized with appropriate icons (🔐 for permissions, ⏳ for idle)
Message Formatting
Each event is formatted with:
- Timestamp
- Event-specific icon
- Rich formatting using Slack Block Kit
- Contextual information based on event type
Thread Management
- Each Claude Code session gets its own Slack thread
- Threads are reused for the same session ID
- Inactive threads expire after the configured timeout (default: 1 hour)
- Thread cleanup runs automatically every 5 minutes
Configuration
Environment Variables
SLACK_BOT_TOKEN: Your Slack bot token (required)SLACK_CHANNEL: Default Slack channel ID (required)
Hook Configuration Examples
Monitor Only Specific Tools
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "ccth --debug"
}
]
}
]
}
}Note: For PostToolUse, if you omit the matcher field entirely, it will match all tools.
Full Session Monitoring
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
],
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "ccth"
}
]
}
]
}
}This configuration provides:
- User prompts via
UserPromptSubmit - Tool executions via
PostToolUse - Completion status via
Stop - Permission requests and idle alerts via
Notification
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
