This project runs a local bridge between Slack and codex app-server.
It supports:
- mentioning the Slack bot to bind a Slack thread to a local Codex session
- invoking
/codex ...as a slash command entrypoint - chatting with Codex from the Slack thread after the bind
- running direct local
bashcommands from Slack - task progress streaming into Slack while Codex is responding
- remaining token/context budget summaries in
@codex status - task-finished notifications via the final Slack reply
- approval prompts in Slack with approve, approve-for-session, deny, cancel, and interrupt actions where the app-server protocol supports them
The bridge talks to a shared local codex app-server over websocket.
That matters because it lets:
- your local terminal TUI connect with
codex --remote ws://127.0.0.1:8765 - Slack connect to the exact same backend session host
- approval prompts and task completion notifications flow to Slack for sessions attached to that shared backend
If you already have an older standalone Codex CLI session, Slack cannot directly hijack that process. Instead, either:
- connect your terminal through the shared app-server, or
- use
@codex recentand@codex resume <thread-id>to load a saved session into the shared app-server
Create a Slack app with:
- Socket Mode enabled
- Interactivity enabled
- a
/codexslash command configured - Bot token scopes:
app_mentions:readchannels:historychat:writegroups:historyif you want private channelsim:historyandmpim:historyif you want DMs and multi-party DMs
Subscribe to these events:
app_mentionmessage.channelsmessage.groupsif using private channelsmessage.imandmessage.mpimif using DMs
You need:
SLACK_APP_TOKENfor Socket ModeSLACK_BOT_TOKENfor bot API calls
For the slash command:
- go to
Features > Slash Commands - create
/codex - with Socket Mode, you do not need a public Request URL
Set environment variables:
export SLACK_APP_TOKEN='xapp-...'
export SLACK_BOT_TOKEN='xoxb-...'
export CODEX_APP_SERVER_PORT=8765
export SLACK_SHELL_TMUX_TARGET='%8'
export COMMAND_OUTPUT_PREVIEW_LINES=1
export COMMAND_OUTPUT_PREVIEW_MAX_CHARS=120
export COMMAND_OUTPUT_EXPANDED_LINES=160Start the bridge:
npm startIf you want the local terminal UI to attach to the same shared backend, start Codex like this in another terminal:
codex --remote ws://127.0.0.1:8765By default the bridge starts its own local codex app-server. If you already run one elsewhere, set:
export CODEX_START_APP_SERVER=false
export CODEX_APP_SERVER_URL='ws://127.0.0.1:8765'Mention the bot in a Slack thread:
@codex sessions@codex attach latest@codex recent@codex resume <thread-id>@codex new@codex new fix the failing test@codex new --cwd /path/to/repo@codex new --cwd /path/to/repo fix the failing test@codex plan@codex plan draft the migration steps@codex chat@codex chat continue with the implementation@codex bash pwd@codex bash --cwd /path/to/repo npm test@codex status@codex interrupt@codex detach
Or use slash commands:
/codexshows the available commands and what they do/codex help/codex new fix the failing test/codex new --cwd /path/to/repo/codex plan draft the migration steps/codex chat continue with the implementation/codex bash pwd/codex bash --cwd /path/to/repo npm test/codex attach latest/codex recent/codex sessions/codex status/codex interrupt
/codex and /codex help reply ephemerally with the command list. Other slash commands open or continue a Slack thread for the Codex session.
Once a Slack thread is bound, ordinary replies in that Slack thread are sent to Codex without repeating the mention.
Use @codex plan or /codex plan to switch the bound session into plan mode for future Slack replies. Use @codex chat or /codex chat to switch back to the default chat mode.
- Permission prompts for additional filesystem or network access can be granted from Slack.
- Direct
bashcommands run on the same machine as the bridge. If the bridge is running inside tmux, the command is executed in a temporary tmux window so terminal-oriented programs still have a tty; otherwise it falls back tobash -lc. - Set
SLACK_SHELL_TMUX_TARGETto a tmux pane or window target such as%8orsession:1.0if you want Slackbashcommands to run in an existing shell pane instead of a temporary tmux window. SLACK_SHELL_TMUX_TARGETmust point to an interactive shell pane, and it must not be the same pane that is running the Slack bridge.- When
SLACK_SHELL_TMUX_TARGETis set and you omit--cwd, the command runs in that pane's current shell context so working directory and exported shell state can carry across commands. - Existing-pane mode injects a small wrapper command into that pane so the bridge can detect command boundaries and stream output back to Slack.
- Command output previews can be tuned with
COMMAND_OUTPUT_PREVIEW_LINES,COMMAND_OUTPUT_PREVIEW_MAX_CHARS, andCOMMAND_OUTPUT_EXPANDED_LINES. The default collapsed preview is intentionally tiny and only shows the first part of the output; expanding shows the larger head-and-tail view. - Consecutive command executions with no other Codex output in between are folded into one Slack message. The collapsed view shows the first command in the sequence, and expanding reveals the later commands.
- For
item/permissions/requestApproval, the current app-server protocol exposes grant payloads but not a dedicated deny payload. This bridge offersInterrupt Turnin Slack as the refusal path. - Tool-driven structured user input prompts can now be answered from Slack buttons, and custom "Other" answers can be supplied by replying in the Slack thread.