Skip to main content
Glama

codex-supervisor-mcp

English | 中文

npm version npm downloads license CI node

官网 codex-supervisor.zriyo.com · 给模型读的 llms.txt

让几个 agent 同时改一个仓库,结果是互相覆盖、没人说得清谁改了什么,主线程的上下文还被 worker 的输出塞满。

codex-supervisor-mcp 是一个 Codex MCP server,把「派单」和「记账」从模型上下文里拿出来放到磁盘上:一个主线程(Claude Code、Codex 或任何 MCP 客户端)同时指挥多个 Codex CLI worker,一个 worker 一个 Git worktree,状态落盘到 SQLite,附一个网页看板。

演示:一个 Claude Code 主线程同时派 3 个 Codex worker,各自独立 worktree,并行跑完后合并提交

30 秒真跑:create_codex_worker ×3,三个 worker 各自 worktree 并行,主线程收 3 份 diff 合成一次 commit。

解决什么

问题

做法

几个 worker 互相踩文件

一个 worker 一个 Git worktree,ownedPaths 在派单前查冲突

worker 不是只会改代码

四种 workspaceKind:Git 编辑 git_worktree、只读 read_only_in_place、联网研究 scratch、显式授权的非 Git 写入 in_place_write;非 Git 默认绝不写原目录

worker 的过程塞爆主线程上下文

事件写 data/runs/<taskId>.jsonl,读的时候有 limit / maxChars / kinds 三道闸

主线程读一次状态就顶满

get_orchestration_overview 把全部 worker 压进 7000 字节

进程重启后不知道谁还在跑

supervisor.sqlite 一行一个 work,带 thread_id

换个会话接不上之前的 worker

resume_codex_worker 走 codex exec resume <thread_id>,接的是同一个 Codex 会话

分不清「跑失败」和「进程没了」

状态机把 failed 和 lost 分开

分不清是谁报错

status / overview / overview_delta 带 failure.source 和 failure.code,区分 provider、supervisor_process、workspace_setup、model_output、acceptance、worker_process

worker 说做完了其实没有

派单给 acceptance 验收命令,worker 退出后 supervisor 在它的 worktree 里跑,失败 land 拒绝

看不见一批活现在到哪了

codex-supervisor-web 开一个看板,按 session 看每路 worker 在干什么

改动留在本地没上线

收活默认 land_codex_worker 合回主分支;主线程自己的改动必须 commit + push;部署前用远端 SHA 核对文件真的在线上

worktree / 分支越堆越多

verify_delivery_push 后自动生成 cleanup plan;只对 acceptance passed + push_verified + clean 判 SAFE,主线程显式 apply_cleanup 才删 worktree,branch/证据永远保留

worker 跑的是 codex exec,model 透传:主线程留在 Claude,worker 可以挂 DeepSeek 或任何 Codex 配了 provider 的模型,账单分开算。

Related MCP server: Antigravity MCP Bridge

五分钟跑起来

前置:Node.js 22.13.0 以上,codex CLI 在 PATH 里。macOS、Linux、Windows 都行。

1. 装

npm install -g codex-supervisor-mcp

npm 全局安装在允许执行安装脚本时,会运行 postinstall,给检测到的 Claude Code/Codex 装 skill 并注册 MCP。--ignore-scripts、禁用安装脚本或只运行 npx 不保证自动注册;没看到时先运行 codex-supervisor-setup,再查两端 mcp get。手动注册也可以:

claude mcp add -s user codex-supervisor -- npx -y codex-supervisor-mcp
codex mcp add codex-supervisor -- npx -y codex-supervisor-mcp

重启 Claude Code / Codex。以后不用再手动更,见「更新」。只要 skill 不要 MCP:npx skills add zriyox/codex-supervisor-mcp。

2. 派第一批活

在 Claude Code 里直接说人话,skill 会让它走正确的流程:

把这三个模块的单测补齐,用 codex-supervisor 分三路并行跑,session 叫「补单测」。

主线程背后做的事(你也可以自己调工具):

preflight_codex_worker  同 workspace/base/sandbox/guard 先跑必要 probe
get_worker_preflight    确认 passed;contract 变化就重跑
create_codex_worker ×3  每路带 preflight_id、session_id、ownedPaths、goal
wait_codex_workers       默认等 60 秒,到点返回快照,没完就接着等
get_worker_result ×3     收每路的汇报,带它真跑过的命令和退出码
get_worker_diff ×3       看实际改动;证据对得上再决定是否 land

每路的改动在各自的 codex/<taskId> 分支上。验收和 diff 都过了,主线程用 land_codex_worker 带 commitMessage 合入;worker 不自行提交。

3. 开看板

codex-supervisor-web
# 没全局装也能起:
npx -p codex-supervisor-mcp codex-supervisor-web

打开 http://127.0.0.1:7877。状态目录按 SUPERVISOR_HOME、最近的 .mcp.json、~/.codex-supervisor 的顺序找;端口用 SUPERVISOR_WEB_PORT 改。看板只看,不派单不取消。

长门禁脚本可主动上报阶段:

node "$CODEX_SUPERVISOR_STAGE_CLI" "gate:s3" --detail "integration queue"

current_stage 会出现在 status / overview / wait,终态保留为 last_stage;不要放 token、密码或 DSN。

