Codex agent type plugin for mngr
Project description
imbue-mngr-codex
The codex agent-type plugin for mngr: real
support for the OpenAI Codex CLI (the Rust codex binary) as a first-class mngr agent,
on par with the claude and antigravity agent types.
mngr create my-task codex launches an interactive Codex TUI agent that mngr can monitor
(RUNNING/WAITING), message, transcript, stop, resume, and isolate per agent.
How it works
See specs/agent-plugin-parity/codex-investigation.md in the monorepo for the full,
source-verified investigation behind each decision.
- Per-agent isolation via
CODEX_HOME. Codex resolves its whole config/auth/session/hook tree fromCODEX_HOME(default~/.codex). Each agent gets its ownCODEX_HOMEunder the agent state dir, injected only on the codex process (env CODEX_HOME=...), leaving the user's real$HOMEuntouched. codex accepts the dotted~/.mngr/...cwd, so there is no workspace symlink either. - Shared auth. The per-agent
auth.jsonis a symlink to the user's shared~/.codex/auth.json. Codex writes that file in place and reloads-before-refreshing, so one login authenticates every agent and token refreshes propagate.config.tomlpinscli_auth_credentials_store = "file"so codex never falls back to a keyring entry keyed by the per-agentCODEX_HOMEpath (which would defeat sharing). - Lifecycle marker (RUNNING/WAITING), subagent-aware. Codex subagents (the multi-agent
spawn_agentfeature) run asynchronously -- the root agent'sStophook fires while subagents are still running, with nofullyIdlesignal. So mngr does not just clear the marker onStop; it recomputes anactivemarker that is present while either the root turn is running (codex_root_active, set onUserPromptSubmit, cleared on the rootStop) or any subagent is in flight (one file peragent_idundercodex_subagents/, maintained by theSubagentStart/SubagentStophooks). The recompute runs under a portablemkdirlock so a concurrent rootStopand finalSubagentStopcan't strand it. A recorded rootsession_idguards against a nestedcodexprocess sharing the sameCODEX_HOME. (Backgrounded OS processes the agent launches are not tracked -- codex emits no hook for them.) - Conversation resume.
mngr stopthenmngr startresumes the prior conversation: the hook records the rootsession_id, and the launch command shell-evaluatescodex resume <id>(codex's session JSONL survives the hard killmngr stopperforms). - Transcripts. The native rollout JSONL is streamed verbatim to the raw transcript and
converted into mngr's agent-agnostic common transcript that
mngr transcriptreads. - Trust & hook bypass (consent-gated). mngr seeds the work dir as a trusted project to
skip codex's folder-trust dialog, and passes
--dangerously-bypass-hook-trustso its own lifecycle hooks run. Because trusting the workspace also lets codex load repo-local.codex/hooks.json, that bypass is consent-gated together with workspace trust: mngr prompts before trusting (or usemngr create --yes/auto_dismiss_dialogs = true).
Configuration
Set fields under an [agent_types.codex] table in your mngr config, or pass overrides.
model— model slug to pin (e.g."gpt-5.5"). Default: unset (codex's own default).model_reasoning_effort—none|minimal|low|medium|high|xhigh. Default: unset.sandbox_mode—read-only|workspace-write|danger-full-access. Default:workspace-write.auto_allow_permissions— whentrue, setsapproval_policy = "never"so codex never prompts for tool approval (the sandbox still applies). Default:false.config_overrides— free-form key/values merged last into the per-agentconfig.toml.auto_dismiss_dialogs— whentrue, trust the repo and allow the hook bypass without prompting. Default:false.update_policy— how mngr handles an outdated codex CLI at provision (see "Updates" below):AUTO(runcodex update, no prompt),ASK(prompt on an attended local run, else just notify), orNEVER(only notify). Default:ASK.emit_common_transcript— emit the common-schema transcript. Default:true.
Updates
mngr pins check_for_update_on_startup = false in the per-agent config.toml, because codex's
own "Update available!" prompt is blocking and would intercept the first message mngr sends
(an Enter could even select "Update now"). mngr surfaces updates itself instead: at provision it
compares codex --version against the latest_version codex last recorded in its own
~/.codex/version.json (no network call — codex refreshes that file on its own throttled
schedule during your normal codex use). The check always runs and is best-effort: any probe or
parse failure is swallowed (debug-logged) and never blocks agent creation. When codex is outdated,
the action is governed by update_policy: AUTO runs codex update; ASK (the default) prompts
to update now only on an attended run — a local host driven from an interactive terminal, and
not --yes — otherwise it logs a non-blocking notice (so an unattended remote/deploy agent
defaults to neither prompting nor upgrading the remote's global install); NEVER only logs the
notice. codex update self-detects the install method (it runs brew upgrade --cask codex for a
brew install, npm i -g for npm, the curl installer for standalone), so mngr needs no per-method
logic. Updating is optional — an outdated codex still runs — so a declined prompt, a NEVER
policy, or a non-interactive run never blocks agent creation, and --yes does not trigger a
global upgrade (only the explicit AUTO policy does).
Model note
Codex picks the account's default model, and a ChatGPT-account login rejects some
*-codex model slugs (e.g. gpt-5.2-codex) with a 400 "model is not supported when using
Codex with a ChatGPT account". Two distinct things cause this:
- Deprecation:
gpt-5.2/gpt-5.2-codex/gpt-5.3-codexhave been sunset for ChatGPT subscriptions (OpenAI's announcement points those users to the API). These fail on a ChatGPT plan in every mode, including the TUI. - Run-mode entitlement: the backend gates some
*-codexmodels by theoriginatorHTTP header (i.e. the client identity). The interactive TUI presents ascodex-tuiand is allowed;codex execpresents ascodex_execand is denied. (See the app-server note below for why this matters and why we do not spoof the TUI identity.)
If your agent errors on the first message with the "not supported" 400, set model to a model
your account supports (e.g. "gpt-5.5"), or authenticate with an API key (which carries the
full model entitlement).
Not yet implemented
Relative to mngr_claude, these are not yet ported (tracked for follow-up): session
preservation on destroy, deploy/scheduling contributions, field generators (waiting_reason),
the streaming snapshot, and installation/version management.
Future direction: an app-server-backed agent variant
This agent drives the codex TUI by tmux send-keys (paste + Enter), with banner-poll
readiness. That works, but it's fragile (screen-scraping) and codex's SessionStart fires
lazily, so there's no clean pre-input readiness signal. Codex offers a much cleaner surface to
drive programmatically -- the app-server -- and a second agent type built on it is a planned
follow-up (mirroring mngr_claude's claude + headless_claude split).
We built the TUI agent first, though, for a concrete reason: like claude -p, the app-server
does not have full feature parity with the interactive TUI on a ChatGPT-subscription login. The
backend gates some *-codex models on the client identity (the originator, derived from the
app-server's initialize clientInfo.name) -- the first-party TUI presents as codex-tui and is
entitled to them; a programmatic app-server client identifying honestly as mngr is not. The only
way to close that gap is to spoof the TUI identity, which OpenAI's terms disallow (see "client
identity" below). So the TUI agent is how you get full *-codex model access on a ChatGPT login
today, and the app-server variant is a complement for the cases where the identity gap is
acceptable (API-key auth, which carries the full entitlement; or only models the honest identity
already gets) -- not a replacement.
What it would give us
- Programmatic messaging instead of tmux paste.
codex app-serverspeaks a JSON-RPC protocol over a socket; you send a turn withinitialize->thread/start->turn/start. Nosend-keys, no paste-visibility polling. - You can still view it in the TUI. Launch the TUI as a viewer with
codex --remote unix://<sock>(acceptsws://,wss://,unix://too) connected to the app-server -- so it runs in tmux and you watch it live, but mngr drives it over the socket. - Clean synchronous readiness. The
initializeresponse /thread.startedevent is an unambiguous "ready for input" signal -- it eliminates the lazy-SessionStartbanner-poll workaround entirely. - Cleaner lifecycle/transcript.
turn.started/turn.completed/item.*events could drive the RUNNING/WAITING marker and the transcript directly, instead of (or alongside) the hook scripts. The hooks, subagents, sandbox, and approval policy are all engine-level (codex-core), so they fire identically whether codex is driven via the TUI or the app-server -- the existing marker hooks would keep working.
How (verified against codex 0.138.0)
codex app-server --listen unix://<sock>runs the server and works with the brew/npm install. (The convenience wrappercodex remote-control start/codex app-server daemonrequires codex's standalone installer at a fixed path -- avoid it; use rawapp-server --listen.)codex app-server proxy --sock <sock>proxies stdio to a running server's control socket.- mngr would override
send_messageto speak JSON-RPC to the socket, andassemble_commandwould launchapp-server+ a--remoteTUI viewer instead of the bare TUI.
Important: client identity and OpenAI's ToS (do NOT spoof the TUI)
The app-server sets its originator from the initialize request's clientInfo.name. It is
tempting but against the spirit (and likely the letter) of OpenAI's terms to set
clientInfo.name = "codex-tui" so the backend grants the *-codex model entitlement it
otherwise denies non-TUI clients. That presents a programmatic client as the first-party TUI
specifically to bypass an intentional server-side model gate -- which falls under OpenAI's
"circumvent any restrictions / bypass any protective measures" clause (codex's own code treats
these names as a trust boundary; the override env var is literally CODEX_INTERNAL_ORIGINATOR_OVERRIDE).
So the app-server variant must identify honestly (mngr's own client name) and use whatever
models that identity is legitimately entitled to. For the gated *-codex models in app-server
mode, authenticate with an API key (OpenAI's documented path for programmatic workflows) --
do not spoof the TUI. The genuine codex TUI agent in this plugin remains the legitimate way
to use *-codex models on a ChatGPT-subscription login (it really is the TUI).
(Driving codex programmatically via the app-server on a single user's own ChatGPT login is itself fine -- it's a first-party feature and OpenAI staff have called such use "permissive"; the line we don't cross is identity-spoofing to defeat the model gate, plus the usual no credential-sharing / no multi-tenant-proxying / no rate-limit-bypass.)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file imbue_mngr_codex-0.1.0.tar.gz.
File metadata
- Download URL: imbue_mngr_codex-0.1.0.tar.gz
- Upload date:
- Size: 66.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5346e0590e209e71f1b96b196c1a7ac11001f5b40ab2ec5942e06fb04a6b7c8c
|
|
| MD5 |
4a333fffd632713835b88495376ae10b
|
|
| BLAKE2b-256 |
6655cd6f5f22e78ba3d2babe3d783aec20a92323a6c77f302c3052d7077c77ef
|
Provenance
The following attestation bundles were made for imbue_mngr_codex-0.1.0.tar.gz:
Publisher:
publish.yml on imbue-ai/mngr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
imbue_mngr_codex-0.1.0.tar.gz -
Subject digest:
5346e0590e209e71f1b96b196c1a7ac11001f5b40ab2ec5942e06fb04a6b7c8c - Sigstore transparency entry: 1810794647
- Sigstore integration time:
-
Permalink:
imbue-ai/mngr@3a0dfcb044f23c4b9b0081e8d4dde79a165ff8aa -
Branch / Tag:
refs/tags/v0.2.13 - Owner: https://github.com/imbue-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3a0dfcb044f23c4b9b0081e8d4dde79a165ff8aa -
Trigger Event:
push
-
Statement type:
File details
Details for the file imbue_mngr_codex-0.1.0-py3-none-any.whl.
File metadata
- Download URL: imbue_mngr_codex-0.1.0-py3-none-any.whl
- Upload date:
- Size: 45.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a353a470fb931379763a7367d4a9c6fa29e888718115ad9808693115325012c9
|
|
| MD5 |
6c39e4a5e9ef72330d70bc06381bd40a
|
|
| BLAKE2b-256 |
4f02b89c26b44cc428175ffd2d4b9af4347336d34a1b24988fad6866fc13b3c6
|
Provenance
The following attestation bundles were made for imbue_mngr_codex-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on imbue-ai/mngr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
imbue_mngr_codex-0.1.0-py3-none-any.whl -
Subject digest:
a353a470fb931379763a7367d4a9c6fa29e888718115ad9808693115325012c9 - Sigstore transparency entry: 1810795163
- Sigstore integration time:
-
Permalink:
imbue-ai/mngr@3a0dfcb044f23c4b9b0081e8d4dde79a165ff8aa -
Branch / Tag:
refs/tags/v0.2.13 - Owner: https://github.com/imbue-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3a0dfcb044f23c4b9b0081e8d4dde79a165ff8aa -
Trigger Event:
push
-
Statement type: