Reflect your Claude Code activity in your Slack status, automatically.
It tracks how many Claude Code sessions you have open and how many are actively thinking (working on a prompt right now), and keeps your Slack profile status in sync:
| State | Emoji | Status text |
|---|---|---|
| No sessions open | (cleared) | (cleared) |
| Sessions open, all idle | 🤖 | 3 Claudes open, idle |
| Some thinking | 1️⃣–🔟 | 2 of 3 Claudes thinking |
The emoji shows up everywhere Slack renders your status — the sidebar, the member list, next to your name in channels — so your team can see at a glance when you've got a swarm of agents churning. The text shows on hover.
Claude Code fires hooks at lifecycle events. This is one small Bash script wired into four of them:
| Hook | Event | Meaning |
|---|---|---|
SessionStart |
start |
a session opened (idle) |
UserPromptSubmit |
thinking |
you sent a prompt — that session is now working |
Stop |
idle |
Claude finished responding — back to idle |
SessionEnd |
end |
the session closed |
Each event writes a tiny state file (one per session) under ~/.claude/sessions-status/, then the script counts the files, builds the status, and calls Slack's users.profile.set. The Slack call is backgrounded so the hook returns instantly and never slows Claude Code down. A short debounce coalesces bursts of events into a single API call, and stale state files (from sessions that crashed without firing end) are reaped after 24h.
No daemon, no dependencies beyond bash, jq, and curl.
- macOS or Linux with
bash,jq, andcurl - Claude Code (any version with hooks support)
- A Slack workspace where you can create an app
- Go to https://api.slack.com/apps → Create New App → From scratch. Name it (e.g. "Claude Status") and pick your workspace.
- In the sidebar, open OAuth & Permissions.
- Under Scopes → User Token Scopes, add
users.profile:write. (It must be a User token scope, not a Bot token scope — you're setting your own status.) - Click Install to Workspace at the top and authorize.
- Copy the User OAuth Token — it starts with
xoxp-.
Heads up: a freshly created Slack app can take ~10–15 minutes before
users.profile.setstarts working — early calls may return HTTP 500 with anx-slack-failure: timeoutheader even though your token and scope are correct. This is app provisioning lag, not a misconfiguration. If you hit it, wait a few minutes and retry.
git clone https://github.com/kmizzi/claude-code-slack-status.git
cd claude-code-slack-status
./install.shinstall.sh copies the script to ~/.claude/hooks/, prompts for your token (stored at ~/.config/slack-status-token, mode 0600), and prints the hooks JSON to add to your settings.
Merge the contents of settings.hooks.json into your Claude Code settings (~/.claude/settings.json), replacing __HOOK__ with the absolute path to the installed script (install.sh prints this for you). If you already have a "hooks" block, merge the keys rather than replacing it. For example:
{
"hooks": {
"SessionStart": [
{ "hooks": [ { "type": "command", "command": "/Users/you/.claude/hooks/slack-claude-status.sh start", "timeout": 5 } ] }
],
"UserPromptSubmit": [
{ "hooks": [ { "type": "command", "command": "/Users/you/.claude/hooks/slack-claude-status.sh thinking", "timeout": 5 } ] }
],
"Stop": [
{ "matcher": "", "hooks": [ { "type": "command", "command": "/Users/you/.claude/hooks/slack-claude-status.sh idle", "timeout": 5 } ] }
],
"SessionEnd": [
{ "hooks": [ { "type": "command", "command": "/Users/you/.claude/hooks/slack-claude-status.sh end", "timeout": 5 } ] }
]
}
}Open a new Claude Code session and your Slack status should light up.
Everything is overridable via environment variables (set them in the hook command or your shell profile):
| Variable | Default | Purpose |
|---|---|---|
SLACK_STATUS_TOKEN_FILE |
~/.config/slack-status-token |
Path to the file holding your token |
SLACK_STATUS_TOKEN |
(unset) | The token inline (overrides the file) |
SLACK_STATUS_STATE_DIR |
~/.claude/sessions-status |
Where per-session state files live |
SLACK_STATUS_LOG |
/tmp/claude-slack-status.log |
Debug log |
SLACK_STATUS_DEBOUNCE |
2 |
Seconds to coalesce a burst of events |
- Your token is read from a file (mode
0600) or an env var — it is never hardcoded and never committed..gitignoreexcludes token files, state, and logs. - The Slack scope is the single narrowest one that works:
users.profile:write. The app can set your status and nothing else. - Session IDs are sanitized before they're used as filenames.
- Status never updates. Check
/tmp/claude-slack-status.log— the raw Slack API response is appended there.{"ok":true}means success;invalid_authmeans a bad/expired token;missing_scopemeans the app lacksusers.profile:write. - HTTP 500 /
timeoutright after creating the app. Provisioning lag — wait ~15 min and retry (see the note above). - Hooks don't fire. Make sure the script is executable (
chmod +x) and the path insettings.jsonis absolute. Runclaude --debugto see hook execution.