我自己怎么用

能连 MCP 的都能当主线程,这里只是我的用法。我开两个 Claude Code 会话,一个只管文档,一个只管派活:一个会话又写详设又盯 worker,上下文两小时就满。

谁

开在哪

管什么

我

定需求,拍板,看汇报

规划会话

需求和文档仓

聊需求,写详设,每一块活写一份任务书,末尾附一段发给主脑的话

主脑会话

代码仓的一个 worktree

读任务书,派 Codex worker,核每路的 diff,把结果填回任务书,向我汇报。不写业务代码

Codex worker

各自的 worktree

一个 worker 做一个能独立验收的功能包,在远端机器上修改、运行验收。不 commit、不 push、不合并

两个会话之间只传一段文字,粘进主脑会话用 /goal 接上。结构固定:

【角色】   你是主脑:读文档和代码,派 worker,核结果,更新文档,向我汇报。不写业务代码。
           派活和盯进度用 codex-supervisor 这个 skill,开工前先加载它。
【背景】   这一块为什么做,上一块留下了什么
【先读】   哪几份文档的哪几节。几份说法不一样时以哪份为准
【仓和分支】工作目录在哪,各分支现在在哪个提交,哪些分支只读
【做什么】 照任务书第几节那张表做。按能独立验收的功能包拆,表里没有的不做。worker 不自行 commit
【派活】   先 search_works 看有没有派过,别重复
           整批用同一个 session_id
           改同一批文件就串行,写入范围不重叠才并行。ownedPaths 覆盖实现、测试、路由、DI、配置和迁移
           依赖先写 workspaceSetup;写 worker 先过同 contract 的 preflight
           task 写全:背景、文档出处、完整写集、验证命令、输出格式
           验证命令同时填 acceptance;worker 用 CODEX_SUPERVISOR_ACCEPTANCE_CLI 自查
           worker 交回来先看 diff。它说过了不算,你看到才算
【构建和测试】全走远端机器,本机不跑
【红线】   不改什么,不推什么,不读什么
【必须停下来问我】
【汇报】   中文,表格优先,报哪几项,然后停下来等我

主脑一轮下来调的工具:

search_works            查这批活派过没有
preflight_codex_worker  同环境跑 probe,确认 sandbox / guard / base / cache 真可用
get_worker_preflight    核 probe 的实际 command evidence;passed 才能派目标 worker
create_codex_worker     一个功能包一个 worker,同一个 session_id,ownedPaths 不重叠
wait_codex_workers      60 秒一轮,compact: true,没完接着调
get_worker_result       它说自己做了什么,verification 里是它真跑过的命令
get_worker_diff         它实际做了什么
ask_codex_worker        对不上就问它为什么,只读,不动它的线程
resume_codex_worker     要改就继续同一线程;主线走远了带 rebaseOnto
land_codex_worker       核过了,带 commitMessage 代提交并落进集成分支

功能包在 land 前仍可 resume_codex_worker 继续修改。真正需要拆开的原因是写集冲突、依赖顺序或独立验收,不是“每一步都必须换一个模型线程”。

看板里有什么

位置

内容

左栏

每个 session 一行:标题、worker 数、几路在跑、最近活动。左下角是版本和更新提示

session 页

统计(总数 / 运行中 / 完成 / 失败 / 丢失),有 worker 在跑时列每路正在执行的命令

worker 台账

一行一路:状态、标题、正在跑的命令或最后一句汇报、耗时、改了几个文件、跑了几条命令

worker 抽屉

七个 tab:概览、汇报、改动、命令、事件、任务书、旁问

旁问

对这路 worker 提问,就是 Codex 的 /btw:从它的线程 fork 出只读旁路会话来答,不碰它正在跑的活。多轮、可中断、换标签页回来自动接上

浅色深色跟系统走,没有外网资源。

工具

39 个。

工具

入参

作用

check_workers

无参

返回新终态、故障及长线程交接提醒;同一 run 的 handoff 只提醒一次,不中止或复制活跃 worker。已死的第1轮 lost / no_work / invalid_report 最多恢复一次;用宿主定时调用及独立 CODEX_SUPERVISOR_OBSERVER_ID 接回

overview_delta

cursor

主线程默认轮询入口:只返回 active / needs_attention / ready_to_land / ready_to_clean、cursor 后变化、短版 attention_reason / next_action 和 next_cursor;不返回全量历史、prompt、diff、event 或 worker capsule

check_acceptance

cwd, acceptance, baseRef, timeoutMs

派单前实际运行给定验收命令,不建 worker,不证明 worker 完成;数量 grep 会提示不能证明失败名单和必跑执行

preflight_codex_worker

cwd, workspaceKind, inPlaceAuthorization, workspaceSetup, ownedPaths, probeCommands, baseRef, sandbox, allowedCommands, context, contracts, networkAccess, writableRoots

用与目标 worker 相同的 workspace/base/sandbox/guard 起短 probe worker;它必须实际跑完每条 probe command。probe 自动获得本次 guard-only 允许,但不进入目标 worker contract;联网和凭据目录仍须显式授权

get_worker_preflight

task_id

返回 probe 的实际 command evidence、运行环境 contract hash、worker outcome 和 running/passed/failed;probe 全部执行通过时,报告 JSON 错误或已 exit 0 的 close-handler 缺失只留诊断,不误判环境失败

create_codex_worker

task, cwd, workspaceKind, inPlaceAuthorization, workspaceSetup, ownedPaths, goal, preflight_id, forbid, allowedCommands, context, contracts, externalOutputs, networkAccess, writableRoots, maxRunMs, maxTotalMs, acceptance, session_id, session_title, session_note, dependsOn, baseRef, sandbox, model, reasoningEffort, title, skipGitRepoCheck

Git 默认隔离 worktree;非 Git 写入必须选 scratch 或有授权、paths、acceptance 的 in_place_write。workspaceSetup 在起 worker 前链接依赖、初始化子模块、跑 prepare;preflight_id 给了就必须是通过的同环境 probe

create_codex_followup_worker

task_id, followup_prompt, session_id, session_title, title, cwd, sandbox, model, ownedPaths, forbid, allowedCommands, context, contracts, externalOutputs, networkAccess, writableRoots, workspaceKind, workspaceSetup, goal, baseRef, acceptance

新会话继承父任务上下文:未 land 用父分支当前提交,已 land 用当前集成 HEAD,显式 baseRef 优先。未提交父改动不复制;不支持 preflight_id、dependsOn、skipGitRepoCheck

resume_codex_worker

task_id, prompt, rebaseOnto, acceptance, context

接同一个 Codex 会话继续跑,thread_id 不变。原生 goal 仍 active 或 goal 状态库不可判定时,本轮自动省略 output schema,避免 ActiveTurnOutputSchemaMismatch。rebaseOnto 先把 worktree 挪到主线新头(stash、跳过已合入补丁、重放新增提交、放回),冲突原样退回不起 worker

wait_codex_workers

task_ids, mode(any/all), timeoutMinutes, timeoutMs, allowLongWait, compact, emitProgress, includeEvents, eventLimit, eventMaxChars, eventKinds

等终态,单次预算默认最多 60 秒,只有确认宿主超时允许后才传 allowLongWait: true。返回实际/请求预算与 timeout_capped,termination_reason 区分 settled / budget_exhausted / client_cancelled;emitProgress 可选,每路摘要用 compact

get_orchestration_overview

status, limit

全部 worker 的状态表,封顶 7000 字节。带 version 和 update

get_worker_result

task_id, limit, maxChars, includeFiles

worker 自己的汇报,默认截 6000 字节、truncated 提示读全。acceptance 是 supervisor 替你跑的验收过没过,verification 是它自己跑过的命令和退出码,base_behind 是主线走了多远(contains_base: false 时 behind 为 null,那是换了线)

get_worker_diff

task_id, file, hunk, pageSize, cursor, maxChars, paths

worker 实际改了什么。默认完整文件索引与 hunk 数;按 file + hunk/cursor 分页读 patch。显式 maxChars 且不传 file 保留旧整份限流模式

ask_codex_worker

task_id, question, timeoutMs, maxChars, fresh, end

旁路问 worker 一句。线程 fork 成只读侧会话,没网络、没 MCP 工具,worker 本身不动。worker 被 resume 过会自动换新 fork,fresh 强制换,end 删

land_codex_worker

task_id, onto, commitMessage, includeFollowupParents, commitMessages, ignoreAcceptance, allowOutsideOwned

把 worker 在 codex/<id> 上的提交 cherry-pick 到派单目录的当前分支。目标要干净,冲突回滚,验收 failed 拒绝;报告格式错不再单独阻止显式 land。commitMessage 先替当前 worker 把未提交改动提交成一笔;includeFollowupParents 按 root-first 落地整条 followup 链,commitMessages 给链中各路提供各自的 checkpoint 提交说明

verify_delivery_push

task_id, remote, branch

fetch 指定 remote branch 并证明 landed_head 已可达;只读验证,不会 push 或部署。通过后记录 push_verified 并生成 cleanup plan

cleanup_plan

task_ids, project_root

生成 15 分钟有效的 SAFE / REVIEW / BLOCKED 计划,含原因、fingerprint 与回收空间估算;SAFE 必须 acceptance passed、push verified、干净且无活跃依赖/进程

apply_cleanup

plan_id, item_ids

只在未过期计划上二次校验 SAFE item、重新 fetch remote 并确认 landed SHA 仍可达后执行 git worktree remove/prune;保留 branch、task、events、JSONL、artifacts

cleanup_history

task_id, limit

查询 cleanup 的计划、理由、fingerprint 和实际回收记录

get_worker_summary

task_id

一段话:goal、状态、改动、最后一条命令和消息

get_codex_worker_status

task_id, includePrompt, promptMaxChars

单个 worker 的状态细节

get_codex_worker_events

task_id, limit, maxChars, kinds

原始事件流

get_context_snapshot_meta

task_id

只读 worker context 的 snapshot ID、fact IDs、token 估算和排除项;不返回 capsule 正文或历史记录

get_fact

fact_id

按 ID 审计原始 fact 版本及 effective_state;撤销和自动过期均保留原版本

search_worker_facts

task_id, query, limit, cursor

只检索当前 work、显式依赖和路径命中 repo scope 的 verified facts;返回 coverage / next_cursor,不返回 raw history

get_worker_evidence

task_id, limit

