Skip to content

friuns2/codex-web-ui

Repository files navigation

Important

This project has moved to friuns2/codexui. Please use the new repository for the latest updates: https://github.com/friuns2/codexui.

🌐 Codex App Web UI Enabler

πŸš€ Run OpenAI Codex Desktop in Your Browser β€” From Any Device πŸš€

Shell Script Electron Platform License Status GitHub stars GitHub forks



Codex Desktop's full UI β€” chat, skills, file editing, code execution β€” accessible from any browser on any device. No Electron window required.

One script. Full Web UI. Anywhere. 🌍


   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—  β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—    β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—    β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ•—
  β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•   β–ˆβ–ˆβ•‘    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘
  β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—   β•šβ–ˆβ–ˆβ–ˆβ•”β•    β–ˆβ–ˆβ•‘ β–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘
  β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•   β–ˆβ–ˆβ•”β–ˆβ–ˆβ•—    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘
  β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β• β•šβ–ˆβ–ˆβ•—  β•šβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•   β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘
   β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•β•šβ•β•  β•šβ•β•   β•šβ•β•β•β•šβ•β•β• β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•    β•šβ•β•β•β•β•β• β•šβ•β•
                    E N A B L E R

🀯 What Is This?

OpenAI's Codex Desktop is a powerful AI coding agent β€” but it's locked inside an Electron window on a single machine. What if you could access it from any browser, on any device, anywhere on your network?

We reverse-engineered the minified Electron bundle and built scripts that patch the app at runtime to expose the full Codex UI over HTTP + WebSocket. The same scripts also unlock a hidden SSH remote execution engine that was already compiled into the binary but never wired up.

One command. Full Web UI. Plus SSH remote control. No recompilation.


πŸ“± See It In Action β€” Codex in Your Browser, From Any Device

Yes, that's a phone. Yes, that's Codex. Yes, it's running on a Mac across the network.


πŸ’¬ Live AI Chat Session
Full Codex conversation running on a Mac, controlled from an Android phone over the network. GPT-5.3-Codex responding in real-time. The address bar says it all: 100.107.32.83:5999 β€” that's a remote Mac.

🧩 Skills Manager β€” From Your Pocket
Browsing and managing Codex skills (Playwright, Oracle Cloud CLI, Three.js, YouTube Search...) from a mobile browser. Full desktop functionality, zero compromises.

🀯 This is not a mockup. This is a real Codex Desktop instance running on macOS, patched with our Web UI Enabler scripts, accessed from a mobile phone browser over Tailscale. Every feature works β€” chat, skills, file editing, code execution β€” all from your pocket.


⚑ Quick Start

# Run directly from npm (no clone needed)
npx -y codex-web-ui --port 5999

Open http://127.0.0.1:5999/ and you're flying. ✈️


🌍 What Can You Actually Do With This?

With the Web UI enabled, Codex breaks free from the Electron window β€” and with SSH mode unlocked, it reaches any machine you own:

🎯 Use Case πŸ’‘ Description
πŸ“± Code From Your Phone Open Codex in any mobile browser β€” full chat, skills, file editing, code execution
πŸ’» Use Any Browser Chrome, Firefox, Safari, Arc β€” no Electron install needed on the client
🌐 Access Over the Network Tailscale, LAN, VPN β€” access your Codex instance from anywhere securely
πŸ–₯️ Control Your Mac Remotely SSH into your MacBook from anywhere and let Codex operate it as if you're sitting in front of it
🐧 Orchestrate Linux Servers Point Codex at your Ubuntu/Debian/Arch boxes and run AI-powered coding sessions remotely
πŸͺŸ Manage Windows via WSL Connect through WSL2 SSH and bring Codex intelligence to your Windows dev environment
🏠 Command Your Homelab Proxmox, TrueNAS, Raspberry Pi clusters β€” Codex becomes your AI sysadmin
☁️ Cloud Fleet Management AWS EC2, Oracle Cloud, DigitalOcean droplets β€” manage entire fleets from one Codex window
πŸ”§ Web Service Orchestration Nginx configs, Docker containers, systemd services β€” edit and deploy across machines
πŸ§ͺ Remote CI/CD Pipelines Trigger builds, inspect logs, fix failing tests on remote CI runners in real-time
πŸ“‘ IoT & Edge Devices SSH into Raspberry Pis, Jetson Nanos, or any edge device and code directly on them
πŸ—οΈ Multi-Machine Refactoring Coordinate code changes across microservices running on different hosts simultaneously

