CLI Agents, Routing, and Integrations
These commands control agent policy and routing, inspect the live proxy, and connect supported clients to opencodex.
Agent policy
Section titled “Agent policy”ocx agent <status|injection|effort|subagents|fallback|roles|sidecar|memory-models|compaction-routing> ...
Section titled “ocx agent <status|injection|effort|subagents|fallback|roles|sidecar|memory-models|compaction-routing> ...”Manage the headless multi-agent roster, effort caps, prompt injection, fallback, and sidecar settings.
Use status for the current policy. See Sub-agent surfaces for how
surface modes, delegation, effort, and fallback behavior fit together.
ocx agent subagents set ark/model-a,openai/gpt-5.5ocx agent roles is for omo (Codex / LazyCodex). It lists each Codex agent role in
$CODEX_HOME/agents with its model pin and whether ~/.omo/omo.jsonc can be updated, or says
LazyCodex is not installed, in which case set is refused. ocx agent roles set <role> <model> [--effort <level>] rewrites only
that role’s root model line, and its model_reasoning_effort line with --effort, and mirrors both into omo.jsonc at
[codex].agents.<role> as model and reasoning. An effort LazyCodex has no level for, such as ultra, is written to the role file only. A missing omo.jsonc, or one containing comments, is left unchanged
and the command says so. See omo (Codex / LazyCodex) role models.
ocx agent roles set explorer xai/grok-4.5 --effort mediumocx agent roles suggest is omo (Codex / LazyCodex) only, refused like set when LazyCodex is not
installed. It sizes every role with one call to the default Codex model (or --model) and
prints a proposed model and effort per role without writing anything. --apply writes every proposal
through the same write as set, skipping and naming the roles whose model and effort already match.
See Auto-assign.
One --apply accepts at most 50 changed roles, so its recorded changes fit one complete
history batch and can be restored together in the dashboard’s Change history. Already-set,
unsized and unassigned roles do not count toward this limit. If more than 50 roles would change,
the command exits 5 before sending any role update. Preview without --apply, then use
ocx agent roles set <role> <model> [--effort <level>] for individual changes.
Updates run sequentially. If a request fails, earlier confirmed writes remain applied, later
roles are not attempted, and the command keeps the original nonzero error exit. The receipt names
confirmed writes, the role whose write was not confirmed, roles not attempted, and the server-issued
history batch when known. A lost response can follow a saved write, including the first write before
its batch id is received; inspect ocx agent roles --json and the dashboard history before retrying.
No automatic retry or rollback occurs. History remains subject to its existing availability and
retention limits; a batch id does not guarantee that every write was recorded or is still restorable.
With --json, an interrupted apply adds complete: false, unconfirmedRole and unattemptedRoles
beside the existing applied, skipped and omoJsoncNotWritten arrays. A preflight refusal instead
adds refusal with code too_many_role_changes, the limit and the proposed change count.
Human-readable suggestion output displays terminal control characters as visible escapes.
Use --json when you need the original suggestion values without presentation escaping.
ocx agent injection suggest <work> does the same for the delegation model: it sizes the described
work, proposes the cheapest sufficient model and an effort from the delegation picker’s list, and writes
nothing unless --apply is given, which saves through the same write as injection set. See
Delegation model and effort.
ocx agent sidecar web --list and ocx agent sidecar vision --list print the models the
server currently offers for each sidecar — the exact filtered set the dashboard picker shows
(picker-visible rows plus the login-entitled Luna/Haiku auth slots, intersected with executor
availability for web search, minus provably text-only models for vision). Human-readable lists
show each model’s backend in brackets. A web-search --model write resolves that server-offered
row and persists its backend and model together, so switching to an Anthropic option cannot keep
an OpenAI backend (or vice versa). Writes go to the same management route as the GUI and are
subject to the same per-sidecar gate: web search refuses a backend/model pair outside the listed
set (closed membership), while vision refuses only a model provably unable to see (unknown ids
stay writable).
ocx agent sidecar web --listocx agent sidecar web --model gpt-5.6-lunaocx agent sidecar web --enabled off--enabled off is the same switch as the Dashboard’s Off row: OpenCodex stops running the
sidecar and the Codex integration writes web_search = "disabled" into ~/.codex/config.toml,
which is what lets an MCP search server be the only search path. --enabled on removes that
marker-owned line again. When the save actually moves the switch, the command reports the
Codex-side write it triggered (codexWebSearch in --json, a trailing Codex config: line
otherwise) and points at ocx sync when it could not happen; a save that leaves the switch
where it was has nothing to report and prints no Codex config: line. The flag works for
vision too.
Injection defaults and sidecar runtime settings
Section titled “Injection defaults and sidecar runtime settings”ocx agent injection status --jsonocx agent injection set --sync-codex-defaults off --jsonocx agent injection status --jsonocx agent sidecar web --stream-routed-output on --jsonocx agent sidecar vision --timeout-ms 30000 --jsonocx agent sidecar status --jsonRun writes only for the requested change. Injection --sync-codex-defaults on|off
updates syncCodexSubagentDefaults; omitted model/effort/prompt/guidance stay intact,
and - clears model/effort/prompt. The receipt has actual normalized
model, effort, prompt, multiAgentGuidanceEnabled and
syncCodexSubagentDefaults, not a fabricated catalog result.
Web --reasoning remains supported. --max-descriptions and --timeout-ms are
vision-only; timeout accepts integers from 1 to 2147483647 milliseconds.
--stream-routed-output is web-only. Partial writes preserve sibling settings.
The new-option receipt exposes only the selected public webSearch or vision
state and codexWebSearch apply report. {applied:false, reason, retryable}
distinguishes native apply deferral/refusal from a saved setting; a missing or
mismatched new setting is unverified and nonzero. Read status for full observed
settings, including web reasoning. Do not retry blindly on ownership refusal.
Memory and compaction routing overrides
Section titled “Memory and compaction routing overrides”ocx agent memory-models show --jsonocx agent memory-models set --extract-model <route> --extract-effort high --consolidation-model <route> --jsonocx agent memory-models show --jsonocx agent compaction-routing show --jsonocx agent compaction-routing set --model <route> --effort high --triggers manual,auto --sources '<exact-source>,<provider>/*' --jsonocx agent compaction-routing show --jsonEach set replaces the entire block. Memory accepts extract/consolidation model
and optional effort pairs; an effort without that phase’s model is refused.
Omitted phases use their existing/default route, not a stopped pipeline.
--file memory.json instead reads the block itself:
{"extract":{"model":"example/model","reasoningEffort":"high"}}An explicit memory file {} is valid and remains an empty override block;
ocx agent memory-models clear --json writes null. Both mean no custom override,
not disabled memory processing. File mode is exclusive with scalar options.
Regular UTF-8 files or piped --file - use the 4 MiB/30-second bounded-input
contract, including a 4 MiB serialized request limit.
Compaction files contain required model, optional reasoningEffort, triggers
and sourceModels. Triggers are unique manual/auto; source selectors must be
exact and unique, or provider/* patterns. Omitted triggers use server defaults;
omitted sources select all sources, not the previous custom scope.
ocx agent compaction-routing clear --json writes null and restores ordinary
compaction routing without disabling compaction. No synthetic model call verifies
these saves.
Reads return only {memoryModels: blockOrNull} or {compactionRouting: blockOrNull}.
Writes add catalogRefreshPending: false exits 0 without promising every client
applied, true exits 1 after saving. Missing/malformed pending evidence is null with
verification:"unverified" and exit 1. Read back before recovery.
ocx effort [status|set|clear]
Section titled “ocx effort [status|set|clear]”Inspect or change main and subagent reasoning-effort caps through the live proxy, or the local
configuration when no proxy is available. Cap values are low, medium, high, xhigh, max,
and ultra; - clears the selected cap. none and minimal are not cap levels and are rejected
before probing the proxy or submitting an update, including when another option in the same command is valid.
They remain valid for --injection, which sets the separate injection effort rather than a cap.
ocx effort status --jsonocx effort set --main high --subagent lowocx effort set --subagent -Status preserves existing stored/runtime cap values and reports unsupported values in warnings
(an empty array when none are unsupported). The same warnings appear in human output and name the
field that is ignored with a correction command. Status never repairs or rewrites those values.
An ignored subagent field does not remove a valid main cap. ocx effort clear clears both caps
while retaining the separate injection-effort setting. See Sub-agent surfaces
for the request surfaces where caps apply.
ocx v2 <status|on|off|mode <v1|default|v2>|keep-native-v1 <on|off>|threads <n>|mode-hint <text|--clear>>
Section titled “ocx v2 <status|on|off|mode <v1|default|v2>|keep-native-v1 <on|off>|threads <n>|mode-hint <text|--clear>>”Manage the Codex multi_agent_v2 feature flag and the three-state multi-agent surface mode.
These operate locally by default. --live uses the selected running proxy with no
local fallback; both targets support --json. Re-read status on the same target
after a change and distinguish stored settings from new-session behavior.
| Subcommand | Action |
|---|---|
status (default) |
Report the current v2 flag, multi-agent mode, and thread concurrency. |
on |
Enable the global multi_agent_v2 feature; local changes resync the catalog. Rejected while the v2 hybrid pin is active because the global override would defeat it. |
off |
Disable the multi_agent_v2 feature and resync the catalog. |
mode v1 |
Force all models to v1, disable native v2, and preserve the active thread limit. |
mode default |
Respect upstream model surface pins. |
mode v2 |
Force models to v2 and preserve the active thread limit. With keep-native-v1 off, enable global native v2; with it on, disable the global override and use catalog pins. |
keep-native-v1 on|off |
Under mode v2, keep ChatGPT-native models on v1 and routed models on v2. Enabling it disables the global V2 override before catalog sync. |
threads <n> |
Set the active v1/v2 thread limit to an integer of at least 1. |
mode-hint <text> |
Set the Proactive delegation hint (Ultra mode) for every model and effort. |
mode-hint --clear |
Remove the hint so the effort-derived policy (ultra = proactive) resumes. |
ocx v2 statusocx v2 mode v1ocx v2 mode defaultocx v2 onocx v2 threads 16ocx v2 mode-hint "Proactive multi-agent delegation is active."ocx v2 mode-hint --clearThe mode subcommand writes multiAgentMode to the opencodex config and resyncs the Codex catalog.
Mode and flag transitions move the current numeric thread limit between the valid v1/v2 Codex keys;
a failed transition restores the original config.toml. Changes apply to new Codex sessions, while
running sessions keep their pinned surface.
Codex resolves an enabled global multi_agent_v2 override before the selected model’s catalog
pin. The hybrid keep-native-v1 contract therefore keeps that global override off; otherwise a
native row stamped v1 would still start on V2 and produce backend-encrypted child tasks.
mode-hint writes features.multi_agent_v2.multi_agent_mode_hint_text in Codex’s
$CODEX_HOME/config.toml even when multi_agent_v2 is currently disabled. The
command only persists the override; it does not enable or disable the feature, so
the hint takes effect when a matching Codex surface is active. The hint overrides
codex-rs’s effort-derived multi-agent policy, so any model and any reasoning effort
receives the Proactive delegation prompt. It does not change reasoning effort
itself. A missing argument or a whitespace-only value is rejected; only --clear
removes the hint. The Subagents dashboard’s Ultra mode on toggle has a stricter
gate: it requires the native feature to be enabled with an explicit v2 surface
(ocx v2 mode v2); ocx v2 on alone does not satisfy that dashboard gate.
Explicit v2 target and outcome
Section titled “Explicit v2 target and outcome”ocx v2 status --jsonocx v2 status --live --jsonocx v2 mode v1 --live --jsonocx v2 status --live --jsonThe live write uses the existing management route. Only explicit live mode
accepts --acknowledge-surface-advisory; add it only when acknowledging that
advisory is requested. Local mode and status/on/off/keep-native/threads/hint reject
it. There is no automatic acknowledgment.
For literal reserved hint text, pass one quoted operand after --:
ocx v2 mode-hint --live --json -- '--clear'This stores literal --clear; without --, mode-hint --clear removes the hint.
The suffix is not scanned for help, live, JSON or clear controls; controls belong
before --. Extra operands and duplicate flags refuse before mutation.
Local JSON is {ok, target:"local", action, changed, state, sync} using actual
post-write state. Mode/keep-native and changed on/off keep their real sync attempt
even without a discovered port; threads/hints and unchanged on/off add no sync.
An absent/malformed sync result becomes unverified with exit 1, not success.
changed or state can be unknown after failure; do not claim rollback.
Live status reports validated state/advisory/recommendation with target:"live";
writes add ok:true and catalogRefresh. Only committed, nondegraded refresh exits
0. HTTP 502 may mean partially applied native state: inspect before retrying.
Local usage errors retain exit 1; new live usage errors use exit 2.
Combo routing
Section titled “Combo routing”ocx combo <list|show|set|remove|stats> ... · ocx route combo ...
Section titled “ocx combo <list|show|set|remove|stats> ... · ocx route combo ...”Manage combo failover and round-robin virtual models. ocx route combo is the hierarchical alias;
combos and routing profiles are distinct resources. Combo targets use
provider/model[:weight],provider/model[:weight].
ocx combo listocx route combo set reliable --targets ark/model-a:2,openai/gpt-5.5set accepts --strategy, --sticky, --effort, --alias, --rename-from, --native-alias, and
--display-name <label|-> (- clears the label). A native alias captures only one currently supported,
unqualified bare OpenAI model id. Bare gpt-5.6-* native aliases use Codex Pool/Direct credentials.
Account-qualified OpenAI routes remain distinct, while provider-qualified routes such as
openai-apikey/gpt-5.6-* use their configured API key and never fall through to the native alias.
Read the safety and visibility contract in the guide before enabling the compatibility pair.
Only when the effective strategy is JEV (--strategy jev, or a stored JEV Combo when --strategy is omitted), the decision method is chosen by one of two mutually exclusive flags.
--decision-provider <provider|-> names a configured jev-decision row (for example a self-hosted
Ollama tev1) as a System One-compatible server. --decision-model <route|-> names an ordinary
opencodex route (for example ollama/qwen3:4b) that answers the same choice as JSON; it cannot be
this combo or any JEV combo. A new JEV Combo that omits both uses TypeSafe; an existing JEV Combo keeps
its stored decision method until one of the flags changes it. --decision-timeout <ms|-> sets the
decision deadline (1000–120000, default 4000); - clears any of the three.
ocx combo set <id> --decision-quota-signals on|off|- controls per-Combo advisory evidence.
--decision-quota-tiers '{"limited":80}' sets partial threshold overrides; - clears them.
Both are JEV-only. Omitted policy survives --targets-file or --targets replacement and rename. Without
--strategy, replacing the targets of an existing Combo keeps its stored strategy, so a JEV Combo stays JEV with
its decision method, quota settings and session pin; a new Combo defaults to failover. If the kept JEV
policy rejects the new targets, the command fails, names that policy, and saves nothing. Off retains thresholds;
switching away from JEV removes both settings. This adds quota data to the selected decision
backend, not probes, new account selection or hard exclusions. See
quota defaults, freshness and privacy.
ocx combo set <id> --session-pin <duration|-> (JEV only) keeps each client session on the target
JEV chose for it while the session stays active, so the provider prompt cache stays warm. The
duration is the idle window: 90s, 20m, 1h or milliseconds, from 1 minute to 24 hours; -
turns it off. See Session pin for JEV.
ocx combo test [--combo <id>] [--decision-provider <provider|jev> | --decision-model <route>] [--decision-timeout <ms>] sends one synthetic decision probe through a saved combo’s method or an
unsaved selection and reports the gate, backend, and latency; it may spend one decision call.
ocx combo discover [--query <text>] lists configured System One rows and catalog models that look
like decision models, with the derived endpoint.
For structured target metadata, inspect offline help and the current combo:
ocx combo set --helpocx combo list --jsonocx combo show reliable --jsonA --targets-file document is a nonempty ordered array, for example this shape
with provider/model values replaced by actual configured candidates:
[{"provider":"example","model":"raw/model","weight":1,"reasoningEfforts":["high"],"modelProfile":"Reasoning tasks","lastResort":false}]Optional fields are weight, reasoningEfforts, modelProfile and lastResort.
Efforts are a unique nonempty list of low, medium, high, xhigh, max, ultra;
empty/none/minimal custom-model semantics do not apply. Files or explicit piped
- have a 4 MiB limit and 30-second read deadline; the serialized management body
must also fit 4 MiB. Unknown fields refuse before the write.
ocx combo set reliable --targets-file targets.json --image-input auto --reasoning-effort-mode strict --jsonocx combo show reliable --json--targets-file and --targets are mutually exclusive. Omitting both preserves
complete target metadata for partial edits; replacement files preserve order and
explicit lastResort: false. --image-input auto|disabled and
--reasoning-effort-mode strict|adaptive preserve omission, while explicit auto
and strict override saved disabled/adaptive values. Reasoning-effort mode is
separate from --effort-mode fallback|force, which governs the default effort.
--allow-metered-targets on|off grants or clears operator consent for marked combo targets on a loopback-only proxy; public and linked callers still need configured-key consent.
--native-alias on|off preserves explicit false; the legacy bare flag means true.
Turning it off may require the intended alias clear, --native-alias off --alias -,
to avoid retaining an incompatible native alias. Set/rename is an upsert without
CAS, so re-read after changes. The receipt is {success, id, model, combo, catalogRefresh};
skipped, failed or degraded catalog refresh returns nonzero after saving.
Observe combo decision statistics
Section titled “Observe combo decision statistics”ocx combo stats reliable --range 30d --jsonUse the exact stored combo ID from list/show, not its public model or alias.
Ranges are 7d, 30d (default), and all. This reads recorded JEV observations
without running a paid decision probe. Inspect decisions, model attempts,
measured attempts, model tokens and decision tokens separately. Keep the
measuredModelAttempts/modelAttempts and decisionUsageReported/decisions
coverage ratios with the totals. Nullable averages are unavailable, not zero.
Preserve usageIncomplete, historyTruncated, entriesTruncated, dropped-entry
counts and snapshot-window boundaries. Zero observations do not prove success.
There is no monetary cost or comparative savings field in this report.
See Combos for routing behavior and configuration guidance.
Fallback off
Section titled “Fallback off”ocx fallback <status|off|on|clear|local> ...
Section titled “ocx fallback <status|off|on|clear|local> ...”ocx fallback status --jsonocx fallback off --kind providerocx fallback on --route combo/codingocx fallback clear --provider anthropic --kind modelocx fallback local on --device mac-studiooff, on and clear take --kind model|provider|all (default all) and at most one scope:
--provider <name>, --route <selector> or --device <id|alias>; with none they set the global switch.
A device set to off always refuses; otherwise route beats provider beats global. local records whether a
device may use its own providers while the Home is unreachable, a permission GOAT reads; OpenCodex itself
still answers home_unreachable there. The commands talk to the live proxy; on a Remote Link Child,
status reads the Home and writes are refused. See Fallback off.
Routing profiles
Section titled “Routing profiles”Existing profiles support inspection and evaluation through the live API:
ocx route policy list --jsonocx route policy show reliable --jsonocx route policy dry-run reliable --model-context 128000 --tools --image --structured-output --jsonOnly run this evaluation with authority to activate Lab on the target. The management POST can activate Lab and start automation that is already enabled there, including upstream probes. Use list/show for observation without that activation effect.
Replace reliable with a listed ID. evaluate is an alias for dry-run; both
send requirements to the saved profile’s evaluator without an inference request.
Creation, update and deletion use the explicit file/revision workflow below.
Combo writes edit a separate resource. Missing profiles return exit 4 and missing
operands return 2.
Edit a routing profile with its observed revision
Section titled “Edit a routing profile with its observed revision”Create/update can activate Lab and already-enabled automation, including upstream probes. Only run them with that authority. List/show are observational; first read offline help and save the intended profile:
ocx route policy update --helpocx route policy show reliable --json > profile.observed.jsonjq 'del(.id, .model, .revision) | if .alias == null then del(.alias) else . end' profile.observed.json > profile.next.jsonEdit and review the next file; keep the observed file unchanged. Input contains
only editable alias, candidates, require, optimize, limits,
unknownEvidence, and compatibility with supported nested fields. id, model,
revision, unknown keys and null alias are not editable input. The server still
validates provider, alias and policy semantics. --file - accepts piped stdin;
regular UTF-8 files/stdin have the 4 MiB and 30-second bounded read contract.
ocx route policy update reliable --file profile.next.json --expected-revision '<exact-revision-from-observed-show>' --jsonocx route policy show reliable --jsonUse the original opaque revision explicitly. HTTP 409 / exit 5 means read show
again, review concurrent changes and rebuild the edit. Never silently fetch a
replacement revision, retry or convert update into create. For an authorized new
ID use ocx route policy create <new-id> --file profile.next.json --json without a
revision. Authorized removal is ocx route policy remove <id> --yes --json and
has no revision guard.
Create/update returns {success, id, model, profile, catalogRefresh} with the new
profile.revision; remove returns {success, id, catalogRefresh}. Only committed,
nondegraded refresh exits 0. A saved receipt with skipped/failed/degraded refresh
exits 1: inspect before recovery instead of repeating the configuration write.
Compatibility Lab
Section titled “Compatibility Lab”Lab is local inspection and explicit evidence/automation management. Reads use the local projection and do not require a running management API:
ocx lab status --jsonocx lab catalog --jsonocx lab subjects --limit 10 --jsonocx lab automation status --jsonocx lab automation runs --limit 10 --jsonocx lab public community --jsonsubject, observations, event, artifact, and production-signals follow
local evidence lineage. The public family offers preview/export by repeated
--event <id>, verification/import through --file <bundle.json>, and community
context. Export and import write local evidence. Verification can print its
result and still exit nonzero when the bundle is not cryptographically valid.
Automation enable/disable changes local policy; manual lab run selects a layer
and scenario and may spend upstream quota. Read ocx help lab and the relevant
leaf before these authorized operations. A saved local policy does not prove
that a separately running proxy’s scheduler adopted it. Full automation policy
editing and run cancellation are not exposed by these CLI controls.
Observability and debug
Section titled “Observability and debug”ocx observe <logs|usage|storage|memory|debug|claude-inbound|injection> ...
Section titled “ocx observe <logs|usage|storage|memory|debug|claude-inbound|injection> ...”Inspect proxy requests, usage, storage, memory, and debug data. The direct aliases are:
| Alias | Equivalent resource |
|---|---|
| `ocx logs [filters] [–follow] [–json | –jsonl |
| `ocx usage [–range <today | 1d |
| `ocx usage compare [–range <today | 1d |
ocx storage [--json] |
ocx observe storage |
ocx memory [--json] |
ocx observe memory |
ocx observe usage --range 30d --jsonocx usage --since 2026-09-01T09:00:00Z --until 2026-09-01T10:59:59.999Z --json--since and --until must be supplied together. They accept integer epoch milliseconds or
full ISO datetimes with an explicit timezone, include both endpoints, and override --range.
Invalid or reversed bounds fail before the request. Human output prints the requested interval;
--json includes customWindow, since, and until. Existing surface/provider/model filters
still apply. These commands query the running proxy; they do not provide offline reports.
--range today (alias 1d) reports the current local day. --provider and
--model narrow the report to one upstream target — distinct from
--surface, which selects the calling client (Codex, Claude Code, Grok)
rather than the provider serving the request.
The default view prints request, token and estimated-cost totals plus
per-provider and per-model breakdowns. Costs are API list-price equivalents,
not a billing receipt: subscription plans and provider credits are billed
separately, and requests with no matching price row are counted as
unpriced/unmetered rather than folded in as zero.
ocx usage --range today --provider xaiWhen some usage records cannot be included, human output warns, including when there are zero readable rows.
Any displayed totals reflect readable records only. If a filter has no readable matches, the output shows
the warning and guidance instead of total lines; skipped records may contain matches.
--json preserves the response-level usageIncomplete diagnostic and reason.
Compare a range with the previous equal window
Section titled “Compare a range with the previous equal window”ocx usage compare --range today --jsonocx usage compare --range 7d --provider xaiocx observe usage compare is the equivalent family form. The command reads GET /api/usage
twice: the named range ending now, then the same range evaluated one equal window earlier
(one local day for today/1d, seven for 7d, thirty for 30d). Default range is 30d.
--range all is refused because open history has no previous equal window. --since and
--until are not accepted; the windows are derived. Surface, provider, model, and API-key
filters apply to both reads. Human output prints current, previous, signed delta, and percent
change. --json is {schemaVersion,range,current,previous,delta,change,incomplete}. The two
reads are sequential, not an atomic snapshot. Custom since/until on each response must
match the requested window. Both reads use the same connection and credential. If the
connection, account, or credential changes during the command, it reports an owner
mismatch and asks you to retry instead of printing a comparison.
Page indexed request history
Section titled “Page indexed request history”ocx logs history --provider xai --status 200 --limit 50 --jsonocx logs history --cursor '<nextCursor>' --jsonocx logs get <request-id> --jsonocx observe logs history and ocx observe logs get are the equivalent family
forms. These read the derived request-history index, not the recent ocx logs
ring. --limit is 1–100 (default 50). --from and --to accept epoch
milliseconds or full ISO datetimes with a timezone and are inclusive. --json
returns {entries,hasMore,nextCursor,index}. --jsonl emits rows only; when
more pages exist, nextCursor=… is printed on stderr so a caller can resume
without mixing the token into the row stream. Empty matches succeed. get
returns one canonical row by request ID; ocx logs explain remains the
route-decision view for that same ID.
Filter a bounded log snapshot
Section titled “Filter a bounded log snapshot”ocx logs filter --surface claude --status errors --time-window 1h --scan-limit 2000 --limit 50 --jsonocx observe logs filter is the equivalent family form. This reads one recent
window, filters locally, then keeps the newest matches in their original order.
--scan-limit controls fetched rows (1–2000, default 2000); --limit controls
returned rows (1–2000, default 200). JSON reports
{schemaVersion:1,logs,cursor,filters,window:{scanLimit,loaded,matched,returned,limit}}.
Counts describe this observed window, not all history. JSONL emits rows only;
empty matches succeed. Cursor metadata is not a resumable search token.
Selectors include --surface all|codex|claude|grok, --status all|success|errors,
--time-window all|15m|1h|24h, --model, --provider, --conversation
(alias --conversationId), --intercepted-only, --min-tok-per-sec,
--max-tok-per-sec, and --protocol-mode all|native|translated|legacy-bridge|blocked|none.
Model/provider equality is trimmed and case-insensitive, including
resolved/served models and attempts. Claude includes Desktop; Codex means absent
surface. Success is HTTP 200–299, errors 400–599. Time lower bounds are inclusive.
Speed uses observed value-kind tok/s, with inclusive minimum and exclusive
maximum; unavailable values fail active speed filters. Protocol none includes
absent or invalid traces. Conversation matching uses the same hash-aware IDs as
ordinary logs. Interception selects string-valued rewrite markers.
Unknown/repeated/conflicting flags, invalid bounds, and follow/events fail before discovery. Malformed, oversized or failed reads are nonzero, not empty results. To reduce response size, reduce the scan limit; reducing output limit does not change the fetch. For streaming use the separate follow forms below.
Search usage model rows
Section titled “Search usage model rows”ocx usage --range 7d --search 'model-a' --json--search matches a trimmed case-insensitive substring in model, provider or
resolved model after reading the report. It sorts model rows by descending total
tokens with stable ties and keeps up to 100 by default. JSON adds
modelView:{query,matchedModelCount,returnedModelCount,limit:100,truncated};
human output labels the view and shows its selected model rows. Report totals,
provider/day/account rows, exact filters and incomplete/window metadata remain
unchanged. No model match does not mean no report usage.
An explicit blank query (--search=) selects the top-100 view; omitting search
preserves the existing output. Exact --provider/--model still scope the
underlying report. Search does not broaden selected-key or connected-client
self scope and is never sent as a new Hub API query parameter.
ocx usage --top 25 (also ocx observe usage --top 25) sets the human model table limit to an integer from 1 to 1000. The default is 10, or 100 with --search; the limit applies after search filtering. It changes local display only: report totals, provider/account rows and API parameters stay unchanged. With --json, a valid --top is ignored; JSON retains its existing full report or 100-row search view. Invalid limits return exit 2 before fetching.
Saved companion usage totals
Section titled “Saved companion usage totals”ocx companion show --jsonocx companion usage --jsonThe second command reads saved companion settings, then today and 30d usage
sequentially on the same management runtime. It applies the saved models and
hiddenProviders preferences and preserves unknown/unmeasured costs and tokens.
Null model selection means all; an empty selection means none. It does not
change settings, operate native windows or relay through a connected client.
JSON returns schemaVersion:1, filters, settingsUpdatedAt,
settingsCorrupt, settingsFallback, ranges and partial. Each range has
status:"available" with filtered data, or status:"unavailable".
An unavailable range sets partial and exit 1 while retaining the other range.
Available incomplete data retains its own metadata; it is not measured zero.
Valid server defaults retain a null settings timestamp and set fallback;
corrupt-file defaults additionally set corrupt and warn in human output.
Malformed settings stop before usage reads. These reads are not an atomic
snapshot. Each GET has a 10-second fetch/body deadline after discovery and a
32 MiB response cap; this is not a whole-command deadline. Signals exit 130/143
without late results.
Follow request windows or injection sequences
Section titled “Follow request windows or injection sequences”ocx logs --helpocx logs --limit 200 --jsonocx logs --follow --events --limit 200--events requires follow and implies JSONL; redundant --jsonl is accepted.
--json remains one-shot and conflicts with follow/events. Each events-v1 line
is {schemaVersion:1,type:"snapshot"|"append",rows,cursor,limit}. Replace the
consumer window on snapshot, append/trim on append, preserving order and repeated
IDs. Initial empty and reset/removal snapshots are emitted; stable empty polls
remain silent. Legacy arrays are snapshots with cursor null, not invented cursors.
These are observed windows, not a lossless replay of traffic missed between polls
or after ring eviction.
ocx logs --follow --jsonl --limit 200 retains row-shaped output. It re-emits changed
occurrences, including same-ID status/token amendments and repeated IDs. Do not
collapse everything by request ID. This legacy output cannot encode removals,
resets or exact window order; choose events when those distinctions matter.
Log follow limit is 1–2000, default 200.
ocx observe injection --limit 500 --jsonocx observe injection --follow --jsonl --limit 500Injection emits ordered {seq,at,line} rows, where at is epoch milliseconds;
internal after advances with seq. Follow limit is 1–2000, default 500. JSON is
one-shot and JSONL requires follow. Observation does not enable capture. Empty
polls do not identify disabled capture or prove absence of gaps. Detectable runtime
drift stops; undetectable restart/latest-N gaps cannot be excluded without an API
epoch/gap marker.
Both follow loops use serial one-second waits, 10-second fetch/body deadlines and 32 MiB response limits. Malformed/oversized/transport errors stop with stderr and exit 1, without automatic retry/reconnect. Reduce limit for oversized windows. SIGINT/Ctrl-C exits 130, SIGTERM 143, with no later polls/output. Inspect exit state and retained rows instead of treating cancellation as complete history.
Companion timeline and key-scoped usage
Section titled “Companion timeline and key-scoped usage”ocx companion timeline --helpocx companion timeline --hours 24 --bucket-minutes 60 --metric total --aggregation sum --grouping model --model example/model-a --hide-provider excluded-provider --jsonReplace fictional IDs with the selected filters. Repeat --model for individual
provider/model IDs (nested slashes allowed; not CSV); repeat --hide-provider to
exclude providers. Positive --provider is unsupported. Hours are 6/24/72/168,
bucket minutes 1–1440 with at most 2000 buckets, metric total/input/output/cached,
aggregation sum/average/max, grouping model/modelAccount. The API limits filter
inputs to 100 items. This reads usage without changing companion settings.
Check appliedFilters.models/hiddenProviders. Timeline bounds are epoch seconds,
with exclusive end, unlike ordinary usage’s millisecond custom window. The end must
match the request-time bucket, or its immediate successor if the request crosses
a bucket boundary; an older aligned window is refused. Empty
series retains bucket/filter metadata. missingMeasurements and truncated must
remain visible: zero-filled points do not prove complete zero usage.
On a non-client management host:
ocx access key list --jsonocx usage --api-key-id key-example --range 7d --jsonUse a non-secret actual key ID. The CLI requires exact response acknowledgment in
filter.apiKeyId; ignored filters fail rather than showing unscoped totals.
An unknown acknowledged ID can return matched:false and empty traffic, not 404.
Keep incomplete/custom-window facts. Connected clients reject --api-key-id
before enrolled-key access or transport; omit it for existing self-only Hub usage
or perform the selected-key view on the Hub. No data key grants management authority.
ocx debug <provider|usage|injection|claude> <on|off|status|reset|logs [-f]>
Section titled “ocx debug <provider|usage|injection|claude> <on|off|status|reset|logs [-f]>”Read or change runtime debug overrides through the running proxy’s management API.
ocx debug provider on|off|status|resetocx debug provider logs [-f|--follow]ocx debug usage on|off|status|resetocx debug usage logs [-f|--follow]With no scope, ocx debug prints usage and, when the proxy is stopped, the next-start environment
defaults. Provider debug defaults from OCX_DEBUG=1 (legacy OCX_DEBUG_FRAMES=1 also works); usage
debug defaults from OPENCODEX_USAGE_DEBUG=1.
API access
Section titled “API access”ocx access <key|endpoints|models|test|audio> ...
Section titled “ocx access <key|endpoints|models|test|audio> ...”Inspect admission keys, external endpoints and models with the access family.
ocx api-key aliases the access-key family. Creation and rotation-start return a
one-time plaintext credential in text and JSON output. Agents must leave those
steps to a human-operated terminal outside the agent session; request only
confirmation and non-secret key/rotation IDs, never the credential.
ocx access key list --jsonAfter the human configures and verifies the replacement, committing its rotation
or removing the old key requires separate explicit revocation authority. Safe
non-secret follow-ups are ocx access key rotate commit <id> <rotation-id> --json
and ocx access key rotate abort <id> <rotation-id> --json, with authority for
the chosen action. Re-list afterward. Missing pending state alone does not prove
commit: expiry or abort can also clear it. Do not route around consent by issuing
the secret-returning management request directly.
Rename one key without changing its access policy
Section titled “Rename one key without changing its access policy”ocx access key rename key-example 'Research client' --jsonocx access key list --jsonUse an actual unique ID or unambiguous name. Rename sends only {id,name} and
preserves provider/model scopes; it does not rotate/delete a key. The response
contains id/name/createdAt and optional allowedProviders/allowedModels, never
plaintext or a prefix. List remains masked. Names are control-free, trimmed,
nonempty and at most 64 JavaScript string units. The read/rename sequence is not
CAS; inspect the masked roster after an unknown outcome before retrying. The
root api-key rename alias uses the same command.
Explicit-key model and audio checks
Section titled “Explicit-key model and audio checks”Discover the installed syntax without contacting upstream:
ocx access test --helpocx access audio transcribe --helpocx access audio live-check --helpModel requests, audio uploads and live-session checks require explicit operator authorization for that particular upstream operation and possible quota/cost. The operator supplies the selected key from an approved private stdin source in a human-operated terminal outside the agent session. Agents must not capture it or ask for it in chat. Never put it in argv/environment. These are the ocx side of that private pipe, not direct interactive key prompts or an agent-run batch:
ocx access test example/model --protocol responses --api-key-stdin --jsonocx access audio transcribe sample.wav --model gpt-4o-mini-transcribe --api-key-stdin --jsonocx access audio live-check --model gpt-live-1-codex --api-key-stdin --jsonChoose only the authorized task and real model/file. TTY input is refused. Input
is bounded to 4096 bytes/30 seconds, valid UTF-8 printable ASCII, without outer
whitespace, controls or extra lines; one final LF/CRLF is allowed. This deliberately
covers currently issued keys, not every Unicode value the server configuration
might accept. Exact supplied-key occurrences in permitted text become [redacted];
arbitrary encodings are not guaranteed detected. No encoded key carrier is printed.
Targets are the checked local serving origin or existing normalized enrolled Hub origin, with identity checked around asynchronous work. There is no custom-origin, admin or enrolled-key fallback, redirect following, credential cache or automatic retry. The operator reports only the non-secret result to the agent.
Model control and response limits
Section titled “Model control and response limits”Protocols are chat (default), responses or messages. Selected-key mode first sends one credentialless malformed-JSON control to that endpoint. Only the native key-required 401 advances to one fixed 16-token model request using the supplied key. The control has a 5-second/4096-byte response budget; the request has a 60-second/2 MiB response budget including body reads. Authless/unrecognized controls stop before inference. Local logging/admission bookkeeping may still occur.
JSON is {schemaVersion:1,control:{outcome,status?},request:{outcome,status?},response?}.
Safe response contains protocol, ordered text, complete/limited completion and
optional measured token counts. A usable length-limited reply is limited;
refusal/content-filter/tool-only or malformed responses are unsupported, even
with HTTP 2xx. Error metadata, IDs, tools and reasoning are not printed.
Operational failure retains one versioned report plus fixed stderr/exit 1;
invalid grammar/key input exits 2 without a fabricated report.
Success says only: “Credentialless request was refused; the model request using
the supplied key succeeded.” Listener/policy changes between calls remain possible;
this does not certify key scope, atomic admission or billing identity. Without
--api-key-stdin, legacy test JSON remains its original payload and says nothing
about a newly selected key.
Transcription and live readiness
Section titled “Transcription and live readiness”Transcription requires a nonempty regular file of at most 25,000,000 bytes with a
30-second local read limit, and a multipart body capped at 32 MiB. Models are
gpt-4o-transcribe, gpt-4o-mini-transcribe or whisper-1, subject to target support.
Upload/response share 130 seconds; response is capped at 2 MiB. Success returns
only {text}, including empty text, with exact-key redaction. Failure leaves
stdout empty and prints fixed stderr/nonzero; no JSON error envelope or raw body.
Audio uses explicit-key admission without the model control. Live-check sends fixed session.update and session.close only. Readiness requires session.started or session.updated with nonblank native session ID within 15 seconds; socket-open or session.created alone is insufficient. After readiness it waits at most 2 seconds for normal code-1000 closure. Each UTF-8 frame is capped at 64 KiB, aggregate 2 MiB; there is no retained frame history.
Live JSON is {schemaVersion:1,ready,close:"confirmed"|"unverified",check:"session-readiness",event?}.
Operational failure preserves that observation without raw frames. Partial readiness
with unverified close exits 1; a later normal close cannot erase an earlier error.
Signals exit 130/143. This checks readiness/closure only, not microphone, upload,
tool execution, full voice roundtrip or server lease release. Opening the upstream
session is not guaranteed free. No reconnect or retry is automatic.
ocx api <protocols|explain|policy> ...
Section titled “ocx api <protocols|explain|policy> ...”Inspect and set how requests travel between the client APIs and provider wires. See Protocol paths for the vocabulary.
| Command | Route | Changes state |
|---|---|---|
ocx api protocols [--provider <name>] [--json] |
GET /api/protocols |
No |
ocx api explain --model <id> --inbound <responses|chat|messages> [--feature <key>]... [--json] |
POST /api/protocols/plan |
No |
ocx api policy [--json] |
GET /api/protocols |
No |
ocx api policy [--messages <on|off>] [--unrepresentable <legacy|reject>] [--rollout <switch>=<on|off>]... [--json] |
PATCH /api/protocols/settings |
Yes |
protocolsprints the contract version, whether each client API is served and why, the unrepresentable policy, every rollout switch, and the policy revision.--provideradds the upstream wire that provider receives, who decided it, and the models on another wire.explainpreviews the path a model would take from one client API.--featureis repeatable and accepts a comma-separated list;ocx api protocols --jsonlists the known feature keys. The preview is computed from configuration: nothing is sent upstream, no combo rotation advances, and the input is not logged.policywithout a setting flag only reads. With one it sends a single change to the running proxy, which validates it, saves the configuration, and answers with the new policy.--messages offalso turns the Claude integration off, as the dashboard toggle does. Switch names and combinations are validated by the proxy; for example--rollout managedMessagesNativeOAuth=onis refused unlessmanagedMessagesNativeis already on or turned on in the same command.
ocx api explain --model combo/main --inbound chat --feature request.seed,request.toolsocx api policy --rollout shadowPlan=onUsage errors exit 2 before any request is sent. --json prints the management API body as is.
Client integrations
Section titled “Client integrations”Basic integration commands
Section titled “Basic integration commands”| Command | Action |
|---|---|
ocx integration client status [--client <id>] [--profile <id>] [--json] |
Read all managed file integrations, one client, or Aside profiles. show and list alias status. |
ocx integration client history [--client <id>] [--profile <id>] [--json] |
Read rollback operations and snapshot availability. journal aliases history. |
ocx integration client enable --client <id> [--profile <id>] [--overwrite-conflict] [--json] |
Apply the managed file integration. Overwriting a conflicting block requires the explicit flag. |
ocx integration client disable --client <id> [--profile <id>] [--json] |
Remove the selected managed integration through its runtime owner. |
ocx integration client restore --op <opId> [--client aside --profile <id>] [--confirm-drift] [--json] |
Restore a recorded operation; replacing later edits requires explicit drift confirmation. |
ocx integration native [list] [--json] |
Read native integration state. |
ocx integration native <claude|claude-desktop|codex|grok> <on|off> [--json] |
Write the selected native client’s configuration through its runtime owner. |
These commands require a running proxy. --profile selects a nonnegative Aside account ID and
requires --client aside; omitted profiles select the aggregate for reads and all profiles for
unbound enable/disable. Native toggles change client configuration; Cursor has separate read-only
inspection commands below. For preview and bound-write options, continue with the recipes below.
Preview and recover managed file integrations
Section titled “Preview and recover managed file integrations”ocx integration client preview --client hermes --operation apply --jsonocx integration client restore --op op-example --preview --jsonop-example is fictional; use an ID from history. Preview operations are apply,
overwrite and disable; restore uses --preview on its existing command. Review
structural changes and canApply/willChange; valid refusal/no-op exits 0 without
applying. Enable/disable/restore accept optional --plan-fingerprint for an
explicit bound commit. Direct legacy writes remain available. Aside preview or
bound writes require --client aside --profile N. Drift confirmation and overwrite
are never automatic; stale binding exits 5 with empty stdout and a re-preview
instruction on stderr. Follow the complete preview/commit and drift recipes.
Droid apply/overwrite supports repeated --reasoning-default MODEL=EFFORT for
full map replacement, or exclusive --clear-reasoning-defaults for {}. Omission
preserves the map. Repeat the exact map in preview and commit; see
Droid defaults.
History removal is irreversible and requires an exact opId plus --yes:
ocx integration client history remove --op op-example --yes --json addresses the
global journal. Only --client aside and optional --profile N provide narrower
delete scopes. The newest row is protected. snapshotRemoved:false exits 1 after
retirement with cleanup incomplete; do not retry deletion or claim rollback.
ocx integration client sync --client aside --json refreshes eligible profiles
through the attested owner, with no profile selector or local fallback. Empty
results is successful observation of no eligible profiles; a failed row makes
the aggregate nonzero while preserving other successes. Read status and recovery
facts before retrying; Aside controls
explain profile intent versus file state.
Inspect Cursor without installing it
Section titled “Inspect Cursor without installing it”ocx integration native cursor status --jsonocx integration native cursor local-installer --jsonStatus can gather model inventory; installer lookup may fetch a public manifest.
They do not download/install or toggle Cursor. Status distinguishes credential
from placeholder gateway mode; the placeholder is not an access credential.
Installer {available:false,url:null,version:null,reason:null} is valid, including
when Private Inference is already installed. A valid unavailable read exits 0.
ocx integration <claude|grok> ...
Section titled “ocx integration <claude|grok> ...”Manage supported Claude and Grok integrations. The direct command families below expose their client-specific controls.
ocx claude [claude args...]
Section titled “ocx claude [claude args...]”Ensure the proxy is running, then launch Claude Code with ANTHROPIC_BASE_URL,
ANTHROPIC_AUTH_TOKEN, CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1, and model slots from
config.claudeCode. Routed models appear in the native /model picker through stable slot aliases
with Claude Code 2.1.129 or newer. On older versions, select with ANTHROPIC_MODEL or /model <id>.
User-exported ANTHROPIC_* variables always take precedence.
Claude Desktop profile commands are:
ocx claude desktop [apply] Save and apply the four-family profileocx claude desktop show [--json] Show routes, families, and defaultsocx claude desktop status [--json] Show applied state, drift, and healthocx claude desktop move <route> <family> [--default]ocx claude desktop default <family> <route|none>ocx claude desktop export <path|-> Export versioned JSON (`-` = stdout)ocx claude desktop import <path> [--apply] Validate and import JSONThe families are opus, fable, sonnet, and haiku; new routes start in opus. none is valid
only when that family is empty. Legacy apply flags --static, --hybrid, and --discovery-only
remain supported. Use ocx claude config <status|set> ... for Claude Code settings.
Read or save the selected runtime’s Desktop profile
Section titled “Read or save the selected runtime’s Desktop profile”The existing show/import commands above are local. The profile family targets
the running management runtime and can gather model inventory:
ocx claude desktop profile show --json > desktop-observed.jsonjq '.profile' desktop-observed.json > desktop-profile.jsonEdit/review the versioned profile, preserving server-owned applied markers. For an authorized save, then read-back:
ocx claude desktop profile import desktop-profile.json --jsonocx claude desktop profile show --jsonImport accepts the profile itself, not the outer {profile,models,rendered,port}
response, using bounded regular JSON files or explicit stdin - (4 MiB/30 seconds).
It returns those observed fields plus ok:true, meaning saved only. --apply and
native-mode flags are rejected; failed runtime save has no local fallback. Apply
is a separate existing Desktop action on its machine, so verify host/context
before choosing it. Rendered models are not proof of native application.
ocx codex [codex args...]
Section titled “ocx codex [codex args...]”The key is supplied only when the configuration and its namespaces are protected from other principals; the current user and privileged OS authorities are trusted. Same-user processes are trusted: an actor with your write access can already read your OpenCodex key file. Same-user configuration replacement between verification and native startup is outside this threat model; the launcher does not freeze configuration at handoff.
On a normal Windows installation, default ProgramData permissions allow other users to create directories. Automatic credentials are therefore withheld even when ProgramData\OpenAI\Codex is absent. The system Codex configuration folder under ProgramData must exist and be writable only by Administrators/SYSTEM, and its ancestors must prevent replacement by other users. Ask an administrator to review the directory policy. opencodex never changes ACLs itself and provides no provisioning command.
Alternatively, supply the key yourself, for example by exporting OPENCODEX_API_AUTH_TOKEN; ocx codex leaves it untouched. Existing system configuration files still withhold automatic credentials and require separate review. Each withholding reason produces one short, specific stderr diagnostic without key values, key-file contents or key-file paths.
Use -- before a single-word prompt so it cannot select an unknown Codex subcommand.
The machine configuration namespace must also prevent other users from creating missing system files. An unprotected Windows ProgramData/OpenAI/Codex namespace withholds automatic credentials; the launcher does not create it. macOS accepts deny-only and read-only allow ACLs, but refuses any allow entry granting write, append, delete, attribute/security changes or ownership changes, even after a deny entry. Unknown tags and inspection errors refuse.
A fresh service token is loaded only when argv is within the allowlist below, the environment has no nonempty HTTP(S)/ALL proxy or CODEX_*/OPENAI_*/AZURE_OPENAI_* overrides (canonical CODEX_HOME is allowed), and the home/config/system namespaces pass ownership checks. The configuration must contain only audited keys and the exact managed loopback provider, with no additional credential consumers or configuration layers. Every unsupported argument, including -c/--config, -p/--profile, unknown flags and resume/fork, withholds the token with a value-free diagnostic; explicit user credentials and original arguments are preserved.
The canonical home directory and config.toml must belong to the current user. POSIX denies group/other writes; Windows checks owner SID and rejects DACL write grants outside the current user, SYSTEM and Administrators. Ancestor replacement permissions are checked too. macOS additionally requires no forced Codex configuration preferences. These checks exclude other-user writers; they do not isolate a malicious process running as the same user or an administrator.
| Allowlist | Flags |
|---|---|
| Switches | --no-daemon, --json, --ephemeral, --skip-git-repo-check, --no-alt-screen, --full-auto, --dangerously-bypass-approvals-and-sandbox, --search |
| One value | --model/-m, --sandbox/-s, --ask-for-approval/-a, --image/-i |
Automatic credential delivery resolves CODEX_HOME as a literal path (including ~ and whitespace), verifies that home, and passes its canonical absolute path to the child. An unreadable home skips loading. Any nonempty HTTP_PROXY, HTTPS_PROXY, or ALL_PROXY variable, in any letter case, also skips loading regardless of NO_PROXY; denied launches and user-exported credentials remain unchanged. With a newly loaded token, both child NO_PROXY and no_proxy include 127.0.0.1 and ::1, preserving existing bypass entries. Enabling features.respect_system_proxy or forwarding --enable/--disable skips automatic loading.
Ensure the proxy is running, then launch Codex with the original arguments. Routing remains in Codex configuration; the launcher never rewrites it. Native and foreign routes skip startup. Unknown routing warns and attempts startup; a failed startup warns and continues. Help/version and internal commands such as login, doctor, and help skip startup and automatic token loading.
A missing OPENCODEX_API_AUTH_TOKEN is read from this installation’s service-api-token only when the selected provider’s complete transport configuration matches the managed block for the configured loopback listener or persisted local client connection. Names and injection comments alone grant no credential access. Unknown or remote destinations, default profiles, project configuration, OPENAI_BASE_URL, and forwarded -c/--config, -p/--profile, -C/--cd, or --remote options skip automatic loading. User-exported credentials and arguments are preserved; token-file overrides cannot select a different credential, and management-token collisions are refused.
Only a matched autostart wrapper launches its backing Codex directly. Unknown state, including an inspection exception, requires a verified bypass; Windows CMD managed wrappers must match the complete current generated template before the selected absolute command runs with OCX_SHIM_BYPASS=1. Ordinary npm launchers remain supported. Unverifiable or obsolete wrappers refuse with exit 1 and start no Codex; run ocx codex-shim install to refresh them. This launch does not repair shims. The content check does not establish Windows backing-file provenance or prevent concurrent pathname replacement.
On macOS, every launch, including help/version, verifies the selected executable when its selected path or canonical location is inside any .app bundle. Renamed bundles and symlinks into bundles require the same safe ownership, permissions and OpenAI signatures for the bundle and executable. A selected bundle member must stay inside that bundle’s canonical Contents/, including through executable, directory or whole-bundle symlinks. Failed verification exits 1 without starting Codex. Ordinary non-bundle executables, including npm installations, retain their behavior.
Use ocx help codex for launcher help and ocx codex --help for Codex help. Launching plain codex later retains its existing behavior.
ocx opencode [opencode args...]
Section titled “ocx opencode [opencode args...]”Ensure the proxy is running, then launch opencode with the generated provider.opencodex and
providers.opencodex blocks in OpenCode’s inline runtime layer (OPENCODE_CONFIG_CONTENT). The
legacy block keeps V1 clients working with variant maps; the V2 block carries native arrays
for the same reasoning-effort choices and defaults. Existing inline config is preserved and only those two keys are replaced
for this launch. Global or project opencode.json files may be read to warn about an existing
override, but on-disk files are never modified. Routed models appear as
opencodex/<provider>/<model>. Launching plain opencode later behaves exactly as before.
ocx grok <status|exclude|include|set|clear|apply> ...
Section titled “ocx grok <status|exclude|include|set|clear|apply> ...”Manage and apply the Grok Build model fence.
Client config export
Section titled “Client config export”Hermes and Command Code export and integration apply/overwrite accept
--model-names alias|routed (JSON API field: modelNames). Omission on export
means routed; omission on a later integration Apply preserves its stored mode.
This is independent of preferModelAliasIds. Only a provider-qualified alias
that routes to the same provider/model is emitted; unsafe, missing or colliding
aliases fall back to routed names, and combos keep their existing keys.
ocx export --client hermes --model-names alias --json previews an existing
current catalog without writing client files or managed state. A cold/stale
catalog returns unavailable; load the catalog separately and retry. Explicit
--out writes only the requested export artifact and retains its existing
exclusive-create/--force behavior. For managed writes, pass the same mode to
both integration client preview --operation apply|overwrite and enable when
confirming a plan. The field is unsupported on disable/restore and other clients.
An alias change during Apply or refresh can cause a conflict before any write;
retry against the current catalog. Removed/renamed aliases migrate at the next successful refresh, with foreign-edit
refusal. See the integration guide.
ocx export --client <opencode|pi|omp|hermes|openclaw|kimi|gajae|dsh|mcode|zcode|prime|aside|raycast|omo|cline|kilo|commandcode|droid>
Section titled “ocx export --client <opencode|pi|omp|hermes|openclaw|kimi|gajae|dsh|mcode|zcode|prime|aside|raycast|omo|cline|kilo|commandcode|droid>”Print a client config wired to the running proxy. The command serializes the
opencodex provider block — base URL, model list, and the client’s credential
reference or loopback placeholder — in the selected client’s native format.
The proxy must be running; the command resolves its live port, uses the current
catalog (/api/models or the server-side client export), and emits only
models Codex can currently see.
OpenCode and Kilo exports preserve effective model limits, known capabilities, declared reasoning choices and defaults, including metadata inherited by custom rows. Explicit overrides still win; unknown capabilities and defaults are not invented. The OpenCode launcher uses the same metadata. See client integrations for managed refresh and upgrade behavior.
| Flag | Action |
|---|---|
--client <opencode|pi|omp|hermes|openclaw|kimi|gajae|dsh|mcode|zcode|prime|aside|raycast|omo|cline|kilo|commandcode|droid> |
Required. Selects the client config dialect. |
--json |
Print the generated document as JSON on stdout for scripts. This is JSON even when the selected client’s native format is YAML, TOML, or JSON5. |
--out <path> |
Write the client’s native config format to <path>. Refuses to replace an existing file. |
--force |
Allow --out to replace an existing file. |
ocx export --client opencode # config plus destination, merge warning, and countsocx export --client pi --json > pi-models.json # JSON document for a pipe or a diffocx export --client omp --out ./omp-models.yml # native OMP YAMLocx export --client opencode --out ~/opencodex-opencode.jsonWithout --json the generated config leads, then the canonical destination path, the merge warning, the env
export line where the client has one, and a model count with how many rows omit context limits (the
client applies its own defaults for those).
| Client | Canonical destination | Download filename | Env var |
|---|---|---|---|
opencode |
~/.config/opencode/opencode.json (XDG_CONFIG_HOME wins when set) |
opencode.json |
OPENCODEX_OPENCODE_API_KEY |
pi |
~/.pi/agent/models.json (PI_CODING_AGENT_DIR wins when set; a relative value is refused) |
pi-models.json |
none — the block carries the literal opencodex-loopback |
omp |
~/.omp/agent/models.yml (OMP_PROFILE wins over PI_PROFILE, even when empty; named profiles use the home-relative PI_CONFIG_DIR directory name and ignore PI_CODING_AGENT_DIR, while the default profile lets PI_CODING_AGENT_DIR win) |
omp-models.yaml |
none — loopback placeholder |
hermes |
~/.hermes/config.yaml |
hermes-config.yaml |
OPENCODEX_HERMES_API_KEY |
openclaw |
~/.openclaw/openclaw.json |
openclaw.json5 |
OPENCODEX_OPENCLAW_API_KEY |
kimi |
~/.kimi-code/config.toml |
kimi-config.toml |
none — loopback placeholder |
gajae |
~/.gjc/agent/models.yml |
gajae-models.yaml |
non-secret loopback placeholder |
dsh |
$DSH_HOME/settings.yaml (default ~/.dsh/settings.yaml) |
settings.yaml |
none — non-secret loopback bearer placeholder |
mcode |
~/.minimax/config.yaml (MINIMAX_DATA_DIR, then the legacy MAVIS_DATA_DIR, win when set; a relative value is refused) |
mcode-config.yaml |
none — loopback placeholder |
zcode |
~/.zcode/v2/config.json (dataBaseDir in the default-home setting.json relocates the root; ZCODE_DATA_DIR wins when set; relative values are refused) |
config.json |
none — loopback placeholder |
prime |
~/.prime/agent/models.json (PRIME_AGENT_CODING_AGENT_DIR wins when set; a relative value is refused) |
prime-models.json |
none — loopback placeholder |
aside |
~/.aside/u/<account>/models.json for the account Aside’s own accounts.json names as current; an unreadable manifest is refused rather than defaulting to an account |
aside-models.json |
none — loopback placeholder |
raycast |
~/.config/raycast/ai/providers.yaml on macOS and Windows alike (Raycast does not honor XDG_CONFIG_HOME) |
raycast-providers.yaml |
none — loopback only, no api_keys entry is written |
omo |
~/.omo/agent/models.json (OMO_CODING_AGENT_DIR, then SENPI_CODING_AGENT_DIR, then PI_CODING_AGENT_DIR win in that order when set; a relative value is refused) |
omo-models.json |
none — loopback placeholder |
kilo |
first existing kilo.jsonc, kilo.json, opencode.jsonc, opencode.json, or config.json under ~/.config/kilo (XDG_CONFIG_HOME relocates that directory); uses kilo.jsonc when none exists |
kilo.jsonc |
OPENCODEX_KILO_API_KEY |
commandcode |
~/.commandcode/providers.json (on Windows with the default home: use HOME ?? USERPROFILE only if nonblank and Windows-absolute, otherwise homedir(); a separately supplied home is preserved; append .commandcode\providers.json) |
providers.json |
loopback only; apiKey: false; no environment variable |
droid |
~/.factory/settings.json (%USERPROFILE%\.factory\settings.json on Windows) |
factory-settings.json |
loopback only; no environment variable |
The managed DSH export requires DSH 0.1.0-rc.6 or newer and owns only
llm-pi-ai.providers.opencodex. DSH hot reloads that provider; the user’s default model and
deepseek-official remain untouched. This export is loopback-only and carries no real credential.
DSH 0.1.7 and newer import settings.yaml once into the first profile that boots and then rename
it, so the dashboard integration writes the same provider into the llm-pi-ai row of the Desktop
profile’s $DSH_HOME/profiles/desktop/cordis.patch.yml once that profile exists.
opencode interpolates {env:OPENCODEX_OPENCODE_API_KEY}. The generated Pi and OMP exports do
not require an environment variable: each carries the literal opencodex-loopback placeholder.
This is load-bearing because both clients resolve apiKey while building their model lists and
hide the whole provider when an existing config contains an unset env reference. The proxy never
checks the generated placeholder on loopback. OMP supports provider-level headers, but this initial
integration deliberately remains loopback-only; remote x-opencodex-api-key wiring is deferred.
The Raycast export is a standalone providers.yaml document with one id: opencodex element
in the providers sequence: name: OpenCodex, the proxy’s /v1 base URL, and every routed model
with its abilities (tools and system_message always supported, vision from the catalog’s
input modalities, reasoning_effort when the model has an effort ladder, temperature off for
reasoning models). Custom Providers is a Raycast Pro feature, and Raycast watches the file, so a
saved change takes effect without a restart. The format is documented at
manual.raycast.com/ai/custom-providers. No
api_keys entry is written, so this export is loopback-only and a non-loopback bind is refused.
The MCode, ZCode and Prime exports are loopback-only for the same reason and likewise carry the
opencodex-loopback placeholder rather than a real credential. Prime Agent reads the same
models.json contract Pi does, so the two exports produce the same document; only the destination
differs. A relative path in any of those three environment overrides is refused, because the proxy
and the client can have different working directories and would otherwise disagree about which
file is meant.
ZCode 3.8.1 may save runtime-derived reasoning, limit.output, and default context metadata back
into the generated provider.opencodex.models entries. Managed integration status treats only
those documented additions as refreshable drift. Provider identity and connection settings,
including options.baseURL, model membership, names, modalities, and any context limit OpenCodex
emitted authoritatively remain protected; editing them reports conflict / foreign-edit instead of
overwriting the file. An ownership record created by an older OpenCodex version can recover
automatically when the generated catalog is otherwise unchanged. If both the catalog and the block
changed, re-apply only after reviewing the file because the older record cannot prove which change
was ZCode-derived.
No key is ever serialized. Configs carry either a documented environment reference or a
non-secret loopback placeholder. A loopback address (127.0.0.1) alone does not establish keyless
admission: check the target policy and endpoint. Selected-key model/audio commands
still require explicit key input on loopback. Set a referenced variable only when the client schema supports it and
the proxy binds beyond loopback; see
Remote access for how admission keys are issued. Keys for
the upstream providers themselves are a separate thing entirely, configured per
Providers.
The generated gjc integration uses a non-secret loopback placeholder and needs no environment variable. It remains loopback-only; it does not configure remote admission credentials.
The same payload is served by GET /api/client-config and rendered on the dashboard’s API tab, so
the CLI, the API, and the GUI use the same bytes.
Runtime and configuration
Section titled “Runtime and configuration”ocx system <status|settings|startup|diagnostics|sync|codex-app-server|codex-restart|update|codex-cli-update> ...
Section titled “ocx system <status|settings|startup|diagnostics|sync|codex-app-server|codex-restart|update|codex-cli-update> ...”Manage headless runtime settings, startup, sync, diagnostics, and updates.
ocx system codex-restart --yes restarts Codex app-servers through the same module as
ocx sync --restart-codex. It quits and relaunches the Codex desktop app when the app launched before the current model catalog was written or this request changed
its model_catalog_json binding, because the model picker is built at
launch. Otherwise the app stays open, respawns its own app-server, and keeps unsaved drafts and
pending approvals. If the app or catalog state cannot be read, it takes the full restart. When
the proxy itself is running inside the Codex app, the desktop restart refuses with an actionable
message instead of promising a handoff it cannot complete.
A model_catalog_json binding changed by this request also forces the desktop restart, even when the shell started after the catalog file was written.
ocx system settings --stream-mode eager-relayAdditional system booleans take on/off: --show-codex-credits, --account-picker,
--main-account-hard-lock, --ultra-fast-tier, and --fast-rows. They write only
explicit fields and may combine with existing system options. Showing credits is
a display preference, not paid-credit opt-in; system Ultra Fast is separate from
provider Fast.
Ultra Fast is an opt-in setting, default off. With --ultra-fast-tier on, the
generated catalog adds the Ultrafast speed choice to native gpt-6-astra and
gpt-6.1-sol (including account-bound rows), so the Codex picker offers it next to
Fast. Ultrafast requires an eligible ChatGPT plan; the catalog cannot check that,
so turn the setting on only if your plan includes it. Other models and the default
speed are unchanged.
For routed models, sync and catalog convergence retain an existing routed
row’s operator-supplied ultrafast entries in service_tiers and
additional_speed_tiers alongside its current Fast capability. Declarations belong
to the exact provider/model slug; they are not copied to other models. The setting
does not create missing declarations or restore removed models. Turning it off
removes Ultra Fast from ordinary routed rows and the generated native choice on the
next catalog regeneration.
The proxy’s Fast mode decides what reaches the backend: when it is unset, a selected
Ultrafast request is forwarded as service_tier: "ultrafast"; fastMode: true
replaces any tier with Fast (priority), and fastMode: false removes the tier.
Leave Fast mode unset to use Ultrafast.
ocx system settings --jsonocx system settings --show-codex-credits on --jsonocx system settings --jsonNew-option writes report {ok:true, settings: observedFields, catalogRefreshPending}.
Ultra Fast performs same-target GET read-back because PUT omits that value. A
missing/mismatched/read-failed observation stays verification:"unverified" with
unverifiedFields and a nonzero exit after acceptance; requested values are never
substituted for observations. Combined desktop switches retain stored/effective
and apply facts. Pending catalog or deferred/refused native apply is distinct from
a saved setting. False pending is not proof that every client has reloaded.
ocx system update updates OpenCodex itself. The separate Codex CLI inspection surface is:
ocx system codex-cli-update check --jsoncheck makes no package-registry request and inspects bounded configured-candidate provenance evidence,
including a redacted executable location and ownership evidence. Trusted published-launcher context authenticates
the candidate snapshot, not successful Codex execution. On POSIX, selection is attested only when the runtime
resolver selects the same canonical environment candidate without executing it. A linked npm-global manifest
can then establish managed: true when it proves ownership and, if a candidate version is reported, that version matches the manifest; persisted candidates remain unattested. The JSON report exposes candidateAvailable, candidateVersion, candidateSource,
and selectionAttested. Inspecting the configured candidate requires a trusted published-launcher context;
a direct Bun/source launch has no such proof, ignores ambient and persisted candidate state, and may report
candidate_unavailable on POSIX. On Windows x64, a proof-captured absolute standard npm codex.cmd
can be managed when held local handles bind its package, a prefix-local Node/npm pair or the captured
PATH metadata pair tied to the launcher architecture, and the first in-prefix platform backing.
This metadata pair does not attest the interpreter a later CMD invocation would select.
Plan paths and configured version-manager roots must use their canonical long DOS names;
aliases, unavailable roots and reparse points leave the installation unmanaged. Other Windows layouts remain deferred or unmanaged. Windows never consults persisted state, so a run
with no captured environment candidate reports windows_inspection_deferred rather than candidate_unavailable:
the command cannot observe whether a Codex CLI is installed, so it reports the deferral instead of asserting
that no candidate exists. The command does not execute Codex or a package manager, repair a shim,
write configuration or cache state, stop a process, or install anything. App-bundled, recognized
version-manager, unverified standalone, and ambiguous shim states are reported as unmanaged or unknown
and are never classified as managed.
On Windows, a captured bare command such as CODEX_CLI_PATH=codex, a remote path, or a device path reports candidate_path_unavailable instead. Those cases have a captured candidate; its path is not eligible for this inspection.
Read-only Codex CLI update plan
Section titled “Read-only Codex CLI update plan”ocx system codex-cli-update plan --channel latest --jsonRun through the published Node launcher with the intended CODEX_CLI_PATH in the shell environment.
The plan requires an attested npm-global installation and a linked package manifest version.
Windows supports only an explicit absolute standard npm codex.cmd with a held-bound Node/npm toolchain —
prefix-local when present, otherwise the captured-PATH pair anchored to the launcher architecture;
PATH-only selection, OpenCodex autostart wrappers and global/vendor fallback stay deferred.
It queries the official npm registry for an exact version, SHA-512 integrity and same-origin tarball,
using the launcher’s captured PATH and isolated temporary npm configuration, cache and logs. Proxy
settings and NODE_EXTRA_CA_CERTS remain supported; cleanup is best-effort. No Codex command runs.
An applicable plan reports applicable: true and a deterministic planId binding platform,
installation-root/content digests, installed version, channel and exact main/platform artifacts. The plan is never
persisted. It refuses downgrades, already-current versions, active Codex sessions and incomplete
process observation. Supported Windows metadata queries use the observed Node/npm under matching
held handles. Windows x64 can be applicable only for a bounded npm prefix with verified
write authority; other observed prefixes retain windows_apply_disabled. Active/unknown sessions still refuse earlier. Unsupported
Windows layouts return windows_inspection_deferred before registry/process queries.
A refusal exits 0: inspect applicable and refusal. The printed install argv is indicative; this
command installs nothing, changes no application state and never signals a session.
A plan ID alone is not installation authorization: apply requires separate explicit confirmation.
Confirmed Codex CLI apply and job status
Section titled “Confirmed Codex CLI apply and job status”ocx system codex-cli-update apply --plan-id <32-hex> --yes --request-id <stable-key> --jsonocx system codex-cli-update status <job-id> --jsonApply supports the selected, managed, non-shim npm-global CLI on Linux/macOS and the restricted
Windows x64 npm layout. It revalidates the
approved plan under an installation lease, verifies the exact main/platform archives, installs them
offline with lifecycle scripts disabled, and checks installed files and the selected CLI’s version.
Existing Codex sessions are never stopped; active or unknown process observations refuse the update.
Windows supports shared prefixes with verified ACLs and no reparse paths. Observation includes
unrelated packages and shims, capped at 4,096 entries, 512 MiB total and 384 MiB per file. Their
bytes and identities must be preserved. Larger or unsafe prefixes, ARM64, shim repair, native apps
and other installation managers remain unsupported. Unknown child lifetime or incomplete handle cleanup retains staging and
the installation lease; do not retry by deleting its lock. Readback includes auxiliary files,
new/absent backing roots and npm’s hidden lockfile. not_applied means scoped installation state
was observed unchanged, not that npm performed no I/O anywhere.
Installation directories and staging require trusted POSIX ownership and permissions throughout their
ancestry. Unsafe installation paths report installation_prefix_unsupported or
installation_paths_untrusted; unsafe temporary roots report staging_path_untrusted. Use a private
temporary directory below trusted ancestors (root-owned sticky temporary roots are supported).
Owned session starts, desktop restarts and runtime/shim selection changes report busy while installation
and readback run. An unconfirmed installer or verification child keeps admission closed. Admission
recovers when the owned process group is proven gone, including a verification child that closes after
its reap deadline. Worker loss before commit also restores admission; worker close after commit alone
does not. Durable recovery records preserve this exclusion across proxy restarts.
On Windows, recovery checks the exact installer/verifier Job and original process creation identity;
all Job members must have exited. Access failures keep admission closed and never stop an installer.
Missing child identity, partial records or inaccessible liveness evidence require inspection. A complete terminal write left
before its publication rename can restore admission after restart when its exact owner and current
parent/group absence are verified. On Windows, a complete pending child identity can also restore
admission when it matches the armed owner and Job, the guardian’s terminal proof is valid, and the
parent, exact child lifetime and every Job member are proven gone. Missing proof, incomplete or armed
pending writes still require inspection; guardian death alone cannot reopen admission.
Recovery does not change an
ambiguous job result, retry installation or reclaim an abandoned installation lease.
Without recovery history, a symlinked OPENCODEX_HOME (or home ancestor) permits these ordinary
operations. With history, admission reads the protected canonical home target; unsafe recovery
paths still report busy. This does not relax the updater’s installation or config-path eligibility.
Shim repair, native apps and other installation managers remain unsupported.
Apply exits 0 only for an applied job; not_applied, refused, ambiguous and pending duplicate jobs
exit 1, including with --json. Status reads the
same private job record without a running proxy or GUI token. Reuse the same optional request ID after
a lost response: the same key and plan return the original job; a changed plan with that key refuses.
The private ledger retains up to 64 jobs, including finished jobs, without automatic pruning. At that
limit, new request IDs are refused with store_full; existing matching retries still return their
original job. Capacity and operator recovery remain a separate follow-up that must preserve this
deduplication contract. A busy admission ledger reports job_store_busy (HTTP 503 with Retry-After: 1);
permanent admission failures have no retry-delay header. Missing or unreadable CLI
status returns job_unavailable and a nonzero exit. Completion persistence failures do not rerun the
installer or turn an uncertain job into a confirmed success.
An ambiguous result is never automatically retried or rolled back. After an owner restart, an unfinished
job reports unknown ownership instead of claiming the old process stopped. Inspect the job’s outcome,
child/lease state and cleanup errors; command exit status alone does not establish an installation result.
The management API provides authenticated plan/status reads and confirmed trusted-loopback GUI-session
apply admission. A published Node ocx start supplies the required inspection snapshot; direct Bun or
compiled sidecar startup does not provide that proof. The Dashboard update panel is a separate follow-up.
Explicit installation observation on Windows x64
Section titled “Explicit installation observation on Windows x64”ocx system codex-cli-update attest [--json]ocx system codex-cli-update attest --candidate <absolute-path> --npm-prefix <absolute-path> --npm-cli <absolute-path> --node <absolute-path> [--json]attest is an opt-in, read-only observation of a Windows x64 npm installation. With no options it identifies the selected candidate from the proof-bound launcher snapshot — the configured CODEX_CLI_PATH or the first codex on the captured PATH, with an OpenCodex wrapper resolving to its renamed codex.opencodex-real.cmd npm backing. Supplying all four absolute paths overrides discovery; discovery only proposes paths and the held-handle observation remains the authority. --candidate must name the standard npm <prefix>/codex.cmd or <prefix>/node_modules/@openai/codex/bin/codex.js. --npm-cli must end in node_modules/npm/bin/npm-cli.js; --node names an explicit node.exe. App bundles, recognized version-manager layouts, opencodex-owned shims without their npm backing, and custom wrappers are refused.
Native handles hold the ancestor directories and files during bounded reads. Unsupported platforms, reparse points/junctions, conflicting writers, unsafe paths, and oversized files are refused. The fixed report contains no paths: status is observed or refused, with installationIdentityObserved; selectionAttested, managed, and applyAllowed remain false. Check status, not just the process exit code: a reported refusal can exit 0.
An observed identity or digest describes those files during this observation. It is not a durable update permit and does not prove the selected runtime, the past installer, effective npm configuration, or tool authenticity. The supplied Node is observed only, not proven to be the Node a launcher would select. No target is executed; no registry request, installation, configuration write, or process control occurs. The separate Windows check/plan predicate above can establish read-only planning evidence; attest remains observation-only.
ocx config [show|get|set|unset|validate|export|import] ...
Section titled “ocx config [show|get|set|unset|validate|export|import] ...”ocx config [show] [--json] [--source] displays the local configuration without a running proxy. Omitting show also works with either flag or both, in either order. --source includes diagnostic source, error, and warning fields and is only accepted for display. --json may precede an explicit action; it does not change which action runs. Repeated --json or --source flags and unknown arguments are rejected.
Inspect and safely modify validated OpenCodex configuration. show and get mask secrets. Import
validates before writing and requires --yes.
Display and mutation output strip credentials from proxy URLs while retaining the host and port.
direct and credential-free proxy values stay readable. export preserves credentials so the
backup can restore the configuration; store exported files as secrets.
Usage from a connected client
Section titled “Usage from a connected client”ocx usage reads the connected hub with this client’s enrolled data key. Human output identifies the hub source and client-key scope; --json returns the same scoped data. Range, surface, provider/model filters and custom --since/--until bounds remain available. Account breakdowns and other clients’ records are not shared. An old or unavailable hub produces an explicit error instead of substituting local usage; upgrade the hub if it does not support this read.
The read-only data-plane endpoint is GET /v1/usage, using x-opencodex-api-key with a configured client key. Environment-wide and admin keys are refused. It accepts range, surface, provider, model, since, and until; unknown/repeated options and caller-selected key IDs are rejected. Oversized skipped rows retain the explicit incomplete-history warning.
Explain a listed request
Section titled “Explain a listed request”Human ocx logs output includes id=<request-id>. Pass that value to ocx logs explain <request-id> to inspect routing decisions. Rows without an ID or with control characters in their ID omit the field instead of displaying a different lookup key. JSON and JSONL output retain their existing schema.
Routing profile lookup status
Section titled “Routing profile lookup status”ocx route policy show <id> exits 4 when the profile does not exist. Missing or invalid command arguments exit 2. Scripts can distinguish a missing profile from incorrect usage.
Upstream error details
Section titled “Upstream error details”When an upstream error envelope contains several message fields, OpenCodex uses the first nonblank string in its established priority order. Empty or malformed fields no longer hide a valid fallback diagnostic.
Forced Claude Code subagent model
Section titled “Forced Claude Code subagent model”The Subagents page offers Force all subagents onto one model, off by default. Select an exposed roster-style id, such as combo/tev-auto, then enable the switch. The roster is offered first; unavailable saved roster entries cannot be force targets.
ocx agent subagents force combo/tev-auto sets claudeCode.subagentModelForce; ocx agent subagents force - clears it. ocx agent status reports the setting. GET /api/subagent-models returns force, forceAvailable, and forceStatus; PUT accepts { "force": "combo/tev-auto" } or { "force": null } without changing the roster. Omitting force leaves it unchanged. Invalid or unexposed targets are rejected on write; stale targets are reported and skipped at launch.
This takes effect on the next routed ocx claude launch, injecting CLAUDE_CODE_SUBAGENT_MODEL as an explicit proxy alias (with [1m] only for an authoritative million-token window; native Claude targets use a reversible native alias) and CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1. Each nonempty shell-exported variable independently wins. Native launches inject neither variable; plain claude is not affected. No plugin files or settings.json are modified by this setting.
Claude Code 2.1.257 or newer is required for FORCE. Plugin and built-in agents (including Explore/Plan) and per-call model arguments are overridden. Forks and subagent skills with model: inherit keep the main conversation model. The main loop and Haiku/small-fast sidecars are unaffected. Existing roster files remain available.
The dashboard warns about old or unknown CLI versions, unavailable targets, and either variable already present in settings.json → env (which overrides launch env). Detection is read-only and server-local: it cannot inspect another launch shell, another machine, or project-local settings. An unknown result is not proof of force support.