返回某 worker 的有界 event 元数据和 retained artifact 索引;按需再点查 artifact / event

get_artifact

artifact_id, maxChars

读取一个 supervisor-managed evidence artifact;不影响 worker capsule 或主线程自动上下文

promote_worker_fact

fact_id, scope, watchedPaths, expiresAt

主线程显式把 candidate 追加为 verified fact;repo scope 必须声明 watchedPaths,worker 不能自升真相

revoke_worker_fact

fact_id, reason

主线程审计后追加撤销版本和事件,不覆盖原 fact;被撤销事实从 search / capsule 排除

create_independent_verifier

task_id, title

为已结算 worker 创建独立 read-only / 无网络 verifier;只给目标与当前 worktree,不给原 report/candidate facts

record_independent_finding

verifier_task_id, verdict, reason

记录独立 verifier 的 passes/fails/inconclusive finding,写 subject event 和 retained artifact

resolve_independent_finding

verifier_task_id, resolution

记录 finding 的收口方式,保留原 finding 与证据

get_independent_review

verifier_task_id

查询 subject / verifier / finding / resolution 的持久关联

get_worker_goal

task_id

派单时记的 goal + Codex 原生 goal(token、用时)

list_codex_workers

status, includeHistory, includeDetails

列 worker,默认只看在跑的

get_session_works

session_id

一个 session 的全部 worker。主线程重启后靠它找回那批活

describe_session

session_id, title, note, objective, default_acceptance, approval_state, expected_revision

给 session 记标题和说明

search_works

query, limit

在 title / goal / prompt / last_message 里找子串,从新到旧

check_for_update

force

问 registry 有没有新版本

cancel_codex_worker

task_id

终止 worker。跨进程按 pid 兜底,先确认那个 pid 跑的是 codex

MCP schema 必填两个:ownedPaths 和 goal.objective。写 worker 还必须通过上面的 preflight 工作流门禁;preflight_id 暂时保留为 optional 只为兼容旧客户端,不是正常流程可以跳过。ownedPaths 的写冲突在派单时预留,运行时 guard 会查直接写入,land 会再查完整 diff。

acceptance 在 Bash 中启用 errexit 和 pipefail:未处理的失败会停止检查,npm test | tail 中的测试失败也会保留。worker 自查必须运行 node "$CODEX_SUPERVISOR_ACCEPTANCE_CLI",它只读 supervisor 状态库中的验收契约,不需要写数据目录;不要手抄到 zsh,变量拆词等交互壳差异不会污染证据。写 worker 不能只用 test -s、test -f 或 [ -e ] 这类文件存在性命令交付;要加真实 test、endpoint probe 或结构化执行证据。识别到的 test runner 输出 no tests to run / [no test files] 时,即使退出码是 0 也判失败。预期失败用 if 或 || 显式处理;超时始终判失败,即使命令收到终止信号后退出 0。Windows 需要 Git for Windows 的 Bash;找不到会报错。显示的输出会裁剪,退出码不会因此改变。

package.json 仓库里,如果 acceptance 使用 npm、pnpm、vitest、vue-tsc、eslint、nuxi 等本地 JavaScript 工具,而派单没有 workspaceSetup,会直接拒绝为 workspace_setup_required。这条是 runtime 硬门禁,不再靠模型记得手工链接依赖。

前端 worktree 的标准配置:

{
  "workspaceSetup": {
    "links": [{ "path": "node_modules", "source": "node_modules" }],
    "submodules": true,
    "commands": ["npx nuxi prepare"]
  }
}

同一份配置要同时传给 preflight_codex_worker 和目标 create_codex_worker,否则 runtime contract 不匹配。

workspaceSetup.links.source 按派单的 cwd 解析,也可以直接写绝对路径;path 始终是 worktree 内的相对目标。源目录必须先存在。

create_codex_followup_worker 在父任务未 land 时继承其 codex/<parent> 分支的当前提交,父任务已 land 则从当前集成分支 HEAD 开始;显式 baseRef 优先。父 worktree 里没提交的改动仍只属于父任务,父 checkpoint 丢失时返回 followup_checkpoint_missing。需要整条接续链落地时调用 land_codex_worker({includeFollowupParents: true}),主线程先审各路 acceptance 和 diff,工具再按 root-first 落地;途中失败保留此前已落地的结果,修复后可重复调用。

worker 和 run host 都已退出时,当前 run 的 durable turn.completed 可以恢复 completed 和退出结算,独立保留 acceptance 的通过、失败或中断状态。缺失验收结果标记为 interrupted,仍需重新验收后才能 land;恢复不会删除 worktree 或自动重跑 worker。

链式 landing 会跳过已证明在目标分支上的提交和零改动祖先;ignoreAcceptance / allowOutsideOwned 只作用于指定的 leaf,不自动扩大到祖先。

普通 worker 启动时会关闭它继承到的 codex-supervisor MCP,不能再派 worker、resume、cancel 或改编排状态;主线程是唯一编排者。其他业务 MCP 不受影响;旁问 fork 仍关闭全部 MCP,因为它只允许只读回答。