TL;DR: Codex in your browser + SSH to any machine = your entire infrastructure as one AI-powered IDE. 🧠


πŸ“ Project Structure

codex-unpacked-toolkit/
β”œβ”€β”€ 🌐 launch_codex_webui_unpacked.sh     # WebUI mode launcher (browser access)
β”œβ”€β”€ πŸ”§ launch_codex_unpacked.sh          # SSH unlock & debug launcher
β”œβ”€β”€ πŸ”Œ webui-bridge.js                    # Browser-side WebSocket ↔ IPC bridge
β”œβ”€β”€ πŸ“– PROJECT_STATE.md                    # Living project state & patching reference
β”œβ”€β”€ πŸ“‚ images/                            # Screenshots & proof it works
β”‚   β”œβ”€β”€ mobile-chat-session.jpeg          # Codex chat from mobile phone
β”‚   └── mobile-skills-browser.jpeg        # Skills manager from mobile phone
└── πŸ“‚ skills/
    └── launch-codex-unpacked/
        └── SKILL.md                      # Codex skill definition

🌐 launch_codex_webui_unpacked.sh β€” Browser-Based Codex

The main event. Run Codex in your browser. No Electron window needed. Access from any device on your network.

What It Does

  1. πŸ“¦ Extracts app.asar β€” Same unpacking as above
  2. πŸ’‰ Injects WebUI runtime patch β€” Embeds a full HTTP server + WebSocket bridge directly into the Electron main process (~800 lines of runtime injection)
  3. 🩹 Patches renderer bundle β€” Fixes a roots guard compatibility issue in the React renderer that crashes in WebUI mode
  4. πŸ”Œ Copies webui-bridge.js β€” Installs the browser-side bridge into the webview directory
  5. πŸš€ Launches headless Electron β€” Starts with --webui flag, hides all native windows, serves UI over HTTP
  6. πŸ” Optional token auth β€” Protect your instance with --token for secure remote access
  7. 🌍 Origin allowlist β€” Restrict which domains can connect via --origins
  8. πŸ–₯️ Auto-opens browser β€” Polls the server and opens your default browser when ready

The Injected Runtime Includes

  • 🌐 Full HTTP static file server (serves Codex webview assets)
  • πŸ”„ RFC 6455-compliant WebSocket server (zero dependencies, hand-rolled frame parser)
  • πŸ”’ Timing-safe token authentication (Bearer, header, query param, and cookie)
  • πŸ›‘οΈ Security headers (X-Content-Type-Options, X-Frame-Options, CORP, Referrer-Policy)
  • πŸ“‘ IPC-to-WebSocket bridge (intercepts webContents.send and mirrors to all connected clients)
  • 🚦 Rate limiting (5000 messages/minute for local, configurable)
  • πŸ‘€ Single-client policy (new tab takes over, old tab gets disconnected)
  • πŸ’‰ SPA fallback with automatic webui-bridge.js injection into HTML

Options

--app <path>           Custom Codex.app path
--port <n>             WebUI port (default: 5999)
--token <value>        Auth token for secure access πŸ”
--origins <csv>        Allowed origins (comma-separated)
--bridge <path>        Custom webui-bridge.js path
--user-data-dir <path> Chromium user data dir override
--no-open              Don't auto-open browser
--keep-temp            Keep extracted app dir

Examples

# Run from npm package
npx -y codex-web-ui --port 5999

# Basic local access
./launch_codex_webui_unpacked.sh

# Secure remote access with auth
./launch_codex_webui_unpacked.sh --port 8080 --token mysecrettoken

# Access from specific origins only
./launch_codex_webui_unpacked.sh --origins "https://mysite.com,http://localhost:3000"

πŸ”§ launch_codex_unpacked.sh β€” The SSH Unlocker

