Give Codex and Claude Code independent Codex workers through the shell.
One Bash executable. Five commands. Plain files. No daemon.
Quickstart · Commands · Models · Startup context · Contributing
A coordinating Codex or Claude Code session can hand off a focused task, keep working, and collect
an answer later. Each worker is an independent codex exec process, outside the
coordinator's native subagent pool. Workers start fresh and exit when finished.
The helper stays small enough to inspect in one sitting. There is no scheduler, service, database, or framework to operate. Account usage and rate limits still apply.
| Small by design | What you get |
|---|---|
| Fire and forget | spawn returns a worker ID immediately; the worker survives the launching shell closing. |
| Track completion | spawn --wait stays alive for one run so a harness can manage it as a background command. |
| Explicit context | Pass the task and everything the worker needs. No parent transcript is copied. |
| Cost-conscious defaults | Workers use Luna / medium, with explicit model and reasoning overrides. |
| Controlled delegation | Workers may use native Codex subagents; workers and their subagents cannot launch more workers through mcx. |
| Inspectable state | Prompts, status, logs, and answers are files in .mcx/. |
You need Bash 3.2+, an installed and authenticated Codex CLI, and standard Unix utilities. Python 3 is used only for installation and tests. The current integration was verified with Codex CLI 0.153.4 and Claude Code 2.1.267.
git clone https://github.com/exPardus/multi-codex.git
cd multi-codex
python3 install.py both
# From any project directory:
cd /path/to/your/project
id=$(mcx spawn "Review src/auth for bugs. Report findings; do not edit files.")
mcx list
mcx result "$id"The installer links mcx and multicodex into ~/.local/bin and installs
the native plugin for both apps using their own plugin CLIs. Both command names
run the same Bash program. Choose just what you need:
| Install | Command |
|---|---|
| Both apps + PATH commands | python3 install.py both |
| Codex + PATH commands | python3 install.py codex |
| Claude Code + PATH commands | python3 install.py claude |
| PATH commands only | python3 install.py cli |
If the bin directory is not on PATH, add this to your shell configuration:
export PATH="$HOME/.local/bin:$PATH"In Codex, open /hooks and trust Loading multi-codex context once. Start a new
session in each app to load the skill and startup context. Invoke $mcx in
Codex or /multi-codex:mcx in Claude Code, or simply ask for background Codex
workers. Claude Code uses your existing Codex login to run the workers.
Keep the checkout. PATH commands are symlinks to it. Use
MCX_BIN_DIR=/your/bin python3 install.py bothfor a different bin directory. Existing unrelated commands are never overwritten.install-codex.pyremains an alias for the Codex installer.
The public repository is a marketplace for both apps. You can install the plugin without the Python installer:
# Codex
codex plugin marketplace add exPardus/multi-codex
codex plugin add multi-codex@multi-codex
# Claude Code
claude plugin marketplace add exPardus/multi-codex
claude plugin install multi-codex@multi-codex --scope userThe plugin bundles the executable, skill, and startup hook. Its hook supplies an
absolute launcher path when mcx is absent from PATH. For the short shell command
everywhere, clone the repo and run python3 install.py cli. A standalone skill is
also available at plugins/multi-codex/skills/mcx;
the plugin is the complete installation, including automatic startup context.
| Command | What it does |
|---|---|
mcx spawn "task" |
Starts a fresh background worker and prints its ID. |
mcx list |
Shows local worker IDs, states, models, effort, and tasks. |
mcx result ID |
Prints a finished worker's final answer. |
mcx steer ID "new instruction" |
Interrupts the current run and resumes that worker's saved conversation. |
mcx stop ID |
Stops the worker's process group; completed jobs are left alone. |
Pass - to read a prompt from stdin. This works for both spawn and steer:
mcx spawn - < task.md
mcx steer "$id" - < correction.mdAssign separate files or independent review tasks when workers share a workspace. These are ordinary shell commands either coordinating assistant can run:
auth=$(mcx spawn "Review src/auth. Return concrete bugs and locations; do not edit.")
api=$(mcx spawn "Review src/api. Return concrete bugs and locations; do not edit.")
# Continue your own work, then inspect completion.
mcx list
mcx result "$auth"
mcx result "$api"
# Follow up in the same worker conversation, even after it finishes.
mcx steer "$auth" "Check whether refresh token expiry changes your findings."result exits with 0 when an answer is available, 2 while work is running,
and 1 for a failed, stopped, lost, or invalid job. Errors point to the logs.
Steering starts a new process in the same conversation; it is not live message injection. The model, reasoning, and approval settings stay the same. If the initial session ID is not available yet, retry shortly. A steer replaces that run's local logs and answer; Codex retains its conversation history.
Run these commands using Codex or Claude Code's background shell facility:
mcx spawn --wait "Review src/auth. Return concrete findings; do not edit."
mcx steer --wait ID "Check whether refresh token expiry changes your findings."--wait prints the ID immediately, then waits for that specific run. It reports
completion on stderr and exits with the worker's exit code: 0 for success,
nonzero for failure or interruption. Read the answer with mcx result ID.
Use your harness's completion notification when supported, or collect its
background process handle. A background command does not itself guarantee an
automatic wake-up in every harness.
When steering, the old waiter exits with an interruption status; background the
new steer --wait command to track the resumed run. Each waiter owns one run.
Cancelling a waiter with TERM, INT, or HUP stops its run and child processes;
cleanup cannot affect a replacement run. A forced SIGKILL cannot run cleanup;
use mcx stop ID in that case.
Do not append shell &/nohup or use id=$(mcx spawn --wait ...) when relying
on harness tracking. Without --wait, the existing detached workflow is unchanged.
| Mode | Behavior |
|---|---|
never (default) |
Workspace-write sandbox; cannot request approval. |
auto |
Workspace-write sandbox; eligible approval requests go to Codex's automatic reviewer. |
unrestricted |
No sandbox or approval prompts (--dangerously-bypass-approvals-and-sandbox). |
Set approval=auto (or never / unrestricted) in either plain-text file:
- Global:
$XDG_CONFIG_HOME/mcx/config, or~/.config/mcx/configwhen unset. - Local:
.mcx/config, or$MCX_DIR/configwhen using a custom job directory.
Local config overrides global config. MCX_APPROVAL overrides both for new workers:
MCX_APPROVAL=auto mcx spawn --wait "Run the tests and report the results."The files accept the approval key, blank lines, whitespace, and # comments;
they are parsed as data, never executed. Keep the local file untracked with the
rest of .mcx/. The selected mode is saved with the job and preserved by steer.
Older jobs without a saved mode retain never. These settings do not modify
your Codex configuration. Auto mode requires Codex automatic-review support;
a reviewer denial is a blocker for the worker to report, not a switch to unrestricted.
The worker default is explicitly gpt-5.6-luna / medium, including when the
coordinator uses Astra. Native subagents default to their worker's saved model and
reasoning effort as well. There is no automatic escalation to a larger model.
# Give a more demanding task a stronger worker.
mcx spawn -m gpt-5.6-terra -r high "Fix the parser and run its tests."
# Or choose defaults for this shell.
export MCX_MODEL=gpt-5.6-terra
export MCX_EFFORT=medium| Model | Suggested tasks |
|---|---|
Luna · gpt-5.6-luna |
Small, clearly defined tasks; the default. |
Terra · gpt-5.6-terra |
Everyday coding that needs more reasoning. |
Sol · gpt-5.6-sol |
Complex or open-ended work. |
Astra · gpt-6-astra |
Deliberate use when specifically requested. |
-r accepts none, low, medium, high, xhigh, or max; the chosen model
must support that setting. See the Codex model guide
for model capabilities and availability.
The plugin’s SessionStart hook adds a short, role-specific instruction in both apps:
| Session | Startup context |
|---|---|
| Coordinator | How to call mcx, provide complete task context, collect results, and choose an appropriate model. |
| Worker | Complete the assigned task, using native Codex subagents if useful. Collect their results, close them, and finish. Do not launch independent workers. |
The hook runs at session start, including resume, clear, compaction, and Claude forks. Worker rules are also
included in every worker input, so they remain present without the plugin hook.
MCX_WORKER=1 is exported and explicitly set in Codex's shell environment;
spawn and steer reject calls from workers and their subagents. Native Codex
subagents are enabled, with the normal Codex session limits. The worker's role
instructions also forbid independent sessions through direct Codex/Claude CLI calls.
This prevents accidental recursive worker spawning. It is not a security boundary
against deliberately changing the environment. Codex still loads its normal
configuration and project instructions, including AGENTS.md.
Hook installation, updates, and removal
Both manifests share hooks/hooks.json and one mcx skill. The startup hook emits
only role, discovery, and model essentials; detailed instructions load when the
skill is used. See context design and official sources.
Codex requires trusting the specific hook definition through /hooks. The
installer migrates the earlier global hook after successful plugin installation,
preserving unrelated hooks and backing up changes as hooks.json.mcx-backup.
It honors CODEX_HOME, and Claude Code honors CLAUDE_CONFIG_DIR through its CLI.
For checkout installations, git pull updates PATH commands immediately. Reinstall
Codex with codex plugin add multi-codex@multi-codex and refresh Claude Code with
claude plugin update multi-codex@multi-codex after a release. For GitHub marketplace
installations, update the marketplace snapshot first:
codex plugin marketplace upgrade multi-codex
codex plugin add multi-codex@multi-codex
claude plugin marketplace update multi-codex
claude plugin update multi-codex@multi-codexRestart sessions after plugin updates and review any changed Codex hook. For local plugin development, see Contributing.
To uninstall plugins:
codex plugin remove multi-codex@multi-codex
claude plugin uninstall multi-codex@multi-codexRemove your mcx and multicodex symlinks separately if you also want to remove
the PATH commands. Job files stay in each project’s .mcx/ until you delete them.
flowchart LR
A["Your shell, Codex, or Claude Code"] -->|"spawn · task + context"| B["mcx"]
B --> C["Independent codex exec"]
C -->|"writes answer, then exits"| D[".mcx / job ID"]
A -->|"result"| D
A -.->|"steer: interrupt + resume"| C
A short-lived wrapper records the Codex process's exit state. nohup, redirected
file descriptors, and a separate process group let the worker run independently
of its caller. stop sends TERM to that group and uses KILL after roughly three
seconds if needed.
Workers edit the caller's current directory with workspace-write permissions
and approval policy never by default. The approval setting can opt into automatic
review or unrestricted execution. --wait adds a waiting launcher that exits
with its child; it needs no polling loop or daemon. The launching environment must permit running Codex.
There is no automatic retry, worktree creation, or file merge handling.
.mcx/
└── <worker-id>/
├── prompt Instructions for the current run
├── model, effort Saved model selection
├── approval Saved approval mode
├── pid, state Process identity and lifecycle state
├── events.jsonl Codex's event stream
├── log Diagnostics
└── result Final answer
Run commands from the same project directory, or set MCX_DIR to an absolute
path to share one job folder across projects. Delete finished job folders when
you no longer need their results. Keep .mcx/ out of your project's Git history.
| Environment variable | Purpose | Default |
|---|---|---|
MCX_MODEL |
Model for new workers | gpt-5.6-luna |
MCX_EFFORT |
Reasoning effort for new workers | medium |
MCX_APPROVAL |
Approval mode for new workers: never, auto, unrestricted |
Local/global config, otherwise never |
MCX_DIR |
Job storage directory | .mcx/ in the current directory |
CODEX_BIN |
Codex executable or wrapper | codex from PATH |
MCX_BIN_DIR |
Installer's command directory | ~/.local/bin |
bash -n mcx
shellcheck mcx
python3 -m unittest discover -s tests -vThe offline tests exercise real process lifecycles using a fake Codex, plus installation and hook preservation. CI runs on Linux and macOS with no credentials or model calls. Real Codex smoke checks have also covered spawning, steering, startup context in both apps, and recursion prevention.
Read CONTRIBUTING.md for the project conventions and CHANGELOG.md for changes.
MIT © 2026 exPardus LLP.
Built by exPardus around Codex's non-interactive CLI.