remote-jcodex
v0.2.5
Published
Run the local Codex app bridge from a phone or browser URL.
Readme
remote-jcodex
Open your local Codex session from a phone or another browser. The CLI starts a token-protected HTTP bridge, prints local and LAN URLs, and shows a QR code. If Tailscale is installed and online, it configures Tailscale Serve and prefers the private Tailnet HTTPS URL for the QR code.
npx remote-jcodexShared URLs use a short path token:
http://192.168.1.8:8214/t/<token>The token is also stored in an HTTP-only cookie when the browser accepts it, so refreshes keep working after the first visit.
What's new in 0.2.5
--lite/REMOTE_JCODEX_LITE=1: optional mobile-first UI that drivescodex remote-controland skips downloading the desktop Codex web runtime.- Full UI stability: safer preload loading with token URLs, a prompt-history
guard, and defensive Electron shim access in the webview; PWA manifest
share_targetenctype to reduce browser warnings. - Mobile UX: improved tap targets for sidebar controls, composer behavior, and overlays above fixed layers.
- Internals: shared HTTP access helpers for both bridges; token-prefixed
asset URLs rewrite correctly under
/t/<token>/….
UI modes
Full UI (default) serves the patched Codex desktop webview from a prepared
runtime cache. First run (or after --clear-cache) needs network access to
download and extract that runtime on macOS.
Lite mode (--lite) serves a small bundled React UI and proxies to
codex remote-control over stdio. It does not download the desktop web
runtime, but you still need the Codex CLI installed, on your PATH, and logged
in. Override the binary with CODEX_CLI_PATH or CODEX_PATH if needed.
Scoped sharing (--thread / --chat / REMOTE_JCODEX_THREAD_ID) applies to
both modes: same token rules, URL shape, and thread lock behavior.
Requirements
- macOS 14 or newer (Linux and Windows are not supported)
- Node.js 20.19 or newer; 22.12+ recommended
- Codex CLI 0.128.0 or newer, logged in locally
- Full UI: internet on first run (or after clearing the cache) to prepare
the cached Codex web runtime (
Codex-darwin-arm64). Extraction and patching use package-local Node tooling, not systemunziporpatch. - Lite mode:
codexonPATHwith a workingremote-controlsubcommand
Startup reuses any valid cached runtime immediately, even when the bundled
runtime template has changed. Run --update-runtime to refresh the cache for
the current package version.
Without Tailscale, the phone and host must be on the same LAN.
Verify the machine without starting a bridge:
npx remote-jcodex --check
npx remote-jcodex -cUsage
Defaults:
npx remote-jcodex
bunx remote-jcodexLite mode (no desktop web runtime download):
npx remote-jcodex --lite
bunx remote-jcodex --litePort and bind address:
npx remote-jcodex --port 9000
npx remote-jcodex -p 9000
npx remote-jcodex --host 127.0.0.1 --port 9000
npx remote-jcodex -H 127.0.0.1 -p 9000Single chat/thread (scoped sharing):
npx remote-jcodex --thread <chat-id>
npx remote-jcodex -t <chat-id>
npx remote-jcodex --chat <chat-id>Diagnostics:
npx remote-jcodex --debug
npx remote-jcodex -d
npx remote-jcodex --logs
npx remote-jcodex -lRuntime cache:
npx remote-jcodex --update-runtime
npx remote-jcodex -u
npx remote-jcodex --clear-cache
npx remote-jcodex -CHelp:
npx remote-jcodex --help
npx remote-jcodex -hOn startup the CLI checks npm and may re-exec remote-jcodex@latest when a
stale npx or bunx invocation is detected. Set REMOTE_JCODEX_SKIP_LATEST_CHECK=1
only for offline debugging with a known local version.
Options
--host, -H <host> Bind address. Default: 0.0.0.0
--port, -p <port> Bridge port. Default: 8214
--thread, -t <id> Open and lock the bridge to one chat/thread
--chat <id> Alias for --thread
--lite Mobile UI via codex remote-control (skips desktop runtime)
--check, -c Verify requirements without starting the bridge
--debug, -d Print startup, health, and sharing diagnostics
--logs, -l Write logs and show the bridge log path
--update-runtime, -u Rebuild the cached Codex web runtime
--clear-cache, -C Delete the remote-jcodex cache before running
--no-token Disable access-token auth and print plain URLs
--help, -h Show command usageEnvironment
Common overrides:
REMOTE_JCODEX_HOST=127.0.0.1 npx remote-jcodex
REMOTE_JCODEX_PORT=9000 npx remote-jcodex
REMOTE_JCODEX_DEBUG=1 npx remote-jcodex
REMOTE_JCODEX_SHOW_LOGS=1 npx remote-jcodex
REMOTE_JCODEX_CACHE_DIR="$HOME/.cache/remote-jcodex" npx remote-jcodex
REMOTE_JCODEX_THREAD_ID="<chat-id>" npx remote-jcodex
REMOTE_JCODEX_LITE=1 npx remote-jcodex
REMOTE_JCODEX_SKIP_LATEST_CHECK=1 npx remote-jcodexAccess control:
REMOTE_JCODEX_ACCESS_TOKEN="shared-secret" npx remote-jcodex
REMOTE_JCODEX_NO_TOKEN=1 npx remote-jcodexREMOTE_JCODEX_ACCESS_TOKEN is optional; if unset, each run generates a new
random token. Use --no-token or REMOTE_JCODEX_NO_TOKEN=1 only on a network
you trust—anyone who can reach the URL can use the local Codex session.
Advanced:
# Full UI: use a different prepared runtime directory (must exist and be valid)
REMOTE_JCODEX_RUNTIME_ROOT="$HOME/custom-runtime" npx remote-jcodex
# Lite: non-default Codex CLI binary (CODEX_PATH is also read)
CODEX_CLI_PATH="/opt/homebrew/bin/codex" npx remote-jcodex --liteSharing
Local network
Default sharing uses the LAN.
Network http://192.168.1.8:8214/t/<token>Scan the QR code or open the printed Network URL on the phone. The bridge
listens on 0.0.0.0 by default so other devices on the LAN can reach it. Use
--host 127.0.0.1 for local-machine-only access.
Tailscale
When Tailscale is installed and online, remote-jcodex configures Tailscale
Serve to target the current bridge port.
Tailnet https://<device>.<tailnet>.ts.net/t/<token>The QR code uses the Tailnet HTTPS URL when Serve is active—handy when the phone is not on the same Wi-Fi but is on the same tailnet.
The CLI does not log in to Tailscale, connect it, disconnect it, or shut it down. If Tailscale is unavailable or offline, the CLI falls back to the LAN URL.
Scoped chat
--thread, --chat, or REMOTE_JCODEX_THREAD_ID restrict the session to one
Codex chat/thread.
Scoped mode:
- Opens the UI directly on that thread
- Puts the thread in printed URLs and the QR code
- Redirects navigation back to the scoped thread (full UI)
- Rejects renderer IPC that explicitly targets another thread ID (full UI)
Treat the scoped URL as sensitive: it still controls your local Codex session. Lite mode enforces the same thread scope at the app-server message layer.
Behavior
- Binds to
0.0.0.0:8214by default - Generates a per-run access token (unless disabled) and embeds it in printed URLs and QR codes
- Accepts
/t/<token>plus legacy?t=<token>and?remote_jcodex_token=<token> - Stores the token in a cookie when the browser accepts it
- Health-checks the bridge before printing the summary
- Full UI: uses an existing runtime cache before preparing a new one; keeps one compressed WebSocket bridge with heartbeats for IPC; batches same-tick renderer broadcasts
- Lite: serves static UI from the package and bridges the browser to
codex remote-controlover WebSocket - Prints local, LAN, optional Tailnet, and proxy status
- Writes logs only with
--logs,-l, or debug mode - In debug mode, reports HTTP/WebSocket latency, payload volume, reconnect, and heartbeat summaries
- Shows a QR code for Tailnet when available, otherwise LAN
- Applies mobile webview fixes for touch scrolling and Enter-as-newline (full UI)
- Leaves Tailscale Serve configured as a persistent bridge when available
- Stores the runtime cache at
~/.remote-jcodex/runtimeby default
Troubleshooting
If the phone cannot open the URL:
npx remote-jcodex -dDebug mode prints host, port, health checks, Tailscale availability, Serve
setup, performance summaries, and the log path. Use --logs or -l when you
only need the log file.
Quick checks:
- Phone and host share a network when using the LAN URL.
- The first opened URL includes
/t/<token>. - Firewall allows inbound connections on the chosen port.
- If a Tailnet URL returns HTTP 502, restart
remote-jcodexso Serve targets the current bridge port. - Run
npx remote-jcodex --checkfor local requirements.
Lite: ensure codex remote-control works in a terminal; use -d for
[lite …] log lines.
Release / packaging checks (for contributors):
bun run smoke:mobile— built mobile runtime still contains sidebar/composer guardsbun run verify:package— pack and audit the npm tarball for leakage, file count, and size
After upgrading the package, run remote-jcodex --update-runtime once so a
cached desktop runtime picks up new webview patches.
Security
LAN and Tailnet URLs can operate Codex as your local macOS user. Treat the token URL as secret, share it only with trusted devices, and do not expose it via Tailscale Funnel or a public reverse proxy.
The bridge rejects browser, static-file, upload, and WebSocket traffic without the token or token cookie. The token gates access to the bridge; it does not make an untrusted network safe.
License
Source-available proprietary license:
LicenseRef-RemoteJCodex-Source-Available.
You may install and use the unmodified npm package for personal, evaluation, or internal business use. Redistribution, repackaging, resale, hosted-service use, and publishing modified copies are not allowed. See LICENSE.