Bonus superpower. This script extracts, patches, and launches Codex with the hidden SSH remote execution feature fully activated.

What It Does

  1. πŸ“¦ Extracts app.asar β€” Unpacks the Codex Electron bundle into a temp directory using @electron/asar
  2. πŸ”‘ Injects SSH host into global state β€” Writes your SSH host into .codex-global-state.json so the app recognizes it as a configured remote
  3. 🧬 Patches the main bundle β€” Performs a surgical startup-sequence patch on minified main-*.js to auto-select the SSH host on startup (dynamically discovers the target sequence and rewires it to check electron-ssh-hosts first)
  4. πŸ” Enables Node Inspector β€” Launches with --inspect for live debugging (port 9229 by default)
  5. 🌐 Enables Chromium Remote Debug β€” Opens --remote-debugging-port (9222) for DevTools Protocol access
  6. βœ… SSH preflight check β€” Validates connectivity to your host with BatchMode=yes and ConnectTimeout=6 before launching
  7. 🧹 Auto-cleanup β€” Temp directory is removed on exit (unless --keep-temp)

Options

--app <path>                 Custom Codex.app path (default: /Applications/Codex.app)
--user-data-dir <path>       Chromium user data dir override
--inspect-port <n>           Node inspector port (default: 9229)
--remote-debug-port <n>      Chromium remote debug port (default: 9222)
--ssh-host <user@host>       The SSH host to unlock and auto-connect πŸ”‘
--no-inspect                 Disable Node inspector
--no-remote-debug            Disable Chromium remote debugging
--keep-temp                  Keep extracted app dir for inspection

Example

# Unlock SSH to your homelab server with custom ports
./launch_codex_unpacked.sh \
  --ssh-host ubuntu@192.168.1.100 \
  --inspect-port 9230 \
  --remote-debug-port 9223

πŸ”Œ webui-bridge.js β€” The Browser-Side Bridge

Makes the browser think it's Electron. Replaces window.electronBridge with a WebSocket-backed implementation.

What It Does

  1. πŸ” Detects environment β€” Only activates when the native Electron preload bridge is absent
  2. πŸ”„ Establishes WebSocket connection β€” Connects to /ws with automatic reconnection (exponential backoff, 500ms β†’ 5s)
  3. πŸ“¨ Implements full electronBridge API β€” sendMessageFromView, sendWorkerMessageFromView, subscribeToWorkerMessages, and more
  4. πŸ“¬ Message queue β€” Buffers outbound messages while disconnected, flushes on reconnect
  5. πŸ“‘ Event forwarding β€” Translates WebSocket packets into browser MessageEvents that the React app expects
  6. πŸ”„ Worker subscription system β€” Manages per-worker callback subscriptions with proper cleanup
  7. 🏷️ Session management β€” Emits client-status-changed on connect, handles open-new-instance redirects
  8. πŸ›‘οΈ Single-socket guard β€” Token-based deduplication prevents ghost connections

πŸ”¬ How We Found It β€” The Investigation

See the full reverse-engineering findings in PROJECT_STATE.md Β§ 9

We extracted the app.asar, deobfuscated the minified bundles, and traced the execution paths. Along the way we discovered a fully-built SSH remote execution engine hidden inside the binary. Here's what we found:

πŸ”Ž Discovery πŸ“ Detail
Remote host detection Activates when host config kind is ssh or brix
Command execution Builds args from hostConfig.terminal_command, appends --, env vars, and command
SSH wrapper Wraps commands in sh -lc <quoted> with -o BatchMode=yes -o ConnectTimeout=10
Git over SSH Routes git commands through remote shell with GIT_TERMINAL_PROMPT=0
Remote git apply Full flow: mktemp -d β†’ cat > patch β†’ test -e β†’ git apply --3way β†’ rm -rf
Codex home resolution Checks $CODEX_HOME, falls back to $HOME/.codex

