Collaborate with Claude Code as a team -- one Discord thread, multiple minds.
Your team's AI pair programmer, one Discord thread away.
Your team uses Claude Code, but each person runs their own session in their own terminal. Nobody sees what Claude is doing for someone else. Context gets lost, work gets duplicated, and junior devs are left out of the loop.
Claude Crew turns Claude Code into a shared, real-time experience. One person starts a session in Discord. Teammates jump in -- ask follow-up questions, steer Claude in a new direction, review its tool usage -- all in the same thread. Everyone sees the same streaming output, and every message is attributed to the person who sent it.
Concrete scenario: A backend engineer starts a Claude session to refactor the auth module. The security lead joins the thread to add constraints. A new hire watches the whole exchange and learns the codebase. The audit trail records who asked for what. The session runs on your machine with full file access -- nothing leaves your infrastructure.
Alice (laptop) --+
| Discord Thread Claude Crew (Rust) Claude Code CLI
Bob (phone) --+--> #refactor-auth --> session manager --> claude subprocess
Carol (tablet) --+ (per-user attribution) (your machine)
It also works great for solo use -- talk to Claude Code from your phone while away from your desk, check on long-running sessions, and approve tool permissions from anywhere.
- Alice uses
/claude refactor the auth modulein a server channel - Bot spawns a
claudesubprocess on your machine (using--input-format stream-json) - A Discord thread is created; Claude's response streams in real-time
- Bob opens the thread and types a follow-up -- he's auto-joined as a participant
- Carol types in the thread too -- she's auto-joined;
/participantsshows everyone in the session - Every message is attributed: Claude knows who said what
- Alice (the owner) can
/sessionkicksomeone or/endthe session
Works in both DMs (just message the bot directly) and server channels (creates a thread per session).
Multi-User Collaboration
- Auto-join -- authorized users typing in a session thread are automatically added as participants
- Participant management --
/participants,/sessionkick,/sessionbancommands for session membership - Per-user message attribution -- every message to Claude is tagged with the sender's identity
- Owner/participant roles -- session creator has owner privileges; controls who can
/end,/sessionkick, or/handoff - Full audit trail -- tool invocations logged to SQLite with user attribution, input JSON, result preview, error status, and duration
- Admin override -- server admins can manage any session regardless of ownership
Discord Integration
- DM mode -- message the bot directly, no slash commands needed
- Server mode -- thread-per-session with
/claudeslash command - @mention support -- mention the bot in a session thread to continue the conversation
- Message queuing -- messages sent while Claude is busy are queued and auto-processed
- Interrupt --
!prefix or/interruptkills current task and sends the new message - Natural follow-ups -- just type in the thread to continue
- Smart message chunking (handles Discord's 2000-char limit)
- Typing indicators and tool-use status
- Interactive prompts --
AskUserQuestionand permission requests are shown in Discord with @mention; reply to answer, auto-denied after 120s timeout - Expired session auto-resume -- messages in expired threads automatically start a fresh session with the user's message as the prompt (no confirmation needed)
/endarchives the thread after stopping the session
Claude Code Management
- Subprocess lifecycle via
tokio::processwith--output-format stream-json - Streaming
stream-jsonparser for real-time output control_requesthandling -- interactive permission prompts and user questions routed through Discord- Multi-turn conversations via
--resume SESSION_ID - Smart project resolution -- named projects, sibling directory discovery, or default cwd
- Configurable tool permissions per project (auto-approved in headless mode)
- Optional
--dangerously-skip-permissionsfor trusted environments - Git worktree isolation -- optional per-project worktree per session, so concurrent sessions on the same repo don't conflict (
use_worktrees = true) - Smart worktree lifecycle on
/end-- tracks whether the worktree branch was pushed (is_pushedin DB). If not pushed and has local changes (uncommitted or commits ahead), the worktree is preserved with an explicit message. If pushed, the worktree is cleaned up. The session reaper and startup cleanup apply the same logic -- worktrees with unpushed local work are never silently deleted - Worktree-aware resume after
/end-- sending a message in an ended session thread resumes intelligently: if the branch was pushed and still exists on the remote,git pull --ff-onlyruns first (fresh conversation to avoid stale context); if the worktree was preserved locally (not pushed), the conversation resumes with--resume(code state is identical). If the branch was pushed but no longer exists on the remote (merged or deleted), the session stays ended with an explicit message - Auto-PR on
/end-- when enabled (auto_pr = true),/endpushes the worktree branch and creates a PR viaghCLI if there are commits ahead of the default branch. Note: auto-PR currently usesgh(GitHub CLI) only. For GitLab repositories, keepauto_pr = falseand create merge requests manually or let Claude do it via Bash withglab mr create - Co-authored commits -- map Discord users to GitHub usernames/emails via config; collaborative sessions automatically add
Co-authored-bytrailers to every commit via aprepare-commit-msggit hook (worktree sessions) plus system prompt hints (all sessions) - Context-aware sessions -- periodic background task summarizes each session's activity (files touched, tools used, recent messages) and injects sibling summaries into the system prompt. Sessions on the same project know what each other is doing -- preventing conflicting edits and enabling coordinated parallel work. Includes file conflict detection with warnings when sessions touch overlapping files. Opt-in via
[claude.context_sharing] enabled = true - Auth error detection -- 401/auth failures from the Claude API are detected in the stream output and displayed as a formatted message with guidance to run
/login /logincommand -- admin-only OAuth PKCE flow, entirely from Discord. Generates an authorization URL, user authorizes in browser and pastes the callback code, bot exchanges it for tokens via the Anthropic API and writes~/.claude/.credentials.json. No CLI subprocess, no TTY, no manual file transfer needed- Session timeout and automatic cleanup
- stderr capture -- Claude process errors are logged and surfaced to Discord
Security
- Discord user/role allowlist
- Per-project tool restrictions (
--allowedToolsauto-approves listed tools; unlisted tools prompt via--permission-prompt-tool stdio) - No secrets in Discord -- Claude runs locally on your machine
Operations
- SQLite session persistence (survives bot restarts -- active sessions are reconciled to idle on startup so they can be resumed)
- TOML configuration
- Structured logging via
tracingwith custom poise error handler - Graceful shutdown (SIGINT/SIGTERM with 5s timeout)
Native:
- Rust (stable, latest) -- or use
nix-shellfor the dev environment - Claude Code CLI (
claude) v2.1.78+ -- installed and authenticated on your machine
Docker:
- Docker with Compose (Rust and Claude CLI are bundled in the image)
Both:
- Discord Bot -- created via the Developer Portal (see setup below)
- Anthropic authentication -- use
/loginin Discord (OAuth PKCE, recommended), or setANTHROPIC_API_KEYenv var
- Go to https://discord.com/developers/applications
- Click "New Application" -- give it a name (e.g. "Claude Remote")
- Note the Application ID on the General Information page
- Click "Bot" in the left sidebar
- Click "Reset Token" to generate a bot token
- Copy the token -- you'll need it for
config.toml. This is the only time you can see it. - Under Privileged Gateway Intents, enable:
- Message Content Intent (required -- the bot reads message text)
- Save changes
You need two IDs for the config. Enable Developer Mode in Discord first:
- Discord Settings → App Settings → Advanced → Developer Mode → ON
Then:
- Guild (Server) ID: Right-click your server name → Copy Server ID
- Your User ID: Right-click your username → Copy User ID
- Go to "OAuth2" in the left sidebar
- Under OAuth2 URL Generator:
- Scopes:
bot,applications.commands - Bot Permissions:
- View Channels
- Send Messages
- Send Messages in Threads
- Create Public Threads
- Manage Threads (archiving threads on
/end) - Read Message History
- Add Reactions (emoji feedback on messages)
- Use Slash Commands
- Scopes:
- Copy the generated URL and open it in your browser
- Select your server and authorize
# Enter dev environment (optional, if using Nix)
nix-shell
# Create config from example
cp config.example.toml config.toml
# Edit config.toml with your values:
# - discord.token = "your bot token from step 2"
# - discord.guild_id = your server ID from step 3
# - auth.allowed_users = [your user ID from step 3]
# - claude.default_cwd = path to your project directory
# Run the bot
cargo runVia DM: Just open a DM with the bot and type your message. No slash commands needed -- every message starts or continues a Claude session.
Via Server: Use /claude <prompt> in any channel. The bot creates a thread and streams Claude's response. Reply in the thread to continue.
Via @mention: In an existing session thread, @mention the bot with your message to continue the conversation.
Collaborate: Any authorized user who types in an active session thread is automatically joined as a participant. Use /participants to see who's in a session.
[discord]
token = "YOUR_BOT_TOKEN" # Bot token from Developer Portal
guild_id = 123456789012345678 # Your server ID
[claude]
binary = "claude" # Path to claude CLI
default_cwd = "/home/you/projects" # Default working directory
allowed_tools = ["Bash", "Read", "Write", "Edit", "Glob", "Grep", "WebSearch", "WebFetch", "Agent", "ToolSearch", "Skill", "NotebookEdit"]
max_sessions = 3 # Max concurrent sessions
session_timeout_minutes = 30 # Auto-kill after inactivity
# system_prompt = "Keep responses concise." # Optional system prompt
# dangerously_skip_permissions = false # Skip all permission prompts
# use_worktrees = false # Git worktree per session
# auto_pr = false # Auto-create PR on /end
[claude.context_sharing] # Cross-session context awareness
# enabled = false # Opt-in: summarize session activity
# interval_seconds = 120 # How often to update summaries
# max_summary_chars = 1500 # Budget for sibling context in prompt
[claude.projects.myapp] # Named project overrides
cwd = "/home/you/projects/myapp"
# allowed_tools = ["Read", "Grep"] # Restrict tools per project
# use_worktrees = true # Override per project
# auto_pr = true # Override auto-PR per project
[auth]
admins = [123456789012345678] # Can /approve, /revoke, /pending
admin_roles = [] # Roles with admin privileges
allowed_users = [123456789012345678] # Always authorized (config-managed)
allowed_roles = [] # Always authorized (by role)
[auth.user_identities.123456789012345678] # Map Discord ID -> Git identity
github_username = "octocat" # For Co-authored-by trailers
# email = "octocat@example.com" # Preferred over github noreply
[database]
url = "sqlite:data.db?mode=rwc" # SQLite DB path
[logging]
level = "info" # debug, info, warn, error
format = "pretty" # pretty or jsonThe bot uses --permission-prompt-tool stdio --permission-mode default to route all permission decisions through Discord:
- Listed tools (
allowed_tools) are auto-approved -- no prompt needed - Unlisted tools trigger a
control_request-- the bot displays the permission request in Discord with an @mention, and the user can reply to approve or deny AskUserQuestion-- Claude's clarifying questions are forwarded to Discord; your freeform reply is sent back (not just yes/no)- Permission timeout -- if no reply within 120 seconds, the request is auto-denied
- Set
dangerously_skip_permissions = trueto bypass all permission checks (use only in trusted environments)
| Command | Where | Description |
|---|---|---|
/claude <prompt> [project] |
Server | Start a new session in a thread |
| (just type) | DM | Start or continue a session |
| @mention bot | Session thread | Continue the conversation |
/interrupt [prompt] |
Session thread | Kill current task, optionally send new prompt |
!message |
Session thread | Interrupt current task and send message |
/compact |
Session thread | Summarize conversation to reduce context usage |
/context |
Session thread | Show current context window and token usage |
/end |
Session thread | Stop session and archive the thread; preserves worktree if branch has unpushed local work (owner/admin only) |
/sessions |
Anywhere | List active sessions with thread links, project names, age, and status |
/projects |
Anywhere | List git repositories discoverable as sibling directories of default_cwd |
| Command | Where | Description |
|---|---|---|
/participants |
Session thread | List all participants and their roles (ephemeral) |
/handoff <user> |
Session thread | Transfer session ownership to another participant (owner/admin only, ephemeral) |
/sessionkick <user> |
Session thread | Remove a participant (owner/admin only, ephemeral) |
/sessionban <user> |
Session thread | Remove from session and revoke access (admin only, ephemeral) |
| Command | Where | Description |
|---|---|---|
/optin |
Anywhere | Request access (ephemeral) |
/optout |
Anywhere | Remove your own access (ephemeral) |
/approve <user> |
Anywhere | Admin: approve a pending request (ephemeral) |
/revoke <user> |
Anywhere | Admin: revoke a user's access (ephemeral) |
/pending |
Anywhere | Admin: list pending requests (ephemeral) |
/audit [id] [count] [detail] |
Session thread | Admin: view tool usage audit log; detail=true shows full input JSON and result (ephemeral) |
/login |
Anywhere | Admin: OAuth PKCE login — open URL, authorize, paste code, done |
After the initial /claude command in a server, just type messages in the thread -- the bot picks them up automatically.
If Claude is busy, your message is queued and sent automatically when the current task finishes. Prefix with ! to interrupt -- kills the current task and sends your message immediately. If Claude is waiting for your reply to a question or permission prompt, your message is routed as the answer.
Users can be authorized in three ways:
- Config --
allowed_usersandadminsinconfig.toml(permanent, requires restart) - Roles --
allowed_rolesandadmin_rolesin config (Discord role-based) - Dynamic --
/optinrequest approved by an admin via/approve(stored in DB, instant)
cargo build # Dev build
cargo run # Run the bot
cargo test # Run unit tests
cargo clippy --all-targets # Lint
cargo build --release # Release build (LTO, stripped)The bot can be containerized using the pre-built static binary pattern.
cargo build --release --no-default-features --target x86_64-unknown-linux-musl
cp target/x86_64-unknown-linux-musl/release/claude-crew .docker build -t claude-crew .The image uses debian:bookworm-slim as the base and installs Claude Code as a standalone binary (no Node.js required).
cp config.example.toml config.prod.tomlAll cwd paths in the config must point inside the /projects mount so Claude can read/write project files. The host directory is bind-mounted read-write.
# config.prod.toml -- Docker paths
[database]
url = "sqlite:/data/data.db?mode=rwc"
[claude]
default_cwd = "/projects"
[claude.projects.myapp]
cwd = "/projects/myapp"# Set your API key
export ANTHROPIC_API_KEY="sk-ant-..."
# With compose
docker compose up -d
# Or standalone
docker run -d \
--name claude-crew \
--restart unless-stopped \
-e ANTHROPIC_API_KEY \
-v claude-data:/data \
-v claude-state:/home/appuser/.claude \
-v ./config.prod.toml:/app/config.toml:ro \
-v /path/to/your/projects:/projects \
claude-crew| Mount | Purpose |
|---|---|
/data |
SQLite database (named volume) |
/home/appuser/.claude |
Claude CLI session state and settings (named volume) |
/app/config.toml |
Configuration file (bind mount, read-only) |
/projects |
Project directories Claude works on (bind mount) |
- Rust with Tokio async runtime + tokio-util (CancellationToken)
- poise -- Discord bot framework (wraps serenity)
- sqlx -- SQLite for session persistence
- dashmap -- Lock-free concurrent session registry
- smallvec -- Inline stack storage for small collections
- tokio::process -- Claude Code subprocess management
- tracing -- Structured logging
- serde + toml -- Two-phase config (Raw TOML -> validated Arc-backed)
See PLAN.md for the full implementation guide including module structure, key types, and design decisions.
| Problem | Fix |
|---|---|
"Missing Access" on /claude |
The bot needs Create Public Threads permission. Check both the bot role AND channel-level permission overrides -- if the channel denies thread creation for @everyone, the bot needs an explicit allow override on that channel |
"The application did not respond" on /claude |
Ensure the bot has Send Messages permission. If the bot just restarted, wait a few seconds for Discord to register commands |
| Bot connects then disconnects with "Disallowed intents" | Enable Message Content Intent in Bot settings on the Developer Portal |
| Slash commands don't appear | Wait 1-2 minutes after first bot startup for Discord to register them globally |
| Bot doesn't respond to DMs | Make sure your user ID is in auth.allowed_users in config.toml |
| "failed to spawn claude" error | Ensure claude CLI is in PATH and authenticated. On NixOS, use an FHS wrapper script as binary |
| Bot responds but Claude output is empty | Check stderr logs -- Claude errors are now logged. Verify default_cwd is valid |
| Claude can't use tools (permission denied) | Add the tools to allowed_tools in config, or set dangerously_skip_permissions = true |
| Follow-up messages start new conversations | Expired sessions auto-resume with a fresh session. Stopped sessions (via /end) resume worktree-aware: preserved worktrees resume with --resume, pushed worktrees pull then start fresh, pushed+deleted branches block resume. Check logs for claude_session_id if issues persist |
| "Auth expired" / 401 errors | Run /login (admin only) to refresh OAuth credentials. The bot detects 401 errors and shows guidance |
| Sessions stuck after bot restart | Fixed: on startup the bot reconciles all "active" sessions to "idle", so the next message in the thread resumes normally |
| Ctrl+C doesn't work | Fixed in v0.2.0: Claude subprocesses now run in their own process group, so SIGINT only reaches the bot which handles graceful shutdown |
| "Invalid Form Body (name)" error | Thread name exceeded 100 chars -- this is now fixed with proper truncation |
Caution
Vibe-coding is addictive. Protect your mental health.
This tool can easily turn you into a x100 developer. That feeling is intoxicating -- and therein lies the danger. Extended AI-assisted coding sessions (8+ hours) are associated with measurable cognitive and psychological harm. Managing multiple concurrent threads amplifies the risk.
What the research shows:
-
Brain changes from extended screen time -- Excessive sessions reduce gray matter volume in the prefrontal cortex (executive function, attention, working memory) and alter white matter integrity. These effects compound with duration and frequency. (Neophytou et al., 2021; Small et al., 2020)
-
Flow state becomes addictive without recovery -- Flow is protective only when followed by adequate rest. Without it, flow accelerates burnout and develops into obsessive, compulsive engagement patterns. 39-83% of developers already exhibit burnout symptoms. (Aust & Beneke, 2022; Almeida et al., 2022)
-
Technostress is a validated clinical construct -- Five empirically identified stressors (overload, invasion, complexity, insecurity, uncertainty) decrease job satisfaction and cognitive performance. (Tarafdar et al., 2007; Fischer & Riedl, 2022)
What to do about it:
-
Nature exposure restores directed attention -- As little as 10-15 minutes outdoors measurably improves executive attention and working memory. A 90-minute nature walk reduces rumination and decreases activity in brain regions linked to depression. (Berman et al., 2008; Bratman et al., 2015)
-
Walking boosts creativity by 60% -- Even short walks (indoors or outdoors) significantly improve divergent thinking, with residual benefits persisting after sitting back down. (Oppezzo & Schwartz, 2014)
-
Take a full no-tech day off between marathon sessions. Digital detox is not optional -- it is maintenance. Your brain needs time in environments that provide what Kaplan's Attention Restoration Theory calls "soft fascination" -- nature, not screens. (Kaplan, 1995; Stevenson et al., 2018)
The rule of thumb: For every deep vibe-coding session, schedule equal recovery time away from all screens. Go outside. Touch grass. Your future self -- and your prefrontal cortex -- will thank you.
Potential future features:
- File attachment support -- Send files/images via Discord attachments for Claude to read
- Reaction-based approval UI -- Discord button components instead of text replies for permission prompts and user questions; collaborative sessions could require quorum approval
/healthendpoint -- HTTP health check for monitoring (lightweight Axum or Hyper)- GitLab merge request support -- Add
glabCLI support alongsideghfor auto-PR on GitLab repositories - PR review integration -- Post PR review comments from Discord; let participants approve/request changes via slash commands
- Comprehensive test suite for CI/CD -- End-to-end tests exercising both the Claude Code CLI integration (stream-json parsing, control_request/control_response protocol, permission flows) and the Discord layer (slash commands, thread lifecycle, ephemeral messages, reply routing)
- claude-code-discord -- TypeScript/Deno, uses Claude Agent SDK directly
- claude-code-discord-bridge -- TypeScript, thread-per-session with git worktrees
- discord-agent-bridge -- tmux polling approach
- Claude-Code-Remote -- Email/Discord/Telegram control
Inspired by the discussion at anthropics/claude-code#15922.
MIT