Real-time bridge between OpenCode and Slack. Mention @opencode in any channel to start an AI coding session — streaming responses, permission buttons, agent questions, file sharing, and multi-project support. All from Slack.
No public URL needed. Connects outbound via WebSocket (Slack) and HTTP/SSE (OpenCode).
# 1. Start OpenCode server
opencode serve
# 2. Install & configure the bridge
git clone <repo-url> && cd opencode-messenger-bridge
bun install
cp .env.example .env # fill in SLACK_BOT_TOKEN, SLACK_APP_TOKEN, SLACK_SIGNING_SECRET
# 3. Run
task run # debug mode (logs to terminal + file)
task start # production mode
task dev # hot-reloadPrerequisites: Bun v1.1+, Task, a Slack app with Socket Mode (see slack-app-setup.md).
@opencode fix the login bug # default agent + default project
@opencode coder: fix the login bug # specific agent
@opencode [backend] fix the login bug # specific project
@opencode [backend] coder: fix it # both
/opencode <message> # slash command (not in threads)
Reply in a thread to continue — no need to re-mention.
- Streaming responses — real-time text streaming with throttled Slack updates
- Permission buttons — Approve / Always Allow / Deny (auto-deny after timeout)
- Question forwarding — agent questions rendered as Slack buttons/checkboxes/modals, answers sent back via REST API
- Thread context injection — mention
@opencodein any thread and previous messages become context - File sharing — auto-shares created files (configurable glob patterns per agent)
- Tool call display — shows which tools the agent is using
- Project targeting —
[project]syntax, channel defaults, global default - AI routing — automatic project + agent detection via LLM (enable with
/init router) - Resolution cascade — message explicit → router → channel default → global default
- Auto-recovery — survives bridge restarts (reattaches from thread history)
- Attach/Resume —
/attach <session-id>,/resume - Session timeout — configurable auto-close after inactivity
- Worktree isolation — per-project git worktrees (one per thread, prevents conflicts)
- First-boot setup —
/setupclaims admin, opens config modal - Access control — open/closed mode, per-user agent allowlists
- Channel config —
/init project,/init agent,/init router - File sharing rules —
/configcommands for glob patterns per agent - Feedback collection — thumbs up/down buttons with optional reason capture (SQLite)
| Command | Description |
|---|---|
/help |
Show all commands |
/hello |
Health check (server status, uptime) |
/status |
Current session info |
/agents |
List available agents |
/projects |
List enabled projects |
/close |
Archive session |
/delete |
Permanently delete session |
/abort |
Stop running operation |
/attach <id> |
Attach existing session to thread |
/resume |
Resume last session in this thread |
/init [project|agent|router|clear] |
Channel configuration (admin) |
/config [...] |
File sharing, users, admin config (admin) |
/setup |
Interactive config modal (admin) |
/sessions |
Active bridge sessions (admin) |
/server-sessions |
Sessions on OpenCode server (admin) |
| Variable | Required | Default | Description |
|---|---|---|---|
SLACK_BOT_TOKEN |
Yes | — | Bot token (xoxb-...) |
SLACK_APP_TOKEN |
Yes | — | App token for Socket Mode (xapp-...) |
SLACK_SIGNING_SECRET |
Yes | — | Signing secret |
OPENCODE_SERVER_URL |
No | http://localhost:4096 |
OpenCode server URL |
DEFAULT_AGENT |
No | server default | Default agent |
SESSION_TIMEOUT_MINUTES |
No | 30 |
Auto-close after inactivity |
PERMISSION_TIMEOUT_SECONDS |
No | 120 |
Auto-deny timeout |
WORKTREE_ISOLATION |
No | false |
Enable per-project git worktrees |
FEEDBACK_MODE |
No | off |
on_done / on_close / off |
ALLOWED_CHANNELS |
No | all | Restrict to specific channels |
BRIDGE_INSECURE |
No | false |
Skip admin requirement (dev only) |
See .env.example for the full list.
Auto-created on first run. Managed via /setup modal and /config commands.
Slack (Socket Mode WS) ←→ Bridge ←→ OpenCode server (HTTP + SSE)
The bridge is provider-agnostic — only src/providers/slack/ depends on @slack/bolt. The core uses a MessagingProvider interface.
src/
index.ts Entry point + bootstrap
bridge/ Core: message routing, streaming, permissions, questions, commands
providers/slack/ Slack-specific: Bolt, Block Kit, modals, file downloads
opencode/ SDK client wrapper, project discovery
router/ AI project routing (throwaway session strategy)
worktree/ Git worktree provisioning + teardown
feedback/ Feedback collection (SQLite)
config/ Config store, access control, serialization
types/ All shared types
utils/ Parser, formatter, logger, config loader
task run # Debug mode
task start # Production mode
task dev # Hot-reload
task test # Unit tests
task typecheck # Type checking
task check # Tests + typecheck
task oc:sessions # List OpenCode sessions
task oc:find -- <q> # Find sessions by name
task oc:export -- <id> # Export session as JSON
task oc:db # OpenCode SQLite shellBun runtime, TypeScript (strict ESM), @slack/bolt (Socket Mode), @opencode-ai/sdk, bun:sqlite, Taskfile.
MIT
{ "admin": { "users": ["U0ADMIN"], "contact_name": "admin" }, "default_user_policy": { "agents": "*" }, "file_sharing": { "default": { "created_files": ["*.md"], "include_modified": false, "max_file_size_bytes": 1048576 } }, "projects": { "enabled": { "backend": { "id": "...", "directory": "/code/backend", "worktree_enabled": true }, "frontend": { "id": "...", "directory": "/code/frontend" } }, "default": "backend" }, "channels": { "C01ABC123": { "project": "frontend", "agent": "coder", "mode": "fixed" } } }