All of this was already compiled into the app. We just wired it up. ⚑


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    YOUR BROWSER                      β”‚
β”‚                                                      β”‚
β”‚   webui-bridge.js                                    β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚   β”‚  window.electronBridge (fake)    β”‚               β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚               β”‚
β”‚   β”‚  β”‚ sendMessage β”‚ β”‚ subscribe   β”‚ β”‚               β”‚
β”‚   β”‚  β”‚ FromView    β”‚ β”‚ ToWorker    β”‚ β”‚               β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β”‚             β”‚  WebSocket   β”‚                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚    /ws       β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ELECTRON MAIN PROCESS (headless)                     β”‚
β”‚             β”‚              β”‚                          β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚
β”‚   β”‚  WebUI Runtime Patch           β”‚                 β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚                 β”‚
β”‚   β”‚  β”‚ HTTP     β”‚ β”‚ WebSocket   β”‚  β”‚                 β”‚
β”‚   β”‚  β”‚ Server   β”‚ β”‚ Server      β”‚  β”‚                 β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β”‚                 β”‚
β”‚   β”‚                      β”‚         β”‚                 β”‚
β”‚   β”‚  webContents.send β—„β”€β”€β”˜ (intercept & mirror)      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β”‚
β”‚                      β”‚                                β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”‚
β”‚              β”‚  SSH Transport β”‚ ◄── UNLOCKED πŸ”“       β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ SSH
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  REMOTE HOST    β”‚
              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
              β”‚  β”‚ ~/.codex   β”‚ β”‚
              β”‚  β”‚ git apply  β”‚ β”‚
              β”‚  β”‚ sh -lc ... β”‚ β”‚
              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Requirements

  • 🍎 macOS with Codex Desktop installed (or custom --app path)
  • πŸ“¦ Launcher dependencies are auto-installed when missing:
    • node/npx (both launchers)
    • ripgrep (launch_codex_webui_unpacked.sh)
    • via Homebrew bootstrap when brew is missing
  • 🌐 Internet access and curl available for automatic Homebrew/tool installation
  • βš™οΈ Optional: set AUTO_INSTALL_TOOLS=0 to disable auto-install behavior
  • 🌐 A modern browser (Chrome, Firefox, Safari, Arc, etc.) for Web UI access
  • πŸ”‘ SSH key-based auth configured for your target host β€” only needed for SSH mode (BatchMode=yes)
  • πŸ–₯️ Target host with ~/.codex directory (or $CODEX_HOME set) β€” only needed for SSH mode

πŸ›‘οΈ Security Notes

  • SSH uses BatchMode=yes β€” no interactive password prompts, key-based auth only
  • WebUI token auth uses timing-safe comparison to prevent timing attacks
  • Security headers are set on all HTTP responses (DENY framing, no-sniff, no-referrer)
  • Single-client policy prevents session hijacking from duplicate tabs
  • Rate limiting protects against WebSocket flood attacks
  • No StrictHostKeyChecking overrides β€” your existing SSH config is respected

πŸ› Troubleshooting

Problem Solution
EADDRINUSE Port already in use β€” try --port 6002
SSH preflight failed Check your SSH key: ssh -o BatchMode=yes user@host 'echo ok'
[webui] Renderer guard patch anchor not found; continuing without renderer patch (bundle shape changed). Informational on newer bundles; launcher now continues
Missing app.asar Point --app to your Codex.app location
Blank page in WebUI Check console for roots error β€” renderer patch may need updating

πŸ› οΈ Development

# Clone this repo
git clone https://github.com/friuns2/codex-web-ui.git
cd codex-web-ui

# 🌐 Launch the Web UI β€” access Codex from any browser
./launch_codex_webui_unpacked.sh --port 5999

# πŸ”“ Or launch with SSH mode unlocked (connects to your remote host)
./launch_codex_unpacked.sh --ssh-host user@your-server.com

🀝 Contributing

Found a new Codex version that breaks the patches? Bundle patterns change between releases β€” PRs to update the patch anchors are always welcome! Open an issue if you hit a new bundle shape.


⭐ Star This Repo

If you think Codex should be accessible from any browser, on any device β€” not just the Electron window it shipped in β€” smash that star button. ⭐


Built by reverse-engineering Codex Desktop's Electron bundle πŸ”¬

Because the best features are the ones they already shipped but forgot to turn on. 😏

About

Codex App Web UI and SSH remote, project moved to https://github.com/friuns2/codexui

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors