npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nchappell/codex-web-ui

v1.0.13

Published

Mobile-friendly web UI client for the official Codex app-server.

Readme

Codex Web UI

TypeScript web UI for controlling codex app-server remotely.

This project does not reimplement Codex. It is a client/UI layer over the official codex app-server.

Status: workaround / experimental.

Target: Linux/Ubuntu users who want a mobile-friendly Codex UI before an official Linux Codex app exists.

The app is a Next.js App Router application with Tailwind, shadcn/ui, and AI Elements components. UI routes live under /threads and /thread/[threadId]; API endpoints are implemented as Next route handlers under /api.

Requirements

  • Node.js 20 or newer.
  • The official Codex CLI installed as codex.
  • A working Codex login; check with codex login status.

Install from npm

npm install -g @nchappell/codex-web-ui
codex-web-ui init
codex-web-ui app-server start
codex-web-ui doctor
codex-web-ui

Open http://127.0.0.1:4545.

codex-web-ui init prints the login password and writes it to ~/.codex-webgui/config.json under the password key. The config file is created with owner-only permissions (0600).

The normal startup command starts only the Next.js server. The detached codex app-server sidecar must already be running and websocket-ready on the configured Unix socket. Run codex-web-ui doctor after install or upgrade to check the production build, Codex CLI availability, login status, auth setup, writable data directories, permission settings, and app-server socket.

For source or git installs, run codex-web-ui --build once if the package does not include a .next production build.

Run from source

npm install
npm run build
node ./bin/codex-web-ui.js init
node ./bin/codex-web-ui.js app-server start
node ./bin/codex-web-ui.js doctor
node ./bin/codex-web-ui.js

Open http://127.0.0.1:4545.

Container Image

The repository includes a Dockerfile for users who prefer an isolated runtime over a global npm install. The image installs the released npm package during docker build; it does not copy the local checkout into the image.

docker build -t codex-web-ui .
docker run --rm -it \
  -p 4545:4545 \
  -e CODEX_WEB_UI_PASSWORD='change-me' \
  -e CODEX_WEB_UI_AUTH_SECRET='separate-token-signing-secret' \
  -v "$HOME/.codex:/home/node/.codex" \
  -v "$HOME/.codex-webgui:/home/node/.codex-webgui" \
  -v "$PWD:/workspace" \
  codex-web-ui --cwd /workspace

The image includes the official Codex CLI and stores Web UI runtime data under /home/node/.codex-webgui. Mount ~/.codex if you want to reuse an existing Codex login. Do not bake passwords, OpenAI keys, tunnel tokens, or Codex credentials into the image.

From a repository checkout, smoke-test the container wiring without requiring a Codex login or a live app-server socket:

npm run test:docker

The Docker smoke builds codex-web-ui:smoke, starts it on port 4555 with a temporary data directory, verifies /threads, /api/auth, and password login, then removes the container and temp volumes. The container entrypoint starts the sidecar before launching the web process. By default it builds with @nchappell/codex-web-ui@<package.json version> from npm. Set CODEX_WEB_UI_DOCKER_NPM_SPEC=@nchappell/codex-web-ui@latest or another npm package spec to test a different published package, CODEX_WEB_UI_DOCKER_IMAGE=<tag> to change the local image tag, or CODEX_WEB_UI_DOCKER_SKIP_BUILD=1 to reuse an existing image.

To smoke-test the published npm deployment path, install the package into a temporary directory and run it with a fresh app-server socket:

npm run test:deployment

The deployment smoke defaults to @nchappell/codex-web-ui@<package.json version>, binds 0.0.0.0:4546, uses password codex, verifies /api/auth and password login, then stops the temporary server. Set CODEX_WEB_UI_DEPLOYMENT_NPM_SPEC, CODEX_WEB_UI_DEPLOYMENT_PORT, or CODEX_WEB_UI_DEPLOYMENT_KEEP=1 to adjust it.

CLI

The npm package exposes a codex-web-ui command:

codex-web-ui init
codex-web-ui doctor
codex-web-ui
codex-web-ui --help
codex-web-ui --port 4545
CODEX_WEB_UI_PASSWORD='change-me' codex-web-ui --host 0.0.0.0
CODEX_WEB_UI_PASSWORD='change-me' codex-web-ui --host 0.0.0.0 --full-control
codex-web-ui --app-server-socket ~/.codex-webgui/codex-app-server.sock --model gpt-5.5 --effort high
codex-web-ui --config ./codex-webgui.json

By default the CLI binds to 127.0.0.1:4545. Binding to a non-loopback host requires CODEX_WEB_UI_PASSWORD or --password; this is intentional because the app can read local files through authenticated preview/download endpoints. If no password is configured on a loopback host, startup prints a temporary local password for that process. Run codex-web-ui init to create a stable password-backed config.

The CLI uses these directory defaults:

  • Next app cwd: the package install directory.
  • Codex cwd: the current working directory where codex-web-ui was launched.
  • Runtime data: ~/.codex-webgui/data.
  • Uploads: ~/.codex-webgui/data/uploads.
  • Managed app-server socket: ~/.codex-webgui/codex-app-server.sock.

codex-web-ui doctor checks the production build, Codex CLI availability and login status, auth setup, writable data directories, permission settings, and app-server socket. It does not start the Web UI.

Useful CLI options:

codex-web-ui \
  --host 127.0.0.1 \
  --port 4545 \
  --app-server-socket ~/.codex-webgui/codex-app-server.sock \
  --cwd /path/to/project \
  --model gpt-5.5 \
  --effort high \
  --data-dir "$PWD/data"

The main command does not manage the app-server sidecar. Start it explicitly with codex-web-ui app-server start, or run the official app-server yourself and point --app-server-socket at that Unix socket. Startup fails fast if the socket is not websocket-ready.

Default permissions are intentionally restricted: new turns start with on-request approval and the workspace-write sandbox. Security is primarily chosen per thread in the UI.

Permission options are split by intent:

  • --permissions restricted|full-control is the user-facing preset. full-control unlocks the nuclear per-thread option; it does not make every new thread start with approvalPolicy=never or danger-full-access.
  • --approval-policy <policy> is a low-level default. If it is set by CLI/env/config, the backend locks that policy and browser requests cannot override it.
  • --unsafe-permissions is required before unsafe low-level defaults such as --approval-policy never or --sandbox danger-full-access are accepted.

Codex approval requests are surfaced in the UI approval tray and answered through the authenticated /api/client-requests/respond endpoint.

Configuration

The CLI loads JSON config in this order:

  1. --config <path> / -c <path>
  2. ./codex-webgui.json
  3. ~/.codex-webgui/codex-webgui.json
  4. ~/.codex-webgui/config.json

CLI options override environment variables; environment variables override the config file; the config file overrides defaults.

Example codex-webgui.json:

{
  "host": "127.0.0.1",
  "port": 4545,
  "password": "change-me",
  "appServerSocket": "~/.codex-webgui/codex-app-server.sock",
  "cwd": "/path/to/project",
  "model": "gpt-5.5",
  "reasoningEffort": "high",
  "permissions": "restricted",
  "dataDir": "~/.codex-webgui/data",
  "uploadDir": "~/.codex-webgui/data/uploads",
  "allowedOrigins": "http://localhost:*,http://127.0.0.1:*"
}

To opt into full local control from config:

{
  "host": "0.0.0.0",
  "password": "change-me",
  "permissions": "full-control"
}

Full control is intentionally broad: it allows individual threads to use approvalPolicy: "never" and sandbox: "danger-full-access". A turn that was already active before a thread is upgraded can still surface approval requests because Codex received its approval policy when that turn started.

Prefer CODEX_WEB_UI_PASSWORD and CODEX_WEB_UI_AUTH_SECRET environment variables for secrets instead of storing them in the config file.

Security and Tunnels

