I am addicted to building with Codex. The main issue with the app is that I cannot use it while away from my desktop. I built this side-project so that I can finally have Codex keep working while I'm buying groceries or watching a movie on the couch.
codex-mobile is a local bridge that mirrors live Codex work and exact Codex approval requests into Discord.
It runs on the same machine as Codex, watches Codex Desktop and Codex CLI at the same time, posts selected activity to Discord, and routes supported approval decisions back into Codex.
Quick notes:
- Windows-first public beta. macOS is best-effort and not yet validated with Codex Desktop (probably won't work)
- the bridge works only while your local machine and bridge process are running
- Discord is the only adapter for now
- Discord is a notification and control surface, not the source of truth
- Discord write-back is limited to exact approval/plan actions and explicit
/codex sendcommands from the configured controller user - Codex Desktop sub-agent approvals can be read-only until the sub-agent chat is opened in Desktop; see How It Looks
The bot mirrors live activity from Codex. Verbosity of mirrored messages can be tuned in bridge.config.json.
You can approve Codex command requests directly from Discord.
Use the /codex send command to talk back to Codex via Discord. This supports starting a new turn, queueing, and steering in an existing thread.
- Windows, or macOS as best-effort
- Node.js 24+
- Discord account and Discord app. The setup guide uses the Windows Discord app because copying IDs and tokens is easier there, but after setup the bot works from any device where you use Discord.
- Codex Desktop (recommended) or Codex CLI already working on this machine
- A local clone of this repo on the same machine where Codex runs.
For the most guided setup, open this project in Codex and say:
Help me set up this project.
Codex should walk you through one setup step at a time, wait for each value or confirmation, run diagnostics, and then tell you how to start the bridge yourself.
To use the terminal wizard instead:
npm install
npm run initThe wizard will create .env, create bridge.config.json, verify the Discord bot permissions, and run diagnostics.
Alternatively, you can manually follow the instructions below with screenshots.
The terminal wizard and Codex-assisted setup follow this same flow.
-
Create or choose a Discord server.
In Discord, use the
+button in the server sidebar to create a server if you do not already have one for the bridge. -
Enable Developer Mode and copy the server ID.
In Discord, turn on Developer Mode from
User Settings -> Developer -> Developer Mode, orUser Settings -> Advanced -> Developer Mode. Then right-click your server and copy the server ID. This value becomesDISCORD_GUILD_IDin.env. -
Create or open the Discord application.
Open the Discord Developer Portal. If Discord asks what you are building, choose
Build a Bot. Create an application named something likeCodex Mobile Bridge, or open your existing bridge application. -
Copy the application ID.
On
General Information, copy theApplication ID. This value becomesDISCORD_APPLICATION_IDin.env. -
Create or confirm the bot.
Open the
Botpage in the left sidebar. ClickAdd Botif Discord asks; if the bot already exists, continue. -
Configure server install permissions.
Open the
Installationpage. Make sure server installs are enabled.Required server install scopes:
applications.commandsbot
Required bot permissions:
Create Public ThreadsManage ChannelsManage MessagesManage ThreadsPin MessagesRead Message HistorySend MessagesSend Messages in ThreadsView Channels
Keep
Requires OAuth2 Code Grantoff. -
Copy the bot token.
On the
Botpage, useReset TokenorCopyto get the bot token. This value becomesDISCORD_BOT_TOKENin.env. -
Invite the bot to your server.
The wizard generates the invite URL from your application ID. If you are following the README by hand, use this format and replace
<DISCORD_APPLICATION_ID>with your application ID:https://discord.com/oauth2/authorize?client_id=<DISCORD_APPLICATION_ID>&scope=bot%20applications.commands&permissions=2252126231276560&integration_type=0Open the URL, choose the server you created or selected earlier, approve the requested permissions, and authorize the bot. The server ID is not part of the URL; Discord asks you to choose the server on the invite page.
-
Verify bot permissions.
The wizard checks the bot's role and creates a temporary category, channel, and thread to confirm the bot can run the bridge. It removes those temporary resources afterward. If you are following the README by hand, you will verify this later with
npm run doctor. -
Copy the controller user ID.
Right-click your own Discord profile and copy your user ID. This one user can approve actions and use
/codex sendin mapped channels. This value becomesDISCORD_CONTROLLER_USER_IDin.env. -
Choose a behavior preset.
Use
recommendedunless you want less or more Discord output:basic: mirrors conversation, grouped command/file activity, and approval responses, without Discord message write-backrecommended: everything inbasic, plus/codex send, queue/retract, and steering write-backfull: everything inrecommended, plus ungrouped command/file activity and detail buttons
See bridge.config.example.jsonc for an explained example of the available customization settings. After choosing your preset, you will save it in the next step.
-
Save
.envandbridge.config.json.If you are using the wizard, it writes these files for you. If you are following the README by hand, create
.envfrom.env.example, then fill in:DISCORD_BOT_TOKEN=<bot token> DISCORD_APPLICATION_ID=<application ID> DISCORD_GUILD_ID=<server ID> DISCORD_CONTROLLER_USER_ID=<your Discord user ID>
Then create
bridge.config.jsonwith the recommended preset:{ "preset": "recommended" }Use bridge.config.example.jsonc only if you want to see all available options.
-
Run diagnostics.
The wizard runs diagnostics automatically. You can rerun them any time:
npm run doctor
When setup passes, start the bridge yourself:
npm startIf you use Codex Desktop, the recommended path is to add this project to the app, open a chat for this project, and run npm start there while you work in other Codex projects.
It is recommended to clean the bot's state after stopping the bridge, to avoid leaving sensitive data on discord. To clean, use /codex cleanall from discord, or run:
npm run cleanThis is not Discord talking directly to your Codex or OpenAI account.
The actual flow is:
- Codex Desktop or Codex CLI is already authenticated on your machine.
codex-mobilestarts locally on that same machine.- The bridge connects to Codex locally through supported local surfaces.
- The bridge mirrors selected activity into Discord.
- When a supported approval appears, Discord buttons send that exact decision back through the local bridge.
The Discord layout mirrors Codex work:
- Discord server = one bridge instance / Codex account context
- category = project or environment
- text channel = top-level Codex thread
- Discord thread = Codex sub-agent or sub-thread
The bridge can mirror final answers, thinking/commentary, user messages, command activity, file-edit activity, and approval requests. Visibility is controlled by bridge.config.json.
Approval and plan-response buttons work only for exact Codex requests the bridge can route back into Codex:
- Codex Desktop top-level approvals are actionable when Desktop exposes the native request.
- Codex Desktop sub-agent approvals may appear read-only until the sub-agent chat is opened in Desktop. In that state, the bridge has only a session-log placeholder and no write-back-capable request.
- Windows Codex CLI approvals are actionable when the CLI session is connected to the bridge listener. In practice, start the bridge first, then launch Codex CLI with the standard
codexcommand. The Windows launcher will transparently run that CLI session with--remoteso the bridge can route approvals and/codex sendcontrols back into the live terminal. If the bridge only sees a local session log, CLI controls remain read-only.
The configured controller user can also use:
/codex sendto send, queue, or steer a message in a mapped Discord location/codex retractto retract the latest pending queued Discord write-back message
Ambient Discord chat messages are ignored.
Discord is treated as semi-trusted. The bridge keeps Codex local and fails closed when state is ambiguous.
Current rules:
- approvals are bound to exact surfaced requests only
- no arbitrary "run command from Discord" path exists
- Discord write-back works only through explicit slash commands in mapped bridge locations
- steering targets only a known active Codex turn
- allowlists are enforced by the local bridge
- secrets are redacted before text is posted to Discord
- detailed command views are opt-in and still redacted
- stale or resolved approval buttons are disabled
- audit entries are kept locally in SQLite
See SECURITY.md for security notes and reporting guidance.
Connection values and local IDs stay in .env. Behavior lives in bridge.config.json, generated by the init wizard. The commented reference is bridge.config.example.jsonc, and the preset defaults live in config/presets.
Important files:
.env: bot token, application ID, server ID, controller user ID, Codex command, store path, log level, optional Desktop overridesbridge.config.json: behavior preset plus any local overridesconfig/presets/*.json: source-of-truth defaults forbasic,recommended, andfull
Behavior presets:
basic: mirrors conversation, thinking/commentary, grouped command/file activity, and approval responsesrecommended: everything inbasic, plus Discord message write-back for/codex send, queue/retract, and steeringfull: everything inrecommended, but command/file activity is ungrouped with detail buttons
The preset is the base. Any sections you add below preset in bridge.config.json override that preset for your local bridge.
Useful knobs include:
approvals.allowFromDiscord: command/MCP/tool approvals and proposed-plan accept/feedbackDISCORD_CONTROLLER_USER_IDin.env: the single Discord controller user allowed to approve actions and use write-back controlsmessageWriteBacks.allowFromDiscord:/codex send, queue/retract, and steeringvisibility.userMessagesvisibility.thinkingMessagesvisibility.finalMessagesvisibility.commandsvisibility.fileEditsui.commandDisplayModeui.enableCommandDetails
Common commands:
| Command | Purpose |
|---|---|
npm run init |
guided setup wizard |
npm run doctor |
diagnostics |
npm start |
start the bridge |
npm run dev |
development start |
npm run inspect |
general bridge inspection |
npm run inspect:discord |
inspect Discord mappings |
npm run inspect:codex |
inspect Codex discovery |
npm run inspect:desktop |
inspect recent Desktop approval/question events |
npm run inspect:store |
inspect local bridge state |
npm run inspect:thread -- <thread-id> 20 |
inspect one Codex thread |
npm run clean |
delete bridge-managed Discord structure and local bridge state |
npm run build |
compile |
npm test |
run tests |
npm run coverage |
test coverage summary |
npm run coverage:gate |
current coverage gate |
To launch Codex CLI through the project helper:
npm run cli -- -C /path/to/workspaceThis is optional. On Windows, setup also reconciles the standard codex launcher. When the bridge is already running, ordinary codex terminals are transparently launched with --remote and can receive supported approvals and /codex send controls from Discord. Start the bridge before starting the CLI session you want to control.
Live e2e playbooks live in e2e-live. Start with:
npm run e2e-live -- groups- make sure the bot was installed into the intended server
- make sure the bot token and application ID belong to the same Discord application
- rerun
npm run doctor
That can still be okay while it is offline. The real check is whether npm run doctor and npm start can connect successfully.
- check
npm run inspect:desktop - check
npm run inspect:thread -- <thread-id> - confirm the bridge is running on the same machine as Codex Desktop
- confirm the approval surface is one the bridge currently supports
For Codex Desktop, a sub-agent approval may stay read-only until the sub-agent chat is opened in Desktop. Until Desktop exposes the native approval request, the bridge may only see a session-log placeholder, which cannot be approved from Discord.
For Codex CLI, read-only approval cards mean the bridge saw a session-log placeholder but did not receive a routable native approval request for that turn. Use the standard codex command on Windows while the bridge is running.
- run
npm run inspect:codex - verify Codex threads are being returned
- verify your startup/backfill behavior preset is not intentionally quiet
If your PowerShell prompt shows a provider-style path such as Microsoft.PowerShell.Core\FileSystem::\\?\C:\..., npm may print a one-line CMD.EXE warning before the bridge starts. The repo scripts normalize back to the actual project root, so this warning is usually harmless as long as the bridge continues starting afterward.
The recommended default is the recommended preset. Use basic to disable Discord-originated messages, or full when you want ungrouped command/file activity.
Use this release if you want:
- mobile visibility into Codex work
- Discord-based approvals for supported approval surfaces
- a local-first bridge with explicit safety controls
Do not use this release if you need:
- multi-user enterprise hardening
- fully validated macOS Desktop integration
- guaranteed support for every internal Codex approval surface
- chat-originated arbitrary control from Discord
Feedback and bug reports are welcome through GitHub Issues. External pull requests are not being accepted during the public beta; unsolicited PRs may be closed without review.
For security issues, do not open a public issue. Follow SECURITY.md.
Run the full test suite:
npm testCurrent layout:
src/bridge: orchestration and mirror/approval logicsrc/codex: Codex app-server, Desktop IPC, and local session integrationsrc/providers: provider-facing contractsrc/providers/discord: Discord provider entry pointsrc/discord: current Discord implementation details
Project hygiene:
