session_id 只负责批次、默认门禁和审批,不再把同批 worker 的标题、汇报或 session objective 自动塞进新 worker。worker 只收到内部编译的 context capsule:L0 只标明 branch 与 acceptance 来源(不塞命令正文)、自身身份/任务、显式依赖的最小交付摘要和路径/SHA 命中的 verified facts;raw event、完整 diff、历史报告、candidate facts 都只可按需读取。repo fact 只有两个 checkout 的 canonical origin、repo-relative watched path 和 base SHA 同时匹配时才跨 checkout 可见;无可识别 origin 就保持 work-scoped。事实的 base SHA 不再覆盖、watched path 发生 Git diff、context 输入内容 hash 或非 Git in-place manifest 漂移时会自动追加 expired 版本并从 capsule 排除。主线程只看 get_context_snapshot_meta,需要证据时再显式 get_fact / get_worker_result / get_worker_diff。

worker 的最终 JSON 报告会先记录为该 run 的 candidate fact,不能跨 work 自动注入;supervisor acceptance 通过后才生成当前 work 的 verified outcome,并带 report/acceptance event 来源、base SHA 与 watched paths。schema-free resume 的纯文本报告只保留为 candidate,不把合成的空数组当作已验证事实。push proof 另存为 retained artifact,verified fact 可回指该 artifact。验收失败、未配置验收或 worker 自报完成都不会升级成共享真相。

交付状态分开:acceptance 通过只是 verified,land_codex_worker 只是 landed,仍不代表远端有这笔提交。需要显式 verify_delivery_push fetch 并校验 landed_head 已在目标 remote branch 上,才是 push_verified;它会自动生成 cleanup plan,SAFE 项进入 cleanup_eligible,但永远不会自己删除。该工具绝不代替用户执行 push 或部署。

worker 进程和 supervisor 验收子进程都包含当前 CODEX_SUPERVISOR_TASK_ID、CODEX_SUPERVISOR_BASE_COMMIT 和 CODEX_SUPERVISOR_RUN;分别是当前任务、运行基线和次数,rebase/resume 后两边一起更新。

结构化验收项用 {command, reportPath, baseline}。baseline 包含 identity.base_commit、failures(test_id/kind/signature)和 required;报告包含 complete、identity、failures、executed、skipped,以及本次 CODEX_SUPERVISOR_CHECK_ID。必跑用例缺失/跳过、旧报告、失败名单变化都拒绝通过,原始退出码保留。reportPath 必须在工作目录内;测试报告可能写文件,要用忽略的临时目录,避免把报告合入。

落地前按真实 diff 核对 ownedPaths,越界拒绝且不提交草稿;只有用户明确授权时才用 allowOutsideOwned。

worker 的 acceptance 在代提交之前执行,应检查功能和测试;test -z "$(git status --porcelain)"、提交数量和提交信息检查由主线程放到 land 后执行。验收失败先核对当前 run 的具体失败项,不能仅因报告更新、外部测试通过或主线程补过提交就视旧失败为已解决;契约冲突交规划/集成负责人修订并重新验收,不手工 cherry-pick 绕过。

同 session 的 default_acceptance 自动加到每路本地检查前;resume 会取最新策略。describe_session 返回 policy_revision,改目标/门禁可传 expected_revision 防旧窗口覆盖;waiting_user 拒绝派单与恢复,approved 后再继续。回执host_goal_sync包含按当前策略生成的/goal命令;宿主已有原生goal时用/goal替换条件,支持ProposeGoal时可提议同一条件并走宿主批准。条件要求读取最新session revision及批准范围;MCP不会偷偷修改或禁用宿主Stop hook。

wait 默认预算60秒、默认compact,过长请求也限制为60秒,返回 requested_timeout_ms / timeout_ms / timeout_capped。确认客户端允许长调用后可显式 allowLongWait: true;emitProgress 只在请求且客户端传 progress token 时通知,不能延长宿主的硬超时。已有后台 wait 就接回它,不重复开长 wait;长期监控用宿主定时调用 check_workers。

每路临时注入随包PreToolUse守卫:apply_patch核对全部目标路径(含rename和symlink),forbid拒绝红线;安全只读检查(rg/cat/sed无-i/git只读/jq无-i/find无-exec或-delete)默认允许且不占其他 worker 的写路径,写入/执行/有副作用的 Shell 命令必须显式声明。声明的验证脚本以派单者权限执行,可有副作用,不能当作任意程序的文件沙箱。guard策略随resume/followup继承,不写全局hooks。空跑write run按本轮输出前后内容和命令判断,no_work进入needs_attention;只读任务不因没改文件判空跑。

守卫同时拦截 create_goal 的预算:派单未传 goal.tokenBudget 时,worker 必须完全省略 token_budget;模型自行填写 0、1 或 null 会被拒绝,不会被误当成“不限预算”。显式传预算时只允许逐值一致,缺失或改动都拒绝。原生 goal 仍用于完成状态与 token 用量统计。

没有独立 apply_patch 工具的模型(实测 Codex 0.162 + DeepSeek/cc-switch)把补丁当 shell 命令发过来:apply_patch <<'EOF' ... EOF。守卫认这个形状,用同一套 ownedPaths 规则判每个目标路径,所以这种模型也能改文件;未加引号的 heredoc、后面还接 &&/; 的都拒绝。

