This plugin uses one runtime config file:
- resolved config path:
$XDG_CONFIG_HOME/opencode/codex-config.jsoncwhenXDG_CONFIG_HOMEis set- otherwise
~/.config/opencode/codex-config.jsonc
If the default config path does not exist, installer/bootstrap flows create it with defaults.
If OPENCODE_OPENAI_MULTI_CONFIG_PATH is set, that explicit file path is loaded for runtime behavior. You are responsible for creating/managing that file.
Note: plugin startup still ensures the default config file exists as a bootstrap convenience, even when runtime reads from an explicit OPENCODE_OPENAI_MULTI_CONFIG_PATH.
Most plugin-managed files follow resolved config roots ($XDG_CONFIG_HOME/opencode/... when set, otherwise ~/.config/opencode/...).
Known exceptions:
- OpenCode provider auth marker/legacy transfer source is OpenCode-owned at
${XDG_DATA_HOME:-~/.local/share}/opencode/auth.json.
Use these schemas for validation/autocomplete:
schemas/codex-config.schema.json->codex-config.jsoncschemas/opencode.schema.json->opencode.jsonschemas/codex-accounts.schema.json->codex-accounts.json(advanced/manual recovery only)
The plugin loads config in this order:
OPENCODE_OPENAI_MULTI_CONFIG_PATH- Resolved default config path:
$XDG_CONFIG_HOME/opencode/codex-config.jsoncwhenXDG_CONFIG_HOMEis set- otherwise
~/.config/opencode/codex-config.jsonc - compatibility fallback:
codex-config.jsonif the canonical.jsoncfile is absent
codex-config.jsonc supports JSON comments (// and /* ... */) for readability. The loader also accepts commented legacy codex-config.json files.
Known-field type validation is applied on load. If a known field has an invalid type/value, the plugin ignores that config file and logs an actionable warning.
Mode-derived runtime defaults when omitted:
runtime.codexCompactionOverride:trueincodex,falseinnativeruntime.collaborationProfile:trueincodex,falseinnativeruntime.orchestratorSubagents: inherits effectiveruntime.collaborationProfile
debug: boolean- Enables plugin debug logging (
falsedefault).
- Enables plugin debug logging (
quiet: boolean- Suppresses plugin toast/UI notifications (
falsedefault).
- Suppresses plugin toast/UI notifications (
refreshAhead.enabled: boolean- Enables proactive token refresh (
truedefault).
- Enables proactive token refresh (
refreshAhead.bufferMs: number- Refresh lead time in milliseconds before expiry (
60000default).
- Refresh lead time in milliseconds before expiry (
runtime.mode: "native" | "codex"native: carbon-copy target of standard OpenCode native plugin identity/header behavior.codex: full codex-rs spoof identity/header behavior.
runtime.rotationStrategy: "sticky" | "hybrid" | "round_robin"sticky: one active account until limits/health require change (default).hybrid: prefers active account, falls back to healthiest/LRU behavior.round_robin: rotates every message (higher token/cache churn).
runtime.sanitizeInputs: boolean- Sanitizes outbound payloads for provider-compat edge cases.
runtime.developerMessagesToUser: boolean- When effective spoof mode is
codex, remaps non-permissionsdevelopermessages touser(truedefault). - Preserves permissions/bootstrap developer blocks (for example
<permissions instructions>content) even when remap is enabled. - Set to
falseto preserve alldeveloperroles.
- When effective spoof mode is
runtime.promptCacheKeyStrategy: "default" | "project"default: preserve upstreamprompt_cache_keybehavior (session-based keying).project: overrideprompt_cache_keywith a versioned hash of project path + mode.
runtime.codexCompactionOverride: boolean- Enables codex-rs compact prompt +
summary_prefixhandoff behavior for OpenAI sessions. - Mode defaults:
trueincodex,falseinnative. - Explicit boolean value overrides mode default.
- Enables codex-rs compact prompt +
runtime.shareableDebug: boolean- Writes a bounded privacy-first summary log to
<config-root>/logs/codex-plugin/shareable-debug.jsonl. - Persists a rolling crash-tolerant event buffer under
<config-root>/logs/codex-plugin/shareable-debug-state/segments/. - On trigger conditions (
401,403,429, auth failures, account-switch retry after failure, and synthetic plugin fatal errors), writes a dedicated incident file under<config-root>/logs/codex-plugin/shareable-debug-state/incidents/. - Uses
<config-root>/logs/codex-plugin/shareable-debug-state/incident-state.jsonto resume or seal interrupted incident capture after restart. - Sensitive identifiers are pseudonymized per process/log bundle instead of logged raw.
- Request bodies, tokens, cookies, OAuth secrets, raw emails/account IDs/session IDs, and raw
prompt_cache_keyvalues are never persisted by this mode. - When enabled, request snapshot logging is suppressed even if
runtime.headerSnapshotsorruntime.headerTransformDebugare also set.
- Writes a bounded privacy-first summary log to
runtime.headerSnapshots: boolean- Writes before/after request header snapshots to debug logs.
- Custom snapshot metadata is stored under a nested
metaobject to prevent collisions with reserved top-level fields.
runtime.headerSnapshotBodies: boolean- When
runtime.headerSnapshots=true, includes redacted request bodies in snapshots. - Response snapshots include status + headers only (no response body capture).
- Caution: request body snapshots can still contain prompt/tool payload content even when token fields are redacted.
- When
runtime.headerTransformDebug: boolean- Adds explicit
before-header-transformandafter-header-transformrequest snapshots for message fetches.
- Adds explicit
runtime.pidOffset: boolean- Enables session-aware offset behavior for account selection.
runtime.collaborationProfile: boolean- Experimental: enables Codex-style collaboration mode mapping from agent names (
plan-> plan mode,orchestrator-> code mode profile). - If omitted, defaults to
trueinruntime.mode="codex"andfalseotherwise. - Explicit
true/falseworks in any mode.
- Experimental: enables Codex-style collaboration mode mapping from agent names (
runtime.orchestratorSubagents: boolean- Experimental: enables Codex-style subagent header hints for helper agents under collaboration profile mode.
- If omitted, inherits
runtime.collaborationProfileeffective value. - Explicit
true/falseworks in any mode.
-
Model availability comes from the selected catalog source for the current account.
-
When a live account-scoped
/backend-api/codex/modelsfetch succeeds, the plugin uses that source alone after normalizing, deduplicating, and sorting the catalog response for provider shaping. -
When live catalog data is unavailable, the plugin falls back to the shared GitHub
models.jsonsnapshot, normalized through the same catalog parser. -
The plugin does not field-merge live catalog entries with GitHub fallback entries.
-
As of March 5, 2026, the live
/backend-api/codex/modelspayload includesgpt-5.4,gpt-5.3-codex,gpt-5.3-codex-spark, and older GPT-5 Codex variants. -
Actual availability still depends on the authenticated account's live catalog and plan entitlements.
-
global.personality: string- Personality key applied to all models unless overridden.
-
global.reasoningEffort: string- Global reasoning effort override forwarded upstream when the request does not already set one.
-
global.reasoningSummary: "auto" | "concise" | "detailed" | "none"- Global reasoning summary format override forwarded upstream as
reasoning.summary. "none"disables reasoning summaries.- Deprecated boolean aliases still load:
reasoningSummaries: true=>"auto"reasoningSummaries: false=>"none"thinkingSummariesbehaves the same way and warns on load.
- Global reasoning summary format override forwarded upstream as
-
global.textVerbosity: "default" | "low" | "medium" | "high" | "none"- Global text verbosity override forwarded upstream as
text.verbosity. "default"uses each model catalog default."none"disables text verbosity.- Deprecated aliases still load:
verbosityEnabled: false=>"none"verbosity: "medium"=>textVerbosity: "medium"
- Global text verbosity override forwarded upstream as
-
global.serviceTier: "auto" | "priority" | "flex"- Global Fast Mode preference (
serviceTier). "priority"maps to request-bodyservice_tier: "priority"only forgpt-5.4*."flex"passes throughservice_tier: "flex"."auto"or omission leavesservice_tierunset unless the request body already sets it.- Deprecated alias:
"default"=>"auto".
- Global Fast Mode preference (
-
global.include: ("reasoning.encrypted_content" | "file_search_call.results" | "message.output_text.logprobs")[]- Global response include values merged into host-provided
include.
- Global response include values merged into host-provided
-
global.parallelToolCalls: boolean- Global override for
parallel_tool_callswhen the request does not already set one.
- Global override for
-
customModels.<slug>.targetModel: string- Required target model slug inherited by the selectable custom model alias.
-
customModels.<slug>.name: string- Optional display name for the custom selectable model.
-
customModels.<slug>.personality,customModels.<slug>.reasoningEffort,customModels.<slug>.reasoningSummary,customModels.<slug>.textVerbosity,customModels.<slug>.serviceTier,customModels.<slug>.include,customModels.<slug>.parallelToolCalls- Defaults applied when that custom slug is selected.
-
customModels.<slug>.variants.<variant>.personality- Variant-level override for the selected custom slug.
-
customModels.<slug>.variants.<variant>.reasoningEffort,customModels.<slug>.variants.<variant>.reasoningSummary,customModels.<slug>.variants.<variant>.textVerbosity,customModels.<slug>.variants.<variant>.serviceTier,customModels.<slug>.variants.<variant>.include,customModels.<slug>.variants.<variant>.parallelToolCalls- Variant-level overrides for the selected custom slug.
-
perModel.<model>.personality: string- Model-specific personality override.
-
perModel.<model>.reasoningEffort,perModel.<model>.reasoningSummary,perModel.<model>.textVerbosity,perModel.<model>.serviceTier,perModel.<model>.include,perModel.<model>.parallelToolCalls- Model-specific overrides with the same semantics as
global.*.
- Model-specific overrides with the same semantics as
-
perModel.<model>.variants.<variant>.personality: string- Variant-level personality override.
-
perModel.<model>.variants.<variant>.reasoningEffort,perModel.<model>.variants.<variant>.reasoningSummary,perModel.<model>.variants.<variant>.textVerbosity,perModel.<model>.variants.<variant>.serviceTier,perModel.<model>.variants.<variant>.include,perModel.<model>.variants.<variant>.parallelToolCalls- Variant-level overrides with the same semantics as
global.*.
- Variant-level overrides with the same semantics as
If a model reports supportsVerbosity=false in catalog/runtime defaults, verbosity overrides are ignored.
Precedence for personality, reasoningEffort, reasoningSummary, textVerbosity, serviceTier, include, and parallelToolCalls settings:
perModel.<model>.variants.<variant>perModel.<model>customModels.<selected-slug>.variants.<variant>customModels.<selected-slug>global
Custom model notes:
customModelscreates selectable aliases likeopenai/my-fast-codex.- The selected custom slug inherits instructions, runtime defaults, capabilities, limits, and supported variants from
targetModel. - The backend request still uses
targetModelas the API model id. - If
targetModelis not present in the active catalog/provider, the plugin warns and skips that custom model instead of inventing metadata. reasoningSummaryFormatremains internal-only. Users control request summaries withreasoningSummary; internal catalog defaults may still populatereasoning.summarywhen no explicit config override is set.
- Fast mode is configured with
serviceTier: "priority". - The plugin preserves an explicit request-body
service_tierif your host already sets one. serviceTier: "priority"is intentionally gated togpt-5.4*requests and is omitted for other models instead of failing the request.- The plugin preserves request-level
model_context_window,model_auto_compact_token_limit, andmax_output_tokensfields through all payload rewrites. - For
gpt-5.4*, the plugin clamps those request-level overrides to the currently documented GPT-5.4 long-context limits before sending the request:model_context_window <= 1,050,000model_auto_compact_token_limit <= min(922,000, model_context_window - 128,000)max_output_tokens <= 128,000
- The
922,000auto-compact ceiling is the full-window practical safe-input cap derived from the published1,050,000total context budget minus the published128,000max output budget. - If you request a smaller
model_context_window, the plugin also preserves the same output headroom by clampingmodel_auto_compact_token_limittomodel_context_window - 128,000. - The live Codex catalog currently still reports
context_window: 272000forgpt-5.4, so any largermodel_context_windowvalue is an explicit request override rather than a catalog default. - OpenAI's current GPT-5.4 guidance says prompts above the standard
272,000input window are billed at higher long-context rates.
Built-in personalities from model metadata:
friendlypragmatic
Custom personalities:
- Store files in:
- project-local:
.opencode/personalities/<key>.md - global:
$XDG_CONFIG_HOME/opencode/personalities/<key>.mdwhenXDG_CONFIG_HOMEis set, otherwise~/.config/opencode/personalities/<key>.md
- project-local:
- Key format:
- lowercase safe slug (no
/,\, or..)
- lowercase safe slug (no
- Pattern recommendation (same shape as native-friendly/pragmatic behavior):
- keep a stable "core assistant contract" (coding agent, safety, correctness, no fabricated output)
- layer style/tone/collaboration preferences under separate sections
- add explicit guardrails and anti-patterns
Installer and startup bootstrap a slash command:
/create-personality
And a tool:
create-personality
And a managed skill bundle:
$XDG_CONFIG_HOME/opencode/skills/personality-builder/SKILL.mdwhenXDG_CONFIG_HOMEis set, otherwise~/.config/opencode/skills/personality-builder/SKILL.md
Flow:
- Run
/create-personality. - The assistant interviews you (inspiration, tone, coding style, guardrails, examples).
- The assistant calls
create-personality. - A new profile is written under
personalities/<key>.md. - Set the key in
codex-config.jsoncviaglobal.personalityorperModel.
Advanced path:
- Use the
personality-builderskill when you want stricter voice/protocol extraction from source docs. - Follow the skill workflow, then persist through
create-personality.
runtime.modeis the canonical persisted mode setting incodex-config.jsonc.- Identity behavior is derived from mode:
native-> native identitycodex-> codex identity
spoofModeis compatibility plumbing, not a canonical config key.
OPENCODE_OPENAI_MULTI_CONFIG_PATH: explicit config file path (absolute path recommended).OPENCODE_OPENAI_MULTI_REASONING_SUMMARIES: global reasoning-summary env override.OPENCODE_OPENAI_MULTI_THINKING_SUMMARIES: deprecated alias forOPENCODE_OPENAI_MULTI_REASONING_SUMMARIES.OPENCODE_OPENAI_MULTI_MODE:native|codex.OPENCODE_OPENAI_MULTI_SPOOF_MODE: advanced temporary identity override (native|codex).- If
OPENCODE_OPENAI_MULTI_MODEis set, runtime mode takes precedence.
- If
XDG_CONFIG_HOME: changes config/agents/personality roots.
OPENCODE_OPENAI_MULTI_PROACTIVE_REFRESH:1|0|true|false.OPENCODE_OPENAI_MULTI_PROACTIVE_REFRESH_BUFFER_MS: integer ms.OPENCODE_OPENAI_MULTI_QUIET:1|0|true|false.OPENCODE_OPENAI_MULTI_PID_OFFSET:1|0|true|false.OPENCODE_OPENAI_MULTI_ROTATION_STRATEGY:sticky|hybrid|round_robin.OPENCODE_OPENAI_MULTI_PROMPT_CACHE_KEY_STRATEGY:default|project.OPENCODE_OPENAI_MULTI_PERSONALITY: personality key override.OPENCODE_OPENAI_MULTI_THINKING_SUMMARIES:1|0|true|false.OPENCODE_OPENAI_MULTI_VERBOSITY_ENABLED:1|0|true|false.OPENCODE_OPENAI_MULTI_VERBOSITY:default|low|medium|high.OPENCODE_OPENAI_MULTI_SERVICE_TIER:default|priority|flex.OPENCODE_OPENAI_MULTI_COMPAT_INPUT_SANITIZER:1|0|true|false.OPENCODE_OPENAI_MULTI_REMAP_DEVELOPER_MESSAGES_TO_USER:1|0|true|false.OPENCODE_OPENAI_MULTI_CODEX_COMPACTION_OVERRIDE:1|0|true|false.OPENCODE_OPENAI_MULTI_HEADER_SNAPSHOTS:1|0|true|false.OPENCODE_OPENAI_MULTI_HEADER_SNAPSHOT_BODIES:1|0|true|false.OPENCODE_OPENAI_MULTI_HEADER_TRANSFORM_DEBUG:1|0|true|false.OPENCODE_OPENAI_MULTI_COLLABORATION_PROFILE:1|0|true|false.OPENCODE_OPENAI_MULTI_ORCHESTRATOR_SUBAGENTS:1|0|true|false.
OPENCODE_OPENAI_MULTI_DEBUG=1: plugin debug logs.OPENCODE_OPENAI_MULTI_SHAREABLE_DEBUG=1: privacy-first shareable structured debug log.CODEX_IN_VIVO=1: enables live quota probe tests.DEBUG_CODEX_PLUGIN=1: alternate debug flag.CODEX_AUTH_DEBUG=1: verbose OAuth lifecycle logging (oauth-lifecycle.log).- Accepted truthy values:
1,true,yes,on. - This flag is independent from general plugin debug flags.
- Accepted truthy values:
CODEX_AUTH_DEBUG_MAX_BYTES: max size foroauth-lifecycle.logbefore rotation tooauth-lifecycle.log.1.CODEX_OAUTH_CALLBACK_TIMEOUT_MS: OAuth wait timeout (min60000).CODEX_OAUTH_SERVER_SHUTDOWN_GRACE_MS: success-page shutdown grace.CODEX_OAUTH_SERVER_SHUTDOWN_ERROR_GRACE_MS: error-page shutdown grace.CODEX_OAUTH_HTTP_TIMEOUT_MS: timeout for OAuth HTTP calls (ms, min1000).- OAuth HTTP requests reject redirects by default for token/code exchange safety.
CODEX_DEVICE_AUTH_TIMEOUT_MS: max total device-auth polling time (ms, min1000).OPENCODE_NO_BROWSER=1: disables browser auto-open.NO_COLOR=1: disables ANSI color blocks in quota UI.
Legacy behavior keys are no longer parsed from codex-config.jsonc.
personalitycustomSettingsand all nestedcustomSettings.*
Use canonical global and perModel keys only.
The plugin synchronizes a pinned upstream Codex orchestrator prompt and plan-mode prompt into a local cache under the resolved config cache root ($XDG_CONFIG_HOME/opencode/cache/ when XDG_CONFIG_HOME is set, otherwise ~/.config/opencode/cache/):
codex-prompts-cache.jsoncodex-prompts-cache-meta.json(stores URLs,lastChecked, and ETags)
Fetch behavior:
- TTL-based refresh (best-effort; normal requests continue if refresh fails)
- ETag-based revalidation (
If-None-Match+304 Not Modified)
The plan prompt from this cache is used to populate plan-mode collaboration instructions.
When runtime.collaborationProfile is enabled, the installer and plugin startup also manage the visibility of an orchestrator.md agent template under the resolved config root ($XDG_CONFIG_HOME/opencode/agents/ when XDG_CONFIG_HOME is set, otherwise ~/.config/opencode/agents/).
{ "$schema": "https://schemas.iam-brain.dev/opencode-codex-auth/codex-config.schema.json", "debug": false, "quiet": false, "refreshAhead": { "enabled": true, "bufferMs": 60000 }, "runtime": { "mode": "native", "rotationStrategy": "sticky", "sanitizeInputs": false, "developerMessagesToUser": true, "promptCacheKeyStrategy": "default", "headerSnapshots": false, "headerSnapshotBodies": false, "headerTransformDebug": false, "pidOffset": false }, "global": { "personality": "pragmatic", "reasoningEffort": "high", "reasoningSummary": "auto", "textVerbosity": "default" }, "customModels": {}, "perModel": {} }