Skip to content

Repository files navigation

multi-codex — One shell. Independent workers.

Linux and macOS tests Bash 3.2 or newer Linux and macOS No runtime packages

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


Why multi-codex?

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/.

Quickstart

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 both for a different bin directory. Existing unrelated commands are never overwritten. install-codex.py remains an alias for the Codex installer.

Install through plugin marketplaces

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 user

The 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.

Five commands

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.md

A small parallel workflow

Assign 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.

Track a worker with your harness

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.

Worker approval mode

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/config when unset.
  • Local: .mcx/config, or $MCX_DIR/config when 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.

Choose your worker model

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.

Codex knows its role

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-codex

Restart 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-codex

Remove 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.

How it works

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
Loading

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.

Plain files, easy inspection

.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

Development

bash -n mcx
shellcheck mcx
python3 -m unittest discover -s tests -v

The 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.

License

MIT © 2026 exPardus LLP.


Built by exPardus around Codex's non-interactive CLI.

About

Lightweight background Codex workers from Codex or Claude Code. One Bash executable, five commands, native plugins.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages