Skip to content

[Bug] Codex 集成的四个问题(2.0.28):默认 scope 回归、丢失 session-end hook、strict-config 被自写字段卡住、插件 MCP 路径写死 macOS #621

Closed

Description

@artist-coding

一句话

在 Linux 上按官方文档接 Codex,会连着撞上四个问题:插件的 MCP server 装得上但起不来,
setup-hooks 默认写到了当前工作目录而不是 ~/.codex,Codex 侧只剩「回忆」没有「记录」,
以及 Evolver 自己写出来的 config 过不了 codex --strict-config。

其中第 2、第 3 条相对 1.x 是行为回归 —— 我装了 @evomap/evolver@1.94.0 做了对照实测。

环境

  • @evomap/evolver 2.0.28(对照组 1.94.0)
  • evolver-codex-plugin @ cbff921(manifest 0.2.0)
  • codex-cli 0.153.0,Linux x86_64(Debian 13),node v24.20.0

以下每一条都是在全新的临时 HOME + CODEX_HOME 里复现的,和我本地的测试环境无关。


1. 插件的 .mcp.json 写死了 macOS Homebrew 的 node 路径

plugins/evolver/.mcp.json(evolver-codex-plugin 仓库,源码 HEAD 里就是如此):

"command": "/opt/homebrew/opt/node@22/bin/node"

这个路径在 Linux / Windows 上不存在。Codex 仍然会把 server 注册成 enabled,
但永远 spawn 不起来,九个 evolver_* MCP 工具全部静默不可用。

复现

codex plugin marketplace add /path/to/evolver-codex-plugin
codex plugin add evolver@evomap
codex mcp list

实际

Name           Command                             Args                     Status
evolver-proxy  /opt/homebrew/opt/node@22/bin/node  ./mcp/evolver-proxy.mjs  enabled

codex mcp list 和 codex doctor 都不会提示这个二进制不存在,所以看起来像「装好了」。

期望 —— 只把这一个字段改成 "command": "node"(走 PATH),bridge 立刻正常:

── initialize   ✔ evolver-proxy v0.1.0 (protocol 2024-11-05)
── tools/list   ✔ 9 tools exposed

evolver-claude-code-plugin 的 .mcp.json 本来就是这么写的。若确实需要锁定 node 大版本,
建议在 mcp/evolver-proxy.mjs 启动时检查并给出可读的报错,而不是钉死某个包管理器的绝对路径。

这条属于 EvoMap/evolver-codex-plugin 仓库。为了让四条一起看,先合并提在这里,
需要的话我再单独开一个过去。


2. setup-hooks 的默认 scope 从 user 变成了 project(回归)

插件 README 和它自带的 SKILL.md 都让用户(以及 Codex 自己)这样跑,不带 --scope:

  • README.md:44 — “when you want the same machine-wide workflow in every Codex
    project: evolver setup-hooks --platform=codex”
  • plugins/evolver/README.md:98
  • plugins/evolver/skills/evolver/SKILL.md:123 —— 这一条是写进 skill 的,
    意味着照着 skill 走的 agent 会把 .codex/ 撒进用户的业务仓库

复现

mkdir -p /tmp/proj && cd /tmp/proj && git init -q .
evolver setup-hooks --platform=codex --json

2.0.28 实际

{"runtime":"codex","outcome":"installed","files":[".codex/config.toml"],"mode":"mcp-plugin"}

写的是 /tmp/proj/.codex/config.toml,~/.codex/config.toml 没动。

1.94.0 对照(同样的命令,同样的干净 HOME)

[setup-hooks] Platform: Codex
[setup-hooks] Config root: <HOME>
[codex] Wrote <HOME>/.codex/hooks.json
[codex] Injected evolution section into <HOME>/AGENTS.md

1.x 默认就是 user scope,和文档说的一致。2.x 默认变成 project,但文档没跟着改。

期望 —— 要么把 Codex runtime 的默认 scope 改回 user,要么把文档和 skill 里的命令
统一加上 --scope=user。现在的组合是「照官方说明逐字执行,会在用户没预期的位置生成配置」。

加上 --scope=user 之后行为是对的,而且正确尊重 CODEX_HOME:

{"runtime":"codex","outcome":"installed","files":["~/.codex/config.toml"],"mode":"mcp-plugin"}

3. Codex runtime 不再安装 session-end hook —— 只回忆,不记录(回归)

evolver setup-hooks --runtime=codex --scope=user 在 2.0.28 上只产出两个 hook:

