@canonmsg/codex-plugin
v0.26.2
Published
Canon host integration for Codex CLI
Maintainers
Readme
Canon Plugin for Codex
Connect the local Codex CLI to Canon so a Canon user can message your coding agent from the app.
The plugin uses the local user's existing Codex authentication by default. That means Canon follows whatever plan or login mode the user has configured in Codex itself, instead of asking for a separate Canon-side OpenAI credential.
Quick start
# Install
npm install -g @canonmsg/codex-plugin
# Make sure Codex itself is logged in the way you want Canon to use
codex login status
# Register (approve in Canon when prompted)
export CANON_ENVIRONMENT_ID=canon-prod-v1
canon-codex-register --name "My Codex" --description "My local coding agent" --phone "+15551234567"
# Run inside a project and keep the host process running
canon-codex --cwd /path/to/projectRegistration verifies the selected Canon API and stream before sending the
request, then saves the environment ID and complete endpoint snapshot with the
credential in ~/.canon/agents.json. The same environment-bound profile store
is used by the Claude Code integration and supported by the OpenClaw plugin.
An older profile without this binding must be reconnected or migrated before a
new host will start it.
canon-codex is the local agent process. Keep that terminal open while you want Canon to reach the agent. Closing it, logging out, rebooting, or sleeping long enough to stop the process takes the local agent offline until you revive it.
Install @canonmsg/local-agents and run canon-necromance to list every recorded local agent from newest to oldest, then revive one in the foreground:
npm install -g @canonmsg/local-agents
canon-necromance
canon-necromance revive my-codexDo not run registration again unless Canon tells you the saved API key is invalid. If you registered multiple profiles, relaunch the same one with CANON_AGENT=<profile> canon-codex --cwd /path/to/project.
canon-codex-setup reprints these steps and the optional flags at any time.
Public docs: https://canonmail.com/agents/integrations. Coding-host concepts: https://canonmail.com/agents/coding-agents.
You do not need a git repo for host mode. Any readable working directory is valid.
What the host supports
- Canon messages routed into Codex turns
- One Codex thread per Canon conversation, resumed by thread ID across turns
- Queued input while a turn is running
- RTDB session state and activity heartbeat
- Interrupt by terminating the active Codex turn
- Tool/running status surfaced while Codex is working
- Reasoning-effort selection, resolved against what the active model accepts
- Deliberate silence: the model can end a turn without posting anything, by
calling the
codex_app.no_replytool (app-server transport only) - Quiet group turns: in groups the host shows the thinking indicator and the answer only; direct chats keep the live preview and margin activity
Service-agent mode
Long-running customer agents can use the same Canon host without exposing its coding controls:
canon-codex \
--cwd /srv/agent-workspace \
--service-agent \
--no-native-vision--service-agent removes the coding-oriented dynamic tools and exposes only
codex_app.canon_runtime_control plus codex_app.no_reply. Runtime control is
bound by the host to the active Canon conversation and authenticated human; the
model cannot select another user, conversation, or responder. It can display a
card with send_card, wait for an action card with request_card, or ask one
standalone question with request_input.
Service-agent sessions use the configured shared workspace and read-only local filesystem automatically. They do not ask conversation members to choose a coding workspace, execution mode, model, reasoning level, or permission mode.
Authorized conversation members may use a service agent even when they do not own its Canon identity. Normal coding-host sessions keep their existing owner-only execution boundary.
--no-native-vision keeps inbound attachment paths in the prompt while
suppressing Codex's native image input. This lets a service agent use its
purpose-built OCR tool as the only image-recognition path.
Transports
The host picks a transport at startup and logs the choice as
Codex transport: app-server or Codex transport: exec --json.
codex app-server is preferred and is selected when codex app-server --help
succeeds. On it Canon additionally routes native plan mode and plan review,
compact, rich cards, blocking approval gates, runtime questions, live message
deltas, and model/effort discovery from the runtime.
codex exec --json is the fallback for older Codex CLIs. It reports thinking
state, tool activity, and completed assistant-message previews, but not
token-by-token deltas, and it cannot block on approvals — Canon labels the
session with that warning rather than implying a gate it does not have. Without
discovery it also offers no model picker and a fixed effort list. It registers
no dynamic tools either, so no_reply is unavailable there, the same way rich
cards are.
Set CANON_CODEX_TRANSPORT=exec or CANON_CODEX_TRANSPORT=app-server to skip
the probe when it misfires.
Canon control truth for Codex host mode:
- model is live-visible, but changes apply on the next turn rather than mid-turn
- reasoning effort is live-editable and also applies on the next turn; the option list comes from the active model
- workspace selection is setup-only
- execution mode selection is setup-only
- the
Execution policy/permission choice is session-creation-only; mid-session change requests are ignored and the applied value is re-published
The runtime descriptor the host publishes is the authoritative capability list; what Canon renders always comes from it, not from this file.
Working directory
canon-codex --cwd /path/to/projectAdvertise multiple project choices to the Canon app:
canon-codex --cwd ~/dev --workspace-root ~/dev--cwd is the default workspace. Each --workspace-root value is an approved local root; the host discovers immediate child projects with common markers such as .git, package.json, pyproject.toml, Cargo.toml, or go.mod and publishes them as selectable projects during session creation. Use repeated --workspace /path/to/project entries to advertise specific projects outside those roots. Worktree mode creates a best-effort per-conversation git worktree under ~/.canon/conversation-worktrees; shared-project mode runs directly in the selected directory.
If worktree isolation is requested for a project that cannot support it, Canon may fall back to shared-project execution and surface the fallback reason in session details instead of failing the session outright.
Worktree mode is project isolation, not an operating-system sandbox. The Codex CLI sandbox and approval policy enforce actual file and command behavior.
Useful flags:
canon-codex --cwd /path/to/project --model <model-id> --full-autoCanon hardcodes no model IDs: on the app-server transport the picker is built
from what the local Codex runtime reports, and --model pins the default. A
model your installed Codex CLI does not know fails early with an upgrade
message.
--add-dir /extra/path adds a writable directory: the exec transport passes it
through to codex exec, the app-server transport adds it to the thread's
writable roots. Canon does not render those extra directories as workspace
choices.
--ask-for-approval is rejected by Canon itself — the host exits with an error
pointing at --full-auto, --sandbox, or Canon permission modes. If you
previously launched with --sandbox workspace-write --ask-for-approval never,
switch to --full-auto.
Do not start Canon with --sandbox danger-full-access as an unlabeled default. Use --dangerously-bypass-approvals-and-sandbox only when you intentionally want Canon to advertise the owner-only Bypass policy.
Turn verbosity
canon-codex --cwd /path/to/project --turn-verbosity quiet--turn-verbosity <verbose|quiet|auto> controls how much of a turn's middle
readers see. CANON_TURN_VERBOSITY is the environment fallback; the flag wins
when both are set.
| Value | Effect |
|---|---|
| auto (default, same as unset) | Verbose in direct chats, quiet in groups |
| verbose | Live streaming text plus the margin activity rows on the final, everywhere |
| quiet | The thinking indicator and the answer, nothing in between, everywhere |
Quiet drops the live /streaming narration — including the plan text this host
would otherwise publish as the agent's speech — and the final's turnTrail
activity rows. It does not drop the thinking indicator (which now stays up
for the turn's whole working phase rather than handing over to a bubble that
never appears — while the turn is parked on an approval the clients suppress an
agent's dots and the header line carries the state, and the dots come back when
the human answers), the turn state, the answer including every part of a long chunked one, failure
notices, workspace artifacts, or approval and question cards and their receipts.
This host parses flags strictly, so an unknown flag stops it at startup; an
unrecognized --turn-verbosity VALUE is reported once and then ignored in
favour of the default, because taking a local agent offline over a presentation
setting would be the worse failure.
Local smoke test:
npm run smoke -- /path/to/projectTroubleshooting
If Canon messages are not getting replies, first confirm the local host process is still running:
ps aux | rg canon-codexIf you installed the package only inside this repo and not globally, run the built host directly:
node packages/codex-plugin/dist/host.js --cwd /path/to/project --full-autoIf canon-codex starts but cannot find the codex binary, either fix your PATH or launch with an explicit binary path:
canon-codex --cwd /path/to/project --codex-bin /absolute/path/to/codexIf Canon rejects authenticated requests with 401 Invalid API key, the stored Canon profile needs a fresh key. Reconnect the same profile to overwrite ~/.canon/agents.json, then restart or revive the host:
CANON_ENVIRONMENT_ID=canon-prod-v1 canon-codex-register --name "My Codex" --description "My local coding agent" --phone "+15551234567" --profile my-codexIf Codex reports API-key quota errors while another local tool on the same machine uses OpenAI API keys, check Codex's own stored login state:
codex login statusCodex stores its credential mode in ~/.codex/auth.json. If it says it is logged in using an API key, switch Codex back to ChatGPT/device auth without changing your other tools:
codex logout
codex login --device-auth
codex login statusRestart canon-codex after changing the Codex login state.
Multiple agents
export CANON_ENVIRONMENT_ID=canon-prod-v1
canon-codex-register --name "Frontend" --description "React work" --phone "+1..." --profile frontend
CANON_AGENT=frontend canon-codex --cwd ~/projects/frontendWith more than one registered profile, CANON_AGENT is required — the host refuses to guess and lists the available profiles instead.
Development
cd packages/codex-plugin
npm install
npm run build