Treat the Web UI as local developer tooling, not as a hardened public service. Authenticated users can start Codex turns, browse and download files visible to the configured Codex cwd, upload attachments, and approve actions according to the configured Codex approval and sandbox policy.

Before binding to 0.0.0.0, using a LAN address, or exposing the port through ngrok, cloudflared, a reverse proxy, or another tunnel:

  • Set a strong CODEX_WEB_UI_PASSWORD.
  • Set a separate random CODEX_WEB_UI_AUTH_SECRET so JWT signing does not depend on the password value.
  • Keep CODEX_WEB_UI_ALLOWED_ORIGINS limited to the exact local, LAN, or tunnel origins you use.
  • Prefer HTTPS for any non-localhost access. Browser microphone and screen-capture permissions require HTTPS, localhost, or another secure browser context, and remote MCP OAuth login generally needs an HTTPS Web UI origin.
  • Avoid --full-control, --unsafe-permissions, danger-full-access, and approvalPolicy=never unless the server is only reachable by people who should have command execution access to the selected workspace.

The password gate is intentionally simple and server-side. For real internet exposure, put this behind HTTPS, use strong secrets, and restrict allowed origins to origins you actually use.

Cloudflare Tunnel has worked well for this use case in testing. A typical setup keeps Codex Web UI bound to a local port, exposes it with cloudflared tunnel --url http://127.0.0.1:4545, and sets CODEX_WEB_UI_ALLOWED_ORIGINS to the resulting https://*.trycloudflare.com or named tunnel origin. Treat the tunnel URL as sensitive, keep password auth enabled, and prefer a named tunnel or access policy for longer-lived use.

Persistence

The server writes:

  • server.jsonl under CODEX_WEB_UI_DATA_DIR.
  • sessions/<thread-id>.jsonl under CODEX_WEB_UI_DATA_DIR.
  • sessions.json under CODEX_WEB_UI_DATA_DIR.
  • Uploaded files under CODEX_WEB_UI_UPLOAD_DIR.
  • A Codex app-server socket at CODEX_APP_SERVER_SOCKET.
  • App-server PID and log files beside the socket when started with codex-web-ui app-server start.

The browser also stores the 4-hour bearer token and UI layout preferences in localStorage.

The server is protected by password auth. Login exchanges CODEX_WEB_UI_PASSWORD for a 4-hour bearer JWT stored by the browser in localStorage and sent as an Authorization header. With no password configured on a loopback host, the CLI generates and prints a temporary local password for that process. With no password on a non-loopback host, startup refuses to bind.

Default npm install paths are:

  • Config: ~/.codex-webgui/config.json.
  • Runtime data: ~/.codex-webgui/data.
  • Uploads: ~/.codex-webgui/data/uploads.
  • App-server socket: ~/.codex-webgui/codex-app-server.sock.
  • App-server PID/log files: ~/.codex-webgui/codex-app-server.pid and ~/.codex-webgui/codex-app-server.log.

To stop the managed sidecar and remove Codex Web UI runtime files:

codex-web-ui app-server stop
rm -rf ~/.codex-webgui/data
rm -f ~/.codex-webgui/codex-app-server.sock ~/.codex-webgui/codex-app-server.pid ~/.codex-webgui/codex-app-server.log

To remove the starter config as well:

rm -f ~/.codex-webgui/config.json ~/.codex-webgui/codex-webgui.json
rmdir ~/.codex-webgui 2>/dev/null || true

These cleanup commands do not remove ~/.codex, Codex login credentials, Codex's own session history, or files in your project workspaces. Clear the browser's site data for the Web UI origin to remove the localStorage token, layout preferences, saved drafts, and per-thread permission overrides.

For development, run Next directly:

npm run dev

Security regression tests cover the API auth boundary and file-explorer path containment:

npm run test:security

For the full local service, run the Codex app-server sidecar as a separate process. This keeps the Codex app-server out of npm lifecycle watchers and leaves PID/log files beside the configured socket. Next talks to the sidecar through the Unix socket in CODEX_APP_SERVER_SOCKET.

Start the sidecar:

npm run app-server:start
npm run app-server:status

Then build and run Next against that socket:

kill "$(cat tmp/backend.pid)" 2>/dev/null || true
npm run build
CODEX_WEB_UI_PASSWORD='change-me' npm start

Do not run next build while next start is serving the same .next directory; stop the backend first, then rebuild and restart it.

Sidecar commands:

npm run app-server:start
npm run app-server:stop
npm run app-server:restart
npm run app-server:recover
npm run app-server:status

app-server:recover treats a live PID without a websocket-ready socket as degraded, restarts the sidecar, and waits until the Unix socket accepts the app-server WebSocket upgrade. Use it when the UI reports connect ENOENT ...codex-app-server.sock or Unix socket closed before WebSocket upgrade.

For MCP OAuth from a phone or another machine, Codex Web UI relays OAuth callbacks through the currently used Web UI origin. When an MCP OAuth login starts, the backend updates Codex's callback config to:

mcp_oauth_callback_port = 33420
mcp_oauth_callback_url = "http://<web-ui-origin>/api/mcp/oauth/callback"

The callback route keeps valid callback path/state pairs in memory, forwards a matching callback once to Codex's local listener, and rejects expired, unknown, or repeated callbacks. OAuth providers generally reject plain HTTP redirects except for localhost, so remote or LAN OAuth login requires an HTTPS Web UI origin. Behind a reverse proxy, set CODEX_WEB_UI_PUBLIC_ORIGIN if X-Forwarded-Proto and X-Forwarded-Host are not enough to reconstruct the public origin. Set CODEX_WEB_UI_MCP_OAUTH_CALLBACK_PORT to change the local Codex callback listener port.

To expose the running server through ngrok:

ngrok http 4545

Useful environment variables:

CODEX_WEB_UI_PASSWORD='change-me' HOST=127.0.0.1 PORT=4545 npm start
CODEX_WEB_UI_ALLOWED_ORIGINS='http://localhost:*,http://127.0.0.1:*,https://example-tunnel.example.com' npm start
CODEX_WEB_UI_ALLOWED_DEV_ORIGINS='192.168.1.66' npm run dev
CODEX_WEB_UI_AUTH_SECRET='separate-token-signing-secret' npm start
CODEX_COMMAND=codex CODEX_CWD=/path/to/project npm start
CODEX_MODEL=gpt-5.5 CODEX_REASONING_EFFORT=high npm start
CODEX_WEB_UI_APPROVAL_POLICY=on-request CODEX_WEB_UI_SANDBOX=workspace-write npm start
CODEX_WEB_UI_UNSAFE_PERMISSIONS=1 CODEX_WEB_UI_SANDBOX=danger-full-access npm start
CODEX_APP_SERVER_SOCKET=/path/to/codex-app-server.sock npm start
CODEX_WEB_UI_DATA_DIR=/path/to/logs npm start

Next loads .env from the project root before reading these variables. Shell environment variables still win over .env.

Features

  • Lists active, archived, and previously logged Codex sessions.
  • Starts, loads, renames, forks, archives, unarchives, and compacts sessions.
  • Starts new turns, steers active turns, and interrupts active turns.
  • Streams app-server notifications and stderr via SSE.
  • Writes backend JSONL logs to data/server.jsonl and data/sessions/<thread-id>.jsonl; RPC request/response logs keep summary metadata instead of full payloads.
  • Shows file-backed session history in the frontend.
  • Renders turns, reasoning, user/agent markdown, commands, command output, file changes, diffs, file references, and tool calls, with AI Elements primitives for the composer, confirmations, terminal output, code blocks, and file tree.
  • Uploads file attachments and inserts uploaded paths into the composer.
  • Supports /goal <objective>, /goal status, /goal pause, /goal resume, and /goal clear through the official app-server goal RPCs.
  • Previews referenced text, code, Markdown, JSON, images, PDFs, and browser-playable video files.
  • Shows app-server status and account rate-limit usage.