Bring workforce of Claude Codes to your Slack workspace. Every thread becomes an isolated coding session — with its own working directory, git worktree, and full access to your local filesystem. Claude runs on your machine, streams responses in real-time, and your whole team can use it simultaneously without conflicts.
bunx compass-agentThat's it. The bot connects via Socket Mode — no servers, no ngrok, no cloud deployment. See Setup for first-time configuration.
You (Slack thread) → Bot (Socket Mode) → Claude CLI (local) → Your filesystem
The bot runs locally using Slack's Socket Mode. When you message it, it spawns a claude CLI process, streams output back to Slack in real-time, and maintains session continuity across messages. Each thread is an isolated session with its own working directory, session ID, and git worktree.
Every thread is an independent Claude session. Subsequent messages in the same thread resume the conversation with full context.
- First message creates a new Claude session
system.initstores the session ID in SQLite- Follow-up messages use
--resume <session_id>to continue
Set the working directory for Claude to read/write files.
| Command | Description |
|---|---|
$cwd |
Opens an interactive picker with recent directories |
$cwd /path/to/project |
Sets the directory directly |
The picker remembers previously used directories. CWD is stored per-thread in SQLite.
Store team conventions that get injected into every Claude session across your workspace.
| Command | Description |
|---|---|
$teach <instruction> |
Adds a new convention |
$teach list |
Lists all active teachings with IDs |
$teach remove <id> |
Removes a teaching by ID |
$teach Use TypeScript for all new files
$teach Always write tests before implementation
$teach Use pnpm instead of npm
These appear in Claude's system prompt as:
Team conventions:
- Use TypeScript for all new files
- Always write tests before implementation
Responses stream token-by-token using Slack's native chatStream API, with automatic fallback to throttled chat.update calls if streaming isn't available.
Tool calls are visualized as an agentic timeline — each invocation (file reads, edits, shell commands) appears as a step that progresses from in-progress to complete.
When the CWD is inside a git repo, the bot automatically creates a worktree for each thread. Parallel threads can make code changes without conflicting with each other or your main working tree.
- First message detects if CWD is in a git repo
- Creates a worktree at
<repo>/trees/slack-<thread_ts>on branchslack/<thread_ts> - Copies
.envfiles from the main repo - Claude runs in the worktree instead of the raw CWD
- Subsequent messages reuse the existing worktree
An hourly cleanup job removes worktrees idle for 24+ hours, skipping any with active processes or uncommitted changes. If the CWD is not a git repo, Claude runs directly in it.
- Stop button — Every response includes a red Stop button that sends
SIGTERMto Claude. Partial responses are preserved. - App Home dashboard — Live stats (active sessions, teachings, worktrees), recent sessions with status indicators, usage logs with cost tracking, and quick actions for managing teachings.
- Usage logging — Every invocation logs session, user, model, tokens, cost, duration, and turns to SQLite. Powers the dashboard's "Recent Activity" section.
- User whitelist — Set
ALLOWED_USERSin.envto restrict access by Slack user ID.
- Bun runtime
- Claude CLI installed and authenticated
- A Slack workspace where you can create apps
- Go to api.slack.com/apps and click "Create New App"
- Choose "From an app manifest" and paste the contents of
manifest.yml - Install the app to your workspace
- Under Settings > Basic Information, generate an App-Level Token with
connections:writescope — this is yourSLACK_APP_TOKEN(starts withxapp-) - Under OAuth & Permissions, copy the Bot User OAuth Token — this is your
SLACK_BOT_TOKEN(starts withxoxb-)
mkdir -p ~/.compass
cat > ~/.compass/.env << 'EOF'
SLACK_APP_TOKEN=xapp-1-...
SLACK_BOT_TOKEN=xoxb-...
ALLOWED_USERS=U096GJFBZ54
EOFbunx compass-agentYou can also point to a specific env file:
bunx compass-agent --env-file /path/to/.envOr pass tokens directly:
SLACK_APP_TOKEN=xapp-... SLACK_BOT_TOKEN=xoxb-... bunx compass-agentgit clone https://github.com/raja-jamwal/compass.git
cd compass
cp .env.example .env # edit with your tokens
bun install
bun start- Real environment variables (highest)
--env-file <path>~/.compass/.env- Local
.envin the current directory (lowest)
- Open the app in Slack (find it in the Apps section)
- Go to the Home tab — you should see the dashboard
- Start a new thread in the Messages tab
- Send
$cwd /path/to/your/project - Send a question — Claude should respond with streaming text
src/
app.ts Entry point — Bolt app, actions, modals, App Home, startup
db.ts SQLite schema and typed prepared statements (bun:sqlite)
types.ts Shared TypeScript interfaces
handlers/
assistant.ts Thread lifecycle — session management, commands, message routing
stream.ts Claude CLI streaming — NDJSON parsing, tool timeline, usage logging
ui/
blocks.ts Block Kit builders — dashboard, stop button, feedback, prompts
lib/
log.ts Structured logging helpers
worktree.ts Git worktree lifecycle (create, remove, detect, cleanup)
mcp/
server.ts MCP server — reminders, teachings, channel CWD tools
manifest.yml Slack app manifest (scopes, events, features)
sessions.db SQLite database (auto-created on first run)
Slack message (Socket Mode)
→ Auth check (subtype, bot, allowed user)
→ Command check ($cwd, $teach)
→ Concurrency check (one process per thread)
→ Session lookup (resume or create)
→ CWD gate
→ Worktree setup (detect git, create/reuse)
→ Post "Thinking..." with Stop button
→ Start chatStream (or fallback to chat.update)
→ Spawn claude CLI with team teachings
→ Parse NDJSON stream (init, text_delta, tool calls, result)
→ Stream to Slack in real-time
→ Finalize: log usage, clean up stop button
| Variable | Required | Description |
|---|---|---|
SLACK_APP_TOKEN |
Yes | App-level token (xapp-...) for Socket Mode |
SLACK_BOT_TOKEN |
Yes | Bot user OAuth token (xoxb-...) |
ALLOWED_USERS |
No | Comma-separated Slack user IDs to whitelist |
CLAUDE_PATH |
No | Path to the claude binary (defaults to claude in PATH) |
CLAUDE_ADDITIONAL_ARGS |
No | Extra CLI args appended to every claude invocation |
ENV_* |
No | Variables prefixed with ENV_ are injected into Claude's environment (e.g. ENV_ANTHROPIC_API_KEY=sk-... sets ANTHROPIC_API_KEY) |