allowedCommands 里以 * 结尾的条目是前缀匹配(如 go test ./internal/* 覆盖 go test ./internal/service -run TestX),只对没有 shell 元字符的单条命令生效。编辑器 worker 的只读白名单覆盖 grep/sed(无 -i)/find(无 -exec/-delete)/jq(无 -i)/awk、git 只读子命令和 cmd | head|tail|wc|sort|uniq 纯读管道;tee、重定向、env 仍拒。守卫不是文件沙箱,漏网的写入只会落在 worker 自己的 worktree,land 会拒。

守卫按 worker 形状放权:git_worktree 编辑 worker 只放声明过的命令和简单读取;read_only_in_place 无写入无网络;scratch 的联网草稿只能写在 SUPERVISOR_HOME/scratch/<taskId>;in_place_write 必须有显式授权、ownedPaths 与 acceptance,并保存前后 manifest。非 Git workspace-write 没写 workspaceKind 会拒绝,绝不默认写用户目录。

check_workers在状态协调后,对已结束的第1轮lost/no_work/invalid_report原子resume一次(invalid_report只要求重发裸JSON,不重做活)。如果当前 run 已经持久化 turn.completed,只是 run host 没落 exit code,supervisor 会从 durable event 恢复为 completed 并保留 report/attention 证据,不再误标 lost。两轮同 fingerprint 的无输出/无命令会升级为 two_stall 和 needs_attention,不再自动重试;审批、认证、权限和quota等待也不重试,返回recoveries记录。worker最终输出要求JSON result/verification/not_done;解析只做安全修复:字符串字段归一成 string[],以及唯一缺少的 ]/},伪造字段仍拒绝。报告只是摘要;invalid_report 保持 completed 生命周期和 attention,不否定同 run acceptance 和真实 diff,显式 land 仍可用;旧历史标legacy_text。

context用绝对文件路径与可选sha256声明材料,最多20份、与contracts合计6000字;文件不超过5 MB。首次派单记录实际哈希,resume校验原材料未变,需要新材料时显式传context。handoff最多1800字/16行,截断明确标记;完整约束和引用单独保留,材料不授予写权限。

确需共享写入时声明externalOutputs:[{path,sha256?}]并配置acceptance。目标必须是绝对文件路径、每份≤1 MB;记录本轮前后哈希和有界内容,result/diff标shared_file_already_written_not_cherry_pick,不能通过land合入外部文件。外部目标参与归属冲突与hook;验证脚本的共享副作用由派单者负责。

workspace-write默认networkAccess:false;需要ssh/联网验证显式true,随resume/followup继承,不以danger-full-access代替。maxRunMs限制单轮、maxTotalMs限制从派单开始的总时长;超限中止worker并保留needs_attention/partial work,不自动重试。wait预算不改变这些quota。

沙箱除工作区和临时目录外,自动放开 OS cache 目录(macOS ~/Library/Caches、Linux ~/.cache、Windows %LOCALAPPDATA%)、home 下已存在的工具链缓存目录(.cargo/.npm/.yarn/.pnpm-store/.bun/.m2/.gradle/.nuget/.ivy2/.bundle/.composer/.pub-cache/.mix/.hex/.stack/.cpanm/.deno/.conda、go/pkg)。Go build cache(平台默认 go-build 或显式 GOCACHE)单独 realpath 并放行真实目录,因此 symlink 指向外置盘时也可在 worker sandbox 使用;凭据目录一律不自动放开(.ssh/.gnupg/.config/.aws/.docker/.kube/.netrc/.git-credentials/~/Library/Keychains):ssh 连服务器要写 known_hosts、kubectl、推私有镜像、签名提交这类需求,派单时显式传 writableRoots,只在这一路生效。SUPERVISOR_NO_AUTO_CACHE_ROOTS=1 关掉全部自动缓存根,显式声明的照常生效。Codex 拒绝带软链的可写根,所以自动 cache 和 writableRoots 都先按 realpath 解析;解析不出无软链路径的根直接不传。其他 cache 放在别处(~/.m2、~/.gradle、vendor 镜像)就传 writableRoots:[绝对路径],要求是已存在目录、最多 20 个、只对 workspace-write 生效、随 resume/followup 继承;只读复用就不用传。

运行前核验Codex CLI是否具备hooks/output-schema(要求0.162+);能力不足返回start_failed,wait可正常结算。get_worker_goal.native_goal_read区分missing_goal、missing_database、locked和read_error,不能把读取失败当没建goal。原生budget/usage限制也进入needs_attention。cleanup保留ignored artifacts、共享证据和未解决attention。

ownedPaths预留和任务入库在同一事务内,跨MCP并发派单/恢复不能抢同一输出;验收或退出尚未结算时仍保留归属。Git工作区隔离创建失败明确报错,不退回主目录执行;非 Git scratch 也不落回原目录。

清理先 cleanup_plan(CLI 对应 npm run cleanup -- --dry-run)分类 SAFE / REVIEW / BLOCKED;SAFE 要求 acceptance 明确 passed、push_verified、干净、无活跃进程/依赖、Git 注册和路径归属可证明。apply_cleanup 会在删除前重验 fingerprint 并 fetch remote 再验 landed SHA;CLI 只能 npm run cleanup -- --apply --plan <plan_id> --item <item_id> 显式选项执行。branch、task row、event、JSONL、artifact 永远保留;脏、未验收、未合、未 push、force-push 回退、lost/failed 和证明不足的一律不删。

和 Claude Code 的 subagent 有什么区别

文件隔离不是差别:subagent 自己也能开 worktree。差别在模型和进程。

Claude Code subagent

codex-supervisor worker

能跑什么模型

只能选 Claude

model 透传给 Codex CLI,DeepSeek 也能挂

干活的是谁

Claude Code 自己

独立的 codex exec 进程

两路写同一个文件

靠 worktree 隔开,没有路径声明

派单前查 ownedPaths 交集,重叠直接拒

主线程进程挂了

主窗口无法收活

独立运行进程继续记录 worker 和验收;新窗口用 session_id 收回同批结果

谁能驱动

只有 Claude Code

任何 MCP 客户端

看过程

只有它返回的结论

原始 JSONL 和网页看板

状态机

status

含义

queued

已派单,未启动

running

运行中。phase:starting → thinking → command → editing → reporting

completed

成功

failed

非零退出码、turn.failed、spawn 失败

cancelled

被 cancel_codex_worker 中断

lost

worker 被外部信号杀掉、运行进程失踪、或者行写了但进程从没起来。resume_codex_worker 接回

终态分两步落盘:turn.completed 先把 status 置成 completed,进程退出后才写 exit_code;wait_codex_workers 等到 exit_code 落了才返回。Windows 没有信号,外部 kill 只报 failed 加退出码。Codex 原生 goal 的 paused / blocked 算 running 并进 needs_attention,usageLimited / budgetLimited 算 failed。

状态存储

默认在 ~/.codex-supervisor/:

文件

内容

data/supervisor.sqlite

tasks(一行一个 work)、task_events、sessions、side_sessions / side_turns(旁问)

data/runs/<taskId>.jsonl

Codex --json 的原始输出

data/update-check.json、auto-update.json

更新检查和后台更新的记录

worktrees/<taskId>/

该 worker 的 Git worktree

changed_files 按 worktree 的真实 diff 算,worker 用 shell 改的、自己 commit 过的都能看到。中文文件名原样返回。老版本的库第一次打开自动迁移。

环境变量

变量

默认

作用

SUPERVISOR_HOME

~/.codex-supervisor

状态根目录。MCP 和看板要指同一个

CODEX_HOME

~/.codex

只读,读 Codex 原生的 goals_1.sqlite 和 MCP 配置

CODEX_BIN

codex

Codex CLI 路径。Windows 上 .cmd shim 自动绕开

GIT_BIN

git

Git 路径

SUPERVISOR_WEB_PORT / SUPERVISOR_WEB_HOST

7877 / 127.0.0.1

看板监听地址

CODEX_SUPERVISOR_NO_UPDATE_CHECK

未设

1 关闭更新检查

CODEX_SUPERVISOR_HANDOFF_TOKEN_THRESHOLD

300000

native goal 累计 token 达到该值时 status/overview 标记 handoff_recommended;设 0 关闭

CODEX_SUPERVISOR_REGISTRY

https://registry.npmjs.org

更新检查和自动更新用的 registry

CODEX_SUPERVISOR_UPDATE_TIMEOUT_MS

4000

等 registry 的上限

CODEX_SUPERVISOR_NO_AUTO_UPDATE

未设

1 关闭后台自动更新(只提醒)

CODEX_SUPERVISOR_SKIP_SKILL_SYNC

未设

1 关闭 server 启动时的 skill 同步

CODEX_SUPERVISOR_SKIP_SETUP

未设

1 跳过 postinstall 的自动安装

CODEX_SUPERVISOR_NPM

未设

自动更新用的 npm,默认用当前 node 自带的

GUI 客户端(Claude Desktop、Cursor、Windsurf)不在本安装器的自动注册目标中,自己把这段加进它的 MCP 配置文件,PATH 里常常没有 codex,显式给 CODEX_BIN:

{
  "mcpServers": {
    "codex-supervisor": {
      "command": "npx",
      "args": ["-y", "codex-supervisor-mcp"],
      "env": { "CODEX_BIN": "/usr/local/bin/codex" }
    }
  }
}

更新

不用手动更。server 启动时后台查一次 registry,有新版就起独立进程 npm i -g 到同一个全局路径;正在跑的会话不受影响,下一个新会话就是新版。只对 npm i -g 装的那份生效,git 源码和 npx 起的不碰。skill 也一样,每次启动刷到已有的 skill 目录,改过的先备份成 SKILL.md.bak-<时间戳>。

装失败(全局目录要 sudo)时 update 字段带原因,手动 npm install -g codex-supervisor-mcp@latest。0.6.1 及以前只提醒不自动装,手动升一次就进自动了。换 Node/安装前缀后,setup 会修复本包生成的旧入口,并读回核对 command/args;已有自定义、disabled、project配置保留并提示处理,不擅自覆盖。重跑安装:codex-supervisor-setup(--skill-only / --mcp-only / --dry-run)。手动注册失败返回非0,自动安装保持成功但打印warning;skill写入失败仍继续尝试MCP注册;没找到CLI时可设 CLAUDE_BIN / CODEX_BIN。skill路径跟随 CLAUDE_CONFIG_DIR / CODEX_HOME。

卸载:

npm uninstall -g codex-supervisor-mcp
claude mcp remove -s user codex-supervisor
codex mcp remove codex-supervisor
rm -rf ~/.claude/skills/codex-supervisor ~/.agents/skills/codex-supervisor ~/.codex/skills/codex-supervisor ~/.codex-supervisor

Windows

  • npm 装的 CLI 是 codex.cmd,Node 拒绝直接 spawn 它。这里绕到 node_modules/@openai/codex/bin/codex.js 用 node 起,不用 shell: true,那样取消时只杀得掉 shell。

  • 跨进程取消用 taskkill /PID <pid> /T /F 杀整棵树,先确认那个 pid 跑的是 codex。

  • 除 PATH 外还探 %APPDATA%\npm、%LOCALAPPDATA%\pnpm、%LOCALAPPDATA%\Volta\bin、%ProgramFiles%\nodejs。

排查

症状

原因

处理

claude mcp list 里没有

装法不跑 postinstall

codex-supervisor-setup 或手动 claude mcp add

派单报 codex only resolved to a shell shim

Windows 只找到 .cmd,背后的包入口没了

重装 @openai/codex,或 CODEX_BIN 指到 codex.js

worker 一起来就 failed,spawn codex ENOENT

进程 PATH 里没有 codex

配置里设 CODEX_BIN

Cannot find module 'node:sqlite'

Node 低于 22.13.0

升 Node

worker lost

worker 或独立运行进程中断

查事件后用 resume_codex_worker 接回

worker 说 git add 报 index.lock: Operation not permitted

默认沙箱把 .git 设成只读,这是正常边界

保持 worker 只改和验收,收活时 land_codex_worker 带 commitMessage

ownedPaths overlap with active worker(s)

两路认领了同一片路径

改拆法,或先取消占着的那路

看板打开是空的

看板和 MCP 的 SUPERVISOR_HOME 不是同一个

在配了 .mcp.json 的项目目录里起,或显式传同一个 SUPERVISOR_HOME

port 7877 ... is already in use

已经有一个看板在跑

直接开它,或 SUPERVISOR_WEB_PORT=8080 再起一个

已知限制

  • 每次运行由独立进程读取 worker 输出、落状态和执行验收,直到结算后退出。派单 MCP 被 kill 后这些工作继续;新窗口用 get_session_works 收结果。若运行进程也被杀,保留 worktree 和 thread_id,核对 lost/interrupted 后恢复。

  • 默认 workspace-write 沙箱里 worker 提交不了(Codex 把 .git 设成只读)。收活时 land_codex_worker 带 commitMessage 替它提交;不要为了提交改用 danger-full-access。

  • worktree 从一个提交切,你工作区里没 commit 的东西不在里面。

  • 只隔离工作目录。临时目录、数据库、端口是共用的。

  • ownedPaths 的冲突预留只在派单时计算;运行时 guard 会拦直接文件写入,land 会再查完整 diff。声明脚本仍可能产生清单外副作用,不能把它当完整文件系统沙箱。

  • 验收是 acceptance 里写了什么就查什么。没写的事它不会替你查,verification 只是 worker 自己跑过的命令,剩下的靠主线程看 diff。

  • 一次 wait_codex_workers 等不到底,客户端的 MCP 工具超时是硬墙,靠反复调。

  • search_works 是子串匹配,几百条够用。

Roadmap

做完的:CODEX_BIN / SUPERVISOR_HOME / GIT_BIN;status 和 phase 拆开;ownedPaths / goal / dependsOn;thread_id 落库 + resume_codex_worker;并发和多进程写库;session_id、search_works、原生 goal;Windows;网页看板;baseRef;收活三件套 get_worker_diff / ask_codex_worker / land_codex_worker;后台自动更新。

运行生命周期已独立于 MCP;每路结算后退出,不需要常驻全局 daemon。

不做的:向量检索(子串匹配在这个规模更快、零维护)、usage_count 排序(实测 80 个 work 里只有 2 个被回头引用过)。

开发

npm install
npm test               # fake-codex 回放,快且确定
npm run test:edge      # 只跑 test/edge
npm run test:real      # 真 codex CLI 端到端
npm run web:dev        # 看板开发,/api 代理到 7877
npm run web:build      # 打包到 web/dist,发 npm 前自动跑

CI 跑 Ubuntu / macOS / Windows,另加一个 Node 22.13.0 的 job 卡 engines 下界。

参与贡献

看 CONTRIBUTING.md。安全问题走 私密通道,见 SECURITY.md。

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables coordinating Claude Code and Codex across separate Git worktrees with shared issue ownership, file reservations, messages, and explicit handoffs.
    677 PyPI
    3
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables Codex or Claude Code to orchestrate persistent Antigravity CLI workers as independent implementers and testers within restricted workspace roots. It supports asynchronous task dispatch, progress polling, result inspection, follow-up messages, and cancellation with bounded, audited local event logging.
    32 npm
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables Codex to orchestrate persistent Pi RPC workers over a local MCP server, spawning dev, explore and review agents in isolated git worktrees or in place. Codex can inspect status, activity, token/cost metrics and real diffs, then merge only the accepted work and clean up idle workers.
    13
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables Codex to supervise one or more local Pi coding-agent workers through bounded task execution, state polling, steering, aborting, and listing. Tasks can run in a direct working directory or isolated Git worktree while Codex remains the planner and reviewer.
    MIT