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

codex-cli-switcher

v1.0.7

Published

A macOS command-line switcher for routing OpenAI Codex CLI between native ChatGPT, CLIProxyAPI, and 9Router backends.

Readme

codex-cli-switcher

codex-cli-switcher is a macOS command-line switcher for routing the OpenAI Codex CLI between native ChatGPT, CLIProxyAPI, and 9Router backends.

It edits only its own marker-fenced blocks in ~/.codex/config.toml, keeps the rest of your Codex configuration intact, and stores local state under your user profile.

╭───────────────────────────────────────────────────────────────╮
│  cxsw — Codex Backend Switcher                                │
├───────────────────────────────────────────────────────────────┤
│  Mode:    cliproxy                                            │
│  Status:  CLIProxyAPI (http://127.0.0.1:8317/v1) HTTP 200      │
│  codex:   codex-cli 0.130.0                                   │
╰───────────────────────────────────────────────────────────────╯

Features

  • Switch Codex CLI between native, cliproxy, and 9router modes.
  • Preserve existing Codex projects, plugins, marketplaces, model settings, and comments.
  • Probe backend health from the CLI or interactive menu.
  • Relaunch, quit, or hot-reload Codex.app after changing backends.
  • Diagnose plugin/marketplace mismatches that can trigger Codex.app crash overlays.
  • Verify that the plain codex command still points to the official @openai/codex CLI and has not been replaced by cxsw.
  • Disable app-backed plugins while proxy mode is active so codex_apps does not fail on a stale native ~/.codex/auth.json OAuth token.
  • Restore Codex OAuth account JSON files into CLIProxyAPI. 9Router Codex OAuth imports stay behind an explicit unsafe opt-in to avoid double refreshers.
  • Repair Codex local session indexes so old threads stay visible after switching backends.
  • Package as a single npm-installed cxsw command with no runtime npm dependencies.

Requirements

  • macOS.
  • OpenAI Codex CLI already initialized at least once.
  • zsh, python3, curl, and sqlite3 available on PATH.
  • Optional: Codex.app at /Applications/Codex.app for app relaunch helpers.
  • Optional: CLIProxyAPI on http://127.0.0.1:8317/v1.
  • Optional: 9Router on http://127.0.0.1:20128/v1.

Installation

npm install -g codex-cli-switcher
cxsw init

Then open the menu:

cxsw

You can also run directly from a cloned repository:

git clone https://github.com/ntdung6868/codex-cli-switcher.git
cd codex-cli-switcher
./cxsw

Quick Start

cxsw status
cxsw use cliproxy
cxsw use 9router
cxsw use native

By default, cxsw use <mode> refuses unsafe switches while Codex.app or an interactive codex session is still running. This prevents a resumed thread from keeping stale backend/auth state after you switch. Use one of the reload forms for app sessions:

cxsw use --relaunch cliproxy
cxsw relaunch-app
cxsw quit-app

If you intentionally want the old "rewrite config only" behavior, add --allow-live-sessions.

Advanced hot reload is also available:

cxsw use --hot-reload cliproxy
cxsw hot-reload

Hot reload kills only the Codex.app app-server child process and lets Electron spawn a fresh one. It is faster, but a broken plugin configuration can still surface Codex.app's crash overlay. Use cxsw doctor before relying on it.

Modes

| Mode | Backend | Default target | | --- | --- | --- | | native | OpenAI direct | ~/.codex/auth.json | | cliproxy | CLIProxyAPI | http://127.0.0.1:8317/v1 | | 9router | 9Router | http://127.0.0.1:20128/v1 |

For 9router, the TOML provider id is stored as r9router because TOML bare keys cannot start with a digit.

Commands

cxsw                         # interactive menu
cxsw init                    # create local state and native snapshots
cxsw status                  # active mode, health checks, account counts
cxsw codex-status            # verify plain "codex" is still official Codex CLI
cxsw current                 # print only the active mode
cxsw last-resume             # print latest "codex resume <id>" fallback

cxsw use cliproxy            # switch to CLIProxyAPI
cxsw use 9router             # switch to 9Router
cxsw use native              # remove managed proxy blocks
cxsw use --relaunch native   # switch and relaunch Codex.app
cxsw use --quit-app native   # switch and quit Codex.app
cxsw use --hot-reload native # switch and restart app-server child only

cxsw relaunch-app            # quit and reopen Codex.app
cxsw quit-app                # quit Codex.app without reopening
cxsw hot-reload              # advanced app-server reload

cxsw doctor                  # inspect plugin/marketplace mismatches
cxsw doctor --fix            # comment out orphaned plugin entries
cxsw plugin-guard status     # show proxy-mode plugin guard state

cxsw import-backup-cliproxy  # backup OAuth JSON files to CLIProxyAPI dir
cxsw import-backup-9router   # unsafe opt-in: backup OAuth files to 9Router SQLite
cxsw sync-cliproxy-9router   # unsafe opt-in: CLIProxyAPI auth dir to 9Router SQLite
cxsw repair-sessions         # rebuild session index + adopt threads to active backend
cxsw repair-sessions --dry-run

Configuration

| Environment variable | Default | | --- | --- | | CXSW_STATE_DIR | ${XDG_STATE_HOME:-$HOME/.local/state}/cxsw | | CODEX_SWITCHER_DIR | legacy alias for CXSW_STATE_DIR | | CODEX_HOME | $HOME/.codex | | CLIPROXY_AUTH_DIR | $HOME/.cli-proxy-api | | CLIPROXY_BASE_URL | http://127.0.0.1:8317/v1 | | CLIPROXY_API_KEY | optional override; default bearer token is your-api-key-1 | | NINEROUTER_DB | $HOME/.9router/db/data.sqlite | | NINEROUTER_BASE_URL | http://127.0.0.1:20128/v1 | | NINEROUTER_API_KEY | optional override; default bearer token is sk_9router | | CLIPROXY_BACKUP_DIR | $HOME/Documents/Backups/codex-oauth-backup/cli-proxy-api-auth | | CXSW_SESSION_SYNC | 1; set 0 to skip automatic session repair on switch | | CXSW_PROXY_PLUGIN_GUARD | 1; set 0 to keep non-bundled plugins enabled in proxy mode | | CXSW_LIVE_SESSION_GUARD | 1; set 0 to allow switching while Codex.app/codex sessions are live | | PYTHON_BIN | python3 | | CODEX_APP_PATH | /Applications/Codex.app |

What cxsw Writes

When you switch to a proxy backend, cxsw inserts two managed regions into ~/.codex/config.toml:

# === cxsw managed: provider key ===
model_provider = "cliproxy"
# === cxsw managed: provider key end ===

# === cxsw managed: provider block ===
[model_providers.cliproxy]
name = "CLIProxyAPI"
base_url = "http://127.0.0.1:8317/v1"
wire_api = "responses"

[model_providers.cliproxy.auth]
command = "/bin/sh"
args = ["-c", "if [ -n \"${CLIPROXY_API_KEY:-}\" ]; then printf %s \"${CLIPROXY_API_KEY}\"; else printf %s \"$1\"; fi", "cxsw-auth", "your-api-key-1"]
# === cxsw managed: provider block end ===

The auth command means codex works even when the shell does not export the proxy API key. If you do export CLIPROXY_API_KEY or NINEROUTER_API_KEY, that value takes precedence over the local default.

Switching back to native removes only those managed regions. Your other Codex settings are left unchanged.

Codex CLI Command Safety

cxsw does not replace, alias, wrap, or patch the official codex command. Plain codex should remain the npm-installed @openai/codex CLI, while cxsw stays a separate backend switcher command.

Check that setup with:

cxsw codex-status

Proxy Plugin Guard

Codex can route model calls through cliproxy or 9router while the native ~/.codex/auth.json token is stale. App-backed plugins such as GitHub and Vercel still start through Codex's native OAuth path, though, and can fail MCP startup with token_revoked.

When CXSW_PROXY_PLUGIN_GUARD=1, switching to cliproxy or 9router temporarily disables enabled non-bundled plugins and records exactly which ones it changed under ~/.local/state/cxsw/proxy-plugin-guard.json. Switching back to native restores only that recorded set. Bundled local plugins such as browser@openai-bundled are left alone.

Session Repair

Codex stores raw conversations in ~/.codex/sessions/, but its visible thread list is also indexed in ~/.codex/state_5.sqlite and ~/.codex/session_index.jsonl. When switching between native, cliproxy, and 9router, older threads can stay tagged with the previous provider and disappear from provider-filtered views.

By default, cxsw use <mode> runs session repair after the backend switch. It:

  • backs up state_5.sqlite and session_index.jsonl under ~/.codex/backups/cxsw-sessions/;
  • scans every rollout in ~/.codex/sessions/**/*.jsonl;
  • rewrites only the session_meta.payload.model_provider metadata in rollout files when needed, with rollout backups;
  • backfills missing SQLite thread rows and rebuilds session_index.jsonl;
  • adopts local thread metadata to the active provider (openai, cliproxy, or r9router) so old conversations remain visible after switching.

Run it manually when needed:

cxsw repair-sessions --dry-run
cxsw repair-sessions

If Codex exits but your terminal does not show the native codex resume <id> hint, the conversation is still recoverable as long as it was written to ~/.codex/sessions/:

cxsw last-resume

Set CXSW_SESSION_SYNC=0 if you only want backend switching and no automatic session metadata changes.

Local State and Privacy

cxsw init snapshots your current native Codex config and auth file so native mode can be restored if ~/.codex/auth.json goes missing.

By default, state lives at:

~/.local/state/cxsw/

That directory can contain private Codex auth material. It is intentionally not part of the npm package or GitHub repository.

Development

npm run check
npm run pack:dry

The npm package is published as codex-cli-switcher, exposes codex-cli-switcher, codex-switcher, and cxsw through the bin field, and ships only:

  • cxsw
  • lib/
  • README.md
  • LICENSE
  • CHANGELOG.md

License

MIT