[[hooks.SessionStart]]
matcher = "startup|resume"
[[hooks.SessionStart.hooks]]
command = "evolver inject session-start --hook-stdin"

[[hooks.UserPromptSubmit]]
[[hooks.UserPromptSubmit.hooks]]
command = "evolver inject prompt-recall --hook-stdin"

两个都是 recall。没有 SessionEnd,所以一次 Codex 会话读得到历史记忆,
但什么都写不回去 —— 闭环是断的。evolver inject 也确实只有这两个子命令:

用法: evolver inject session-start | evolver inject prompt-recall --hook-stdin

1.94.0 对照,同样的命令写出的 ~/.codex/hooks.json:

{
  "hooks": {
    "SessionStart": [{ "command": "node .codex/hooks/evolver-session-start.js" }],
    "PostToolUse":  [{ "command": "node .codex/hooks/evolver-signal-detect.js" }],
    "Stop":         [{ "command": "node .codex/hooks/evolver-session-end.js" }]
  },
  "_evolver_managed": true
}

也就是 1.x 给 Codex 装的是 SessionStart / PostToolUse / Stop 三件套,
和 evolver-claude-code-plugin 今天仍然在装的三件套完全对应。2.x 丢了后两个。

这不是宿主的限制:codex-cli 0.153.0 支持的 hook 事件包括
SessionStart、UserPromptSubmit、PreToolUse、PostToolUse、PermissionRequest、
PreCompact、PostCompact、SessionEnd、SubagentStart、SubagentStop、Interrupt。

影响 —— 同一个 Evolver 安装,在 Claude Code 上会记录结果,在 Codex 上不会。
任何拿「Codex」对比「Codex + Evolver」的评测,Codex 这边压根没有东西可学。

变通 —— 能力其实是在的,只是没接到 hook 上。evolver ingest 原生认识 Codex rollout:

evolver ingest ~/.codex/sessions/2026/09/03/rollout-*.jsonl
# ingest [codex] …: 4 turn(s) → 1 signal(s)
#   [success/success_prose] …
#   → recorded as material 01M1K9M38F7FJG9CTAD7BH3ND4 (material.batch_ready)

诉求 —— 要么给 Codex runtime 恢复一个 SessionEnd hook 接到 ingest 上;
要么如果 evolver autoexec 是 2.x 的既定替代方案,请在 Codex 接入文档里说明,
因为现在没有任何地方指向它。


4. _evox_product_managed 让 codex --strict-config 直接起不来

setup-hooks --runtime=codex 会往它托管的 Codex 配置里写一个 Codex 不认识的 key:

[mcp_servers.evox-product]
command = "…/node"
args = [ "…/productBridgeShim.js" ]
_evox_product_managed = true

复现

export CODEX_HOME=/tmp/sc/.codex
evolver setup-hooks --runtime=codex --scope=user
codex --strict-config exec --skip-git-repo-check </dev/null

实际

Error loading config.toml:
/tmp/sc/.codex/config.toml:8:1: unknown configuration field `mcp_servers.evox-product._evox_product_managed`
  |
8 | _evox_product_managed = true
  | ^^^^^^^^^^^^^^^^^^^^^

Codex 拒绝启动。不带 --strict-config 时它会被忽略,日常使用无影响 ——
但 --strict-config 恰恰是排查配置问题时会用的开关,而它卡在了 Evolver 自己的输出上。

期望 —— 归属标记放到 Codex 不会当作配置解析的地方(Evolver 自己的状态目录,
或者文件里的注释标记),让 Evolver 写出来的配置能通过 Codex 自己的严格校验。


附:顺手撞到的两个小毛病

  • 无法识别的 flag 被静默忽略。 evolver setup-hooks --runtime=codex --nonsense=x
    正常退出 0 并照常安装。拼错的 flag(包括拼错的 --scope)和成功无法区分。
    另外 --platform= 和 --runtime= 行为等价,但 help 只写了 --runtime=,
    插件文档只用 --platform=,建议统一。
  • evolver autoexec --help 不打印帮助,而是直接把 daemon 起起来
    (关掉 stdin 也一样,只能靠 timeout 杀掉,并会留下 autoexec.lock)。

Activity

  1. artist-coding commented on Sep 3, 2026

    @artist-coding
    Author

    提错仓库了,已移到插件仓库:EvoMap/evolver-codex-plugin#8

    内容不变。其中第 2、3、4 条确实出在 @evomap/evolver CLI 侧,如果维护者希望在本仓库单独跟踪,我可以按条拆开重开。抱歉打扰。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions