Install the Codex CLI plugin
The cardinal-codex-plugin puts your OpenAI Codex CLI sessions on the Agent Outcomes dashboard, with the same one-consent setup as the Claude Code plugin:
- Telemetry — your Codex sessions stream to Cardinal, attributed to engineer, branch, PR, and initiative, with per-turn token usage and a computed dollar cost per session.
- MCP tools — a managed
cardinalMCP server entry in your Codex config, exposing whichever tools your org has integrations for. Pass--telemetry-onlyto skip this side.
Like the Claude Code plugin, it also delivers session context and spend limits: sessions in a git repo receive the initiative branch-naming convention at start, and org spend-limit policies are enforced in-session — quiet context at notify, a visible message at warn, a stopped turn at block.
Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.
Coordination on agent intent
Plugin 0.40.0 lets the agent choose when coordination matters, during reasoning, planning, decisions, answering or other work. Supervisor and worker share the same operations:
investigation sync --intent PURPOSEcatches up on fresh collaborator information.investigation request --assignee PRINCIPAL --assignee-session SID --intent PURPOSE --text REQUESTdeclares a required result for that work.investigation wait --intent PURPOSEwaits until new information or a result needs attention. Reuse the exact purpose to resume after an interruption;--request Qadds an existing prerequisite.
Ordinary tools are not classified or blocked by coordination. There is no fixed list of edits, commits or other supported actions, and no mode setting, policy file or enable command. Normal delivery can notify the agent about new information; explicit synchronization retains its own handling and dependency state.
The assignee responds complete, blocked, abstain or reject. Only the
requester accepting the exact complete result, or cancelling with a reason,
resolves the dependency. Reading, acknowledgment and timeout never release it.
Unrelated purposes remain available. New feedback interrupts a wait for handling.
Waiting uses one bounded CLI invocation with incremental reads and backoff; it is not server push or indefinite host parking. A timeout leaves the intent and required results durable. Use the request commands and the runtime contract for feedback review, exact references, outcomes and resumption.
Deploy backend support for coordination_intents version 1 and request_protocol:2
before upgrading clients. Upgrade participants sharing an Investigation before
creating intent-only requests: old clients fail closed on those records. Existing
records remain readable; their old action categories do not intercept tools in
new clients. Broader fleet/performance acceptance remains separate work.
After upgrading, run the existing hook repair and restart Codex to remove the old managed coordination registration. Stale registrations return quietly.
Requirements
- A recent Codex CLI release (with MCP server and hooks support).
- Python 3.11+ on your
PATH. - A Cardinal account on
app.cardinalhq.io, or a self-hosted Cardinal UI your operator has prepared (see Connect AI clients).
1. Install
codex plugin marketplace add cardinalhq/cardinal-codex-plugin
codex plugin add cardinal-codex-plugin@cardinalhq-codex-plugin2. Connect
Ask Codex:
Use cardinal-connectThe connect skill prints a URL like https://app.cardinalhq.io/connect?code=ABCD-EFGH. Open it in your browser, sign in if you aren’t already, pick the org to connect, and click Approve. The plugin picks up your consent within a few seconds and writes:
| File | What gets written |
|---|---|
~/.codex/config.toml | A managed [mcp_servers.cardinal] entry. |
~/.codex/hooks.json | Managed Cardinal telemetry hook entries. |
~/.codex/cardinal.json | Non-secret connection state for status/disconnect. |
~/.codex/cardinal-secrets.json | Your minted keys, written mode 0600. |
For self-hosted Cardinal UI, run the script directly with your host:
python3 scripts/cardinal-connect --host https://ui.example.internalWith --host set, nothing touches Cardinal Cloud: your Cardinal UI runs the consent flow, mints the keys, and hands the plugin your endpoints — MCP on your Cardinal UI, telemetry to your Cardinal Data Lake intake. The telemetry side requires your operator to have set MAESTRO_INGEST_ENDPOINT on the Cardinal UI deployment (see Environment variables); without it the connect bundle omits telemetry and sessions never reach the dashboard.
Then restart Codex so it reloads the MCP and hook configuration, and trust the Cardinal hooks if Codex prompts you to.
3. Verify
Ask Codex:
Use cardinal-statusYou’ll see the connected org, both endpoints, key prefixes, and a reachability probe against each side. Run a session in any git repo and it appears on the Outcomes dashboard within a few minutes.
Variants
python3 scripts/cardinal-connect --telemetry-only # Outcomes dashboard only; skip the MCP tools
python3 scripts/cardinal-connect --rotate # Mint fresh keys, overwrite an existing connection
python3 scripts/cardinal-connect --host https://… # Point at a self-hosted Cardinal UI
python3 scripts/cardinal-connect --dry-run # Walk the consent flow, write nothingUpgrading from a version before 0.4.0? Re-run cardinal-connect --rotate once so the newer hooks are registered.
Upgrading to 0.22.0 from an earlier version? Run python3 scripts/cardinal-connect --repair-hooks, then restart Codex, so the new PostToolUse hook that records decisions is registered.
Getting attributed correctly
Sessions are attributed to an initiative by branch name: <type>/<kebab-name>, where the type prefix is one of feat, fix, refactor, infra, chore, research, or spike (for example fix/login-crash → initiative login-crash, type bugfix). Sessions on main/master/develop/trunk are treated as research/scoping work. The plugin surfaces this convention to Codex at session start, so branches it cuts for you classify cleanly.
Pull requests and decisions
Each prompt’s branch state includes the branch’s pull request when gh is installed and signed in and a PR exists. The lookup is cached and refreshed in the background, so the first prompt on a new branch may not carry it yet.
Decision capture is off by default. Turn it on from your own terminal, not through Codex, whose sandbox can’t write the setting:
python3 scripts/cardinal-decision onWhile it’s on, Codex is asked to record each material choice by running cardinal-decision record …. Inside Codex’s sandbox that command only checks its arguments and prints them; Cardinal’s PostToolUse hook, which runs outside the sandbox, records the decision, sends it tagged with the session, repo, branch, and PR, and tells Codex the recorded id or why nothing was recorded. python3 scripts/cardinal-decision off turns it off, and CARDINAL_DECISIONS=1 or 0 in Codex’s environment overrides the setting.
Storyboard associations
From version 0.25.4, the plugin tells Codex how Cardinal’s storyboards relate to your work, and records where a storyboard was written. See Associations for the model: a storyboard is about something someone declared, or written from a checkout.
- At session start, with Cardinal connected, the plugin gives Codex this session’s id and shows storyboards about or written from the work in this repository, including after a merge. It adds the
cardinal-storyboardcommand (context,discover) for the context a storyboard call needs. - Edited files are recorded after Codex’s
apply_patchsucceeds. Files changed by shell commands are not recorded. - Context filled in automatically in
bypassPermissionsmode, or in any mode when you setCARDINAL_STORYBOARD_CONTEXT=always. Codex applies a rewritten tool call only together with an explicit allow, and it isn’t verified yet whether that can skip an approval prompt, so other modes are off by default: the session-start text tells Codex to pass the output ofcardinal-storyboard contextinstead.alwaysmay skip Codex’s approval prompt for storyboard writes, includingstoryboard__publish, because the plugin’s allow is sent on everycreate,add_act,publishandfindcall it fills in. Set it only if you accept that. - No lookup before an edit. That is Claude Code only.
- Upgrading. Run
python3 scripts/cardinal-connect --repair-hooksand restart Codex, so the newPreToolUsehook and the edit-recording are registered. - Opt out.
CARDINAL_STORYBOARD_SESSION_START=0drops the session id line and the discovery block;CARDINAL_STORYBOARD_DISCOVERY=0drops the discovery block only;CARDINAL_STORYBOARD_CONTEXT=0stops Codex from filling insession_idandcontext. - What it sends. Repository, branch, commit, pull request number and ticket key from the branch name, and (on
main) recently merged pull request numbers and your recent local branch names, to your own Cardinal. Files edited are repository-relative paths, visible to members of your org and never on a public link. See Associations.
Privacy
The plugin captures tool names, command lines, and file paths so Cardinal can tell which repo and service a session worked on, plus token counts and rate-limit standing for cost reporting. The contents of your prompts are never captured.
From version 0.23.0, the result of every tool call that Codex reports to its PostToolUse hook is kept locally as storyboard evidence, in ~/.cardinal/evidence/ on your machine, with credentials scrubbed, and deleted after 14 days. Cardinal’s own tools are skipped: their results are already witnessed. A call that touches something sensitive, such as a .env file, a private key or a secret-printing command, is withheld: only a stub saying why is kept. The plugin never uploads the spool; a result leaves your machine only when you cite it in an Investigation Storyboard and the plugin’s scripts/cardinal-evidence promotes it. Run cardinal-connect --repair-hooks and restart Codex after upgrading to register the capture hook. Codex is verified to report shell commands to that hook; a call it doesn’t report isn’t captured. To opt out, set CARDINAL_EVIDENCE_CAPTURE=0 in the environment Codex starts with, or create the file ~/.cardinal/evidence/disabled.
Disconnect
Use cardinal-disconnectThis revokes your keys with Cardinal and removes the managed MCP entry, hooks, and local state. Everything else in your Codex config is left as it was.