import { EXPORT_CLIENT_IDS } from "../clients/client-ids"; export interface CliCommandEntry { name: string; aliases?: string[]; usage: string; summary: string; details?: string[]; hidden?: boolean; } export const CLI_COMMANDS: CliCommandEntry[] = [ { name: "codex-provider", usage: "ocx codex-provider [--yes]|revoke >", summary: "Explicitly allow or revoke local routing management for a custom Codex provider.", details: ["Consent is bound to the selected CODEX_HOME and provider ID. Only base_url is managed; transport settings and history are preserved."], }, { name: "message", usage: "ocx message [options]", summary: "Discover loaded Codex sessions and queue messages locally or through explicit SSH peers.", details: ["Remote listeners/tunnels require explicit foreground serve; no daemon start. queued is submission, not processing; never replay an unknown send."], }, { name: "chatgpt", usage: "ocx chatgpt ", summary: "Experimental ChatGPT app-server shim (macOS only, default off).", details: ["Experimental launch requires chatgptDesktop.appServerShim: true; restore removes its launcher."], }, { name: "init", aliases: ["setup"], usage: "ocx init", summary: "Interactive setup for providers and Codex config injection.", }, { name: "setup", aliases: [], usage: "ocx setup", summary: "Interactive setup for providers and Codex config injection (alias of init).", }, { name: "start", usage: "ocx start [--port ] [--socks5 [host:port] | --socks5-off]", summary: "Start the proxy server and sync models to Codex.", details: [ "--socks5 [host:port] Route outbound provider traffic through SOCKS5 (default 127.0.0.1:10808). Saved as config.proxy.", "--socks5-off Clear a saved SOCKS5 outbound proxy from config.proxy.", ], }, { name: "stop", usage: "ocx stop [--json]", summary: "Stop the proxy; preserve connected-client integrations, restore native Codex config for standalone owners.", details: [ "--json keeps the stop path unchanged and prints one structured summary document on stdout; human output moves to stderr.", "Exit codes are identical with and without --json: 0, 1, 79 (history cleanup incomplete), 80 (teardown deferred).", ], }, { name: "restore", aliases: ["eject"], usage: "ocx restore [back]", summary: "Restore native Codex config without stopping the proxy; `restore back` re-points codex at the running proxy.", details: [ "--remove-codex-provider-table Also remove [model_providers.opencodex] when a paginated home made restore keep it. Conversations tagged opencodex stop opening.", ], }, { name: "eject", aliases: [], usage: "ocx eject [back]", summary: "Restore native Codex config without stopping the proxy; `eject back` re-points codex at the running proxy.", details: [ "--remove-codex-provider-table Also remove [model_providers.opencodex] when a paginated home made restore keep it. Conversations tagged opencodex stop opening.", ], }, { name: "recover-history", usage: "ocx recover-history (--legacy-openai | --ocx-compaction ) --yes", summary: "Recover legacy provider metadata or one OpenCodeX-compacted thread for native replay.", }, { name: "uninstall", aliases: ["remove"], usage: "ocx uninstall", summary: "Remove service/shim/config and restore native Codex.", details: [ "Alias: ocx remove", "Config cleanup requires ownership metadata created by a fresh install; legacy or shared directories are left in place.", ], }, { name: "remove", aliases: [], usage: "ocx remove", summary: "Remove service/shim/config and restore native Codex.", details: [ "Alias of: ocx uninstall", "Config cleanup requires ownership metadata created by a fresh install; legacy or shared directories are left in place.", ], }, { name: "service", usage: "ocx service [install|repair|restart|start|stop|status|uninstall|remove|claim]", summary: "Run as a background service.", details: [ "With no subcommand, installs when absent or repairs an existing service.", "`repair` refreshes the definition and reloads the manager only when something changed, so repairing a healthy service is not an outage.", "`restart` is the same refresh but always restarts: on macOS an unchanged, already-loaded job is kickstarted in place. Healthy Windows tasks are reused, while stale definitions may re-register and elevate.", "Use `ocx service status` to see diagnostics and log paths. On macOS it reports four states:", "loaded from the current plist, loaded from an OLDER plist (repair), not loaded (repair), or", "`launchd state could not be verified` -- which is an unanswerable probe, NOT a down service.", "Data-plane token: nothing has to be exported by hand. On a non-loopback hostname install/repair uses", "OPENCODEX_API_AUTH_TOKEN when set, otherwise reuses the existing owner-only ~/.opencodex/service-api-token,", "otherwise generates one; the launch wrapper reads that file at start and the value never enters a plist,", "a unit file, or argv. An ADMIN token in OPENCODEX_API_AUTH_TOKEN is refused -- unset it and rerun.", "Repair and restart never ask for the environment variable again once the token file exists.", ], }, { name: "codex-shim", usage: "ocx codex-shim ", summary: "Auto-start the proxy when `codex` launches.", details: ["Use `remove` as an alias for `uninstall`."], }, { name: "tray", usage: "ocx tray [--json] [--no-start]", summary: "Install and control the Windows status tray icon (deprecated in favor of the desktop app).", details: [ "The tray starts at Windows login and provides one-click proxy controls.", "Deprecated: the OpenCodex desktop app provides the tray on Windows, macOS, and Linux; `ocx tray` remains for installs without the desktop app.", "Tray start/stop controls the icon only; use its menu to start or stop the proxy.", "--no-start (install only) installs the tray without launching it immediately.", ], }, { name: "ensure", usage: "ocx ensure", summary: "Ensure the proxy is running and Codex config/cache are current." }, { name: "connect", usage: "ocx connect [--management-url ] (--pairing-code-stdin | --admin-token-stdin) [--clients codex,claude] [--management-transport direct|relay] [--catalog-timeout ] [--no-sync]", summary: "Connect this machine to a remote OpenCodex hub without persisting the one-time authority.", details: [ "Status: ocx connect status [--json]", "Rotate or recover: ocx connect rotate (--pairing-code-stdin | --admin-token-stdin) [--json]", "Revoke while connected: ocx connect revoke --admin-token-stdin [--json]", "Machine resources: /api/machine/status, /api/machine/shim, /api/machine/clients, /api/machine/sync, /api/machine/disconnect, and the fixed /api/machine/hub-relay namespace.", "Remote browser self-logout uses /api/session/logout from the GUI; it is distinct from client disconnect and key revocation.", "Credentials are accepted only through stdin; argv and environment credential forms are not supported.", ], }, { name: "link", usage: "ocx link ", summary: "Allocate and manage a loopback remote home link.", details: [ "Port: ocx link port [--json]", "Issue: ocx link issue --alias --tunnel-port [--json]", "Status: ocx link status [--json]", "Revoke: ocx link revoke --link-id [--force --yes] [--json]", "Reconnect: ocx link reconnect --link-id [--json]", "Cleanup: ocx link cleanup [--link-id ] [--json]", "Issue, status, revoke, and reconnect use the running proxy's loopback management API and admin token.", ], }, { name: "remote-workspace", usage: "ocx remote-workspace ", summary: "Manage this workspace executor or inspect the selected Hub.", details: [ "Pair: ocx remote-workspace pair --pairing-code-stdin --root [--toolchain-root ] [--executor-helper ] [--name ]", "Agent: ocx remote-workspace agent", "Status: ocx remote-workspace status [--json]", "Hub: ocx remote-workspace hub [--json]", "Codex, Claude Code, Pi, provider logins, and API keys remain on the hub; only workspace tools execute here.", ], }, { name: "disconnect", usage: "ocx disconnect [--keep-catalog] [--json]", summary: "Restore local client state offline and clear the remote-hub connection.", }, { name: "sync", usage: "ocx sync [--expect-link | --expect-hub-key ] [--restart-codex] [--restart-app-server-only]", summary: "Fetch provider models and inject them into Codex config.", details: [ "After writing the catalog, warns if long-lived Codex app-server processes are still running.", "--restart-codex restarts the app-servers AND fully quits and relaunches the Codex desktop app on macOS, Linux and Windows, after catalog/cache writes or a committed configuration change. It ends live conversations.", "--restart-app-server-only keeps the narrow behaviour: SIGTERM to matching app-server / code-mode-host processes, desktop app left running. It wins over --restart-codex when both are given.", "--restart-desktop-app is a deprecated alias of --restart-codex and prints a notice.", "--expect-link syncs only when this machine is a connected Remote Link Child of that link (ocx connect status --json reports link.linkId); --expect-hub-key does the same for a hub client's key. The check runs under the lock that chooses the sync path.", "Any other state (disconnected, another link or key, the other client kind, a pending key rotation, connect or disconnect) changes nothing, never syncs local providers, exits 5, and prints {\"phase\":\"child_link_mismatch\"|\"hub_client_mismatch\",\"reason\":...} as the last stderr line. A malformed or repeated flag exits 2.", ], }, { name: "sync-cache", usage: "ocx sync-cache [--restart-codex] [--restart-app-server-only]", summary: "Refresh Codex's model cache from the active catalog.", details: [ "Warns when Codex app-server processes still hold an in-memory model list.", "--restart-codex restarts the app-servers AND fully quits and relaunches the Codex desktop app on macOS, Linux and Windows, so its model picker re-reads the catalog. It ends live conversations.", "--restart-app-server-only keeps the narrow behaviour: SIGTERM to matching app-server / code-mode-host processes, desktop app left running. It wins over --restart-codex when both are given.", "--restart-desktop-app is a deprecated alias of --restart-codex and prints a notice.", ], }, { name: "catalog", usage: "ocx catalog pull [--auth-env ] [--json] [--restart-codex] [--restart-app-server-only]", summary: "Install a validated remote /v1/catalog snapshot into Codex.", details: [ "Authentication is read only from the named environment variable and sent as a Bearer token.", "HTTPS is required except for loopback HTTP; redirects are refused.", "The catalog and models_cache.json are coordinated under the Codex catalog write lock.", ], }, { name: "status", usage: "ocx status", summary: "Check proxy server status." }, { name: "doctor", usage: "ocx doctor", summary: "Diagnose environment/network issues (paths, WSL /mnt, proxy env, ChatGPT reachability).", details: [ "Default mode is observe-only and reports the native-write coordinator state and exact path.", "After stopping the proxy/service, `--recover-zero-byte-coordinator --yes` moves only a proven zero-byte coordinator to a same-directory backup.", ], }, { name: "debug", usage: "ocx debug ", summary: "Show or toggle runtime provider, usage, injection, and Claude debug capture.", details: [ "Provider: ocx debug provider on | off | status | reset | logs [-f]", "Usage JSONL: ocx debug usage on | off | status | reset | logs [-f]", "Env default: OCX_DEBUG=1 (legacy OCX_DEBUG_FRAMES still works)", ], }, { name: "login", usage: "ocx login [--headless]", summary: "OAuth or API-key login for a provider.", details: [ "--headless (anthropic, anthropic2): no browser and no local port; approve in any browser and paste the displayed code.", "Codex/ChatGPT: ocx login codex runs the Codex account-pool login (same flow as ocx account login codex).", "That one needs a running proxy; the OAuth and API-key providers log in locally.", "'chatgpt' and 'openai' are the same route; an OpenAI platform API key is 'ocx login openai-apikey'.", ], }, { name: "logout", usage: "ocx logout ", summary: "Remove a stored provider login." }, { name: "gui", usage: "ocx gui [pair --origin [--json]]", summary: "Open the opencodex dashboard or create a secret single-use remote pairing grant.", details: [ "Pairing requires an explicit allowed --origin; there is no localhost or config-derived default.", "The printed grant is secret, single-use, short-lived, and must not be persisted.", ], }, { name: "hub", usage: "ocx hub invite [--json] [--data-url ] [--management-url ] [--clients codex,claude]\n ocx hub disable [--revoke-clients --client-key ...] [--json]", summary: "Invite another machine, or disable hub mode in one validated config write.", details: [ "Topology: a hub serves ONE port. Remote machines dial `hostname:port` with their own per-client", "key; the hub's own local processes dial `127.0.0.1:` with no credential, through the", "loopback companion listener enabled by `unauthenticatedLoopbackListener: {\"enabled\": true}`.", "The browser-facing management plane is separate: a loopback-only ingress published by an", "operator-owned HTTPS frontend (Tailscale Serve) and advertised as hub.managementPublicOrigin.", "", "Nothing needs to be exported by hand. `ocx service install` provisions an owner-only data-plane", "token at ~/.opencodex/service-api-token and the launch wrapper reads it at start; the value never", "enters a plist, a unit file, argv, or the environment you typed in. Never copy that file to another", "machine -- every client gets its own revocable key from the pairing exchange.", "", "invite requires a running hub and mints a single-use, short-lived pairing code through the same", "attested local route `ocx gui pair` uses, then prints the exact command to run on the other", "machine. The code is bound to hub.managementPublicOrigin and to the connecting machine's local", "browser origin (`http://localhost:10100` unless corsAllowOrigins names another loopback origin);", "the bound origin is always printed, and a different one names the port the client needs.", "--data-url overrides the advertised data origin; hub.dataPublicOrigin is the persistent form, and", "the fallback is http://:. A loopback or wildcard bind has no such address, so", "invite refuses instead of advertising http://localhost:, which would tell the other machine", "to dial itself and spend the code.", "--management-url is a CONFIRMATION, not an override: the grant is bound to", "hub.managementPublicOrigin, so a differing value is refused instead of printed.", "--clients chooses which client configs the printed ocx connect line will point at the hub.", "--json emits { code, expiresAt, dataUrl, managementUrl, command }. Do not persist the code.", "Hub state, including the data token and the companion listener, is reported by `ocx status`.", ], }, { name: "update", usage: "ocx update [--tag latest|preview]", summary: "Update opencodex. Preview installs stay on the preview tag unless overridden.", }, { name: "provider", usage: "ocx provider ", summary: "Non-interactive provider management.", details: [ "Subcommands:", " list List configured and available providers", " add Add a provider (registry or custom)", " edit Edit live provider fields", " pacing Read/edit live request pacing rules", " snapshot Read a non-secret provider editor baseline", " apply Apply edited providers with baseline conflict checks", " test Test the provider's upstream model endpoint", " remove Remove a configured provider", " show Show provider config details", " set-default Change the default provider", " add/remove/set-default support --live; live removal also requires --yes.", " selected Show or set the provider model allowlist", " quota Show provider quota reports", " resets Show recently detected quota resets", " presets List GUI provider presets", " account-mode Set OpenAI Codex pool/direct mode", "", "Examples:", " ocx provider list", " ocx provider list --jsonl", " ocx provider presets --json", " ocx provider add anthropic --api-key ", " ocx provider add my-ollama --adapter openai-chat --base-url http://localhost:11434/v1", " ocx provider show anthropic --json", " ocx provider pacing anthropic --json", " ocx provider snapshot --json", " ocx provider set-default anthropic", " ocx provider edit xai --xai-chat on # opt Grok 4.5/4.6 into Chat Completions", " ocx provider edit xai --xai-chat off # use Responses again", " ocx provider remove my-ollama", "", "Registry providers are auto-configured by name. Custom providers need --adapter and --base-url.", ], }, { name: "account", usage: "ocx account ...", summary: "List and switch provider accounts and API-key pools (GUI parity).", details: [ "list [provider] Codex account pool, OAuth accounts and API keys (identifiers shown masked as the API returns them).", "current Show the active account or key.", "use Switch the active credential; 'main' selects the Codex App login.", "refresh Force-refresh Codex or provider quota reports.", "auto-switch Control the Codex pool threshold.", "priority [first|earlier|normal|later|last|-100..100|reset] Selection order; omit the value to read it.", "remove --yes Remove a stored account or key after an existence check.", "add-key [--label