语言:中文 | English
第一次在本机起步?直接看 docs/getting-started.md 按阶段跑一遍。
已经搭好环境,只想一键挂 Codex Stop hook?跑
./scripts/install-codex-hook.sh(卸载用uninstall-codex-hook.sh)。
一个本地的 Codex 插件,运行分阶段的自我进化循环:
SessionStart — 初始化运行时状态,注入 USER.md + MEMORY.md 构成的稳定背景,以及 recall policy 与 session-recall skill。Stop — 构建标准化 review snapshot,调用 provider-backed reviewer,落盘一份结构化的 SuggestionEnvelope(memory updates、recall candidates、skill actions)。compile-preflight — 廉价的调度器唤醒/检查步骤,返回 skip_empty、skip_locked 或 run。compile — writer-owned 的批量晋升步骤。先读取 existing memory / recall 作为上下文,再运行可插拔 backend(script 或 agent:opencode),最后原子写入终态资产。recall / recall-trigger — 在 live turn 中做聚焦召回。compiler 是唯一负责最终资产写入(memory、recall、managed skills、receipt)的组件;backend 只负责产出结构化 artifacts。
Codex CLI 目前还不读 plugin manifest 里的 hooks 字段 (差距分析),所以我们 直接往
~/.codex/hooks.json写 marker-protected entry。hook 和 scheduler 都通过uvx --from codex-self-evolution-plugin ...调 CLI,不需要 clone 仓库,也不需要常驻 venv。完整分阶段指南: docs/getting-started.md。
macOS happy path。唯一前置:uv
(brew install uv):
# 1. 拿 installer 脚本(脚本本身很小,不 clone 仓库)
curl -fsSL https://raw.githubusercontent.com/T0UGH/codex-self-evolution-plugin/main/scripts/install-codex-hook.sh -o /tmp/install-codex-hook.sh
curl -fsSL https://raw.githubusercontent.com/T0UGH/codex-self-evolution-plugin/main/scripts/install-scheduler.sh -o /tmp/install-scheduler.sh
chmod +x /tmp/install-*.sh
# 2. provider 凭据(放 ~/.codex-self-evolution/ 下)
mkdir -p ~/.codex-self-evolution
curl -fsSL https://raw.githubusercontent.com/T0UGH/codex-self-evolution-plugin/main/.env.provider.example \
-o ~/.codex-self-evolution/.env.provider
# 编辑并填 MINIMAX_API_KEY(或 OPENAI_API_KEY / ANTHROPIC_API_KEY)
# 3. 往 ~/.codex/hooks.json 装 Stop + SessionStart, 同时安装 ~/.local/bin/csep
/tmp/install-codex-hook.sh
# 4. launchd scheduler(每 5 分钟跑 scan --backend agent:opencode)
/tmp/install-scheduler.sh
# 5. 盘点一下
uvx --from codex-self-evolution-plugin codex-self-evolution status | python3 -m json.tool
csep recall "focused query" --format json
后续每次调用(hooks、scheduler、手动 status, 以及模型自触发 recall 用的
csep wrapper)都走 uvx cached wheel,warm 启动 ~100ms。发布新 PyPI 版本时
下次 hook 或 wrapper 触发自动升级。
开发者安装(editable,贡献代码):clone + pip install -e .,用
.venv/bin/codex-self-evolution 直接调。
阶段 2 给了
完整 CLI 驱动 reviewer → compile → memory 的 walkthrough,不需要 Codex /
launchd。
完全清理:/tmp/install-scheduler.sh 同目录有 uninstall-scheduler.sh,
install-codex-hook.sh 同理。都是幂等,不碰其他工具的 hook / launchd job。
所有子命令都可以通过
uvx --from codex-self-evolution-plugin codex-self-evolution <subcmd>
调用,以下示例省略这个前缀:
codex-self-evolution session-start --cwd /path/to/repo
codex-self-evolution stop-review --hook-payload /path/to/stop_payload.json
codex-self-evolution compile-preflight --state-dir data
codex-self-evolution compile --once --state-dir data --backend agent:opencode
codex-self-evolution scan --backend agent:opencode # preflight+compile 跨所有 per-project bucket
codex-self-evolution status # 只读诊断快照
codex-self-evolution recall --query "context" --cwd /path/to/repo
codex-self-evolution recall-trigger --query "remember previous flow" --cwd /path/to/repo --format json
csep recall "focused query for prior repo context" # 给模型读的 Markdown recall
等价的模块调用形式:
python -m codex_self_evolution.cli session-start --cwd /path/to/repo
本节列出所有可配置项。所有变量默认都是可选的;如果你只跑确定性的 dummy / script 路径,不需要任何配置。"必须"一栏说明在什么场景下某项才成为强制。
| Flag / 参数 | 必须 | 默认值 | 用途 |
|---|---|---|---|
--cwd |
session-start、recall、recall-trigger 必须;csep recall 可选 |
csep recall 默认 $PWD |
当前会话操作的 repo。 |
--state-dir |
可选 | ~/.codex-self-evolution/projects/<mangled-cwd>/ |
持久化运行时状态根目录(suggestions、memory、recall、skills、compiler receipts、review snapshots、scheduler)。每个 repo 自动按绝对路径(/ → -)分配独立 bucket,用户代码仓库保持干净。设 CODEX_SELF_EVOLUTION_HOME 可整体迁移根目录。 |
--repo-root |
compile、compile-preflight 可选 |
当前进程 CWD | 当 --state-dir 未指定时用来解析 state-dir 的 repo 根。 |
--once |
compile 可选 |
关闭 | 只跑一次 compile,不循环。 |
--backend |
compile 可选 |
script |
取值 script 或 agent:opencode。默认 scheduler plist 用 agent:opencode。 |
--explicit |
recall-trigger 可选 |
关闭 | 标记该 recall 触发为用户显式发起。 |
--format |
recall-trigger / csep recall 可选 |
markdown |
测试/调试用 json;Markdown 面向模型直接阅读。 |
--top-k |
recall-trigger / csep recall 可选 |
3 |
聚焦召回最多返回几条。 |
--state-dir 下的目录布局(默认 ~/.codex-self-evolution/projects/<mangled-cwd>/):
~/.codex-self-evolution/
├── .env.provider # API key(由 install-codex-hook.sh 管理)
└── projects/
└── -Users-alice-code-myrepo/ # 一个 repo 一个 bucket;/ → -
├── suggestions/{pending,processing,done,failed,discarded}/
├── memory/ # USER.md, MEMORY.md, memory.json
├── recall/ # index.json, compiled.md
├── skills/managed/ # managed skill markdown + manifest.json
├── compiler/ # compile.lock, last_receipt.json
├── review/snapshots/ # Stop 时的标准化 snapshot
├── review/failed/ # reviewer parse 失败时落盘的原始响应
└── scheduler/
这些变量由 Codex 宿主在调用 .codex-plugin/plugin.json 里定义的 hook 命令时注入,用户不需要手工设置。
| 变量 | 作用范围 | 用途 |
|---|---|---|
CODEX_CWD |
session-start、recall、recall-trigger |
当前 repo 工作目录。 |
CODEX_STATE_DIR |
所有 hook | 指向运行时 state 目录。 |
CODEX_HOOK_PAYLOAD |
stop-review |
Stop payload JSON 的路径。 |
CODEX_RECALL_QUERY |
recall、recall-trigger |
聚焦召回的查询串。 |
Stop 阶段)reviewer 是 provider-backed 的。选择优先级:
reviewer_provider 字段。dummy。| Provider | 用途 | 使用时必须配置 |
|---|---|---|
dummy |
测试 / dry run 用的确定性 stub | 无(可选支持 Stop payload 里的 provider_stub_response) |
openai-compatible |
OpenAI chat-completions 协议 | OPENAI_API_KEY(或显式传入 api_key 选项) |
anthropic-style |
Anthropic messages 协议 | ANTHROPIC_API_KEY |
minimax |
MiniMax(走 Anthropic 协议的端点) | MINIMAX_API_KEY |
| 变量 | 必须 | 默认值 | 用途 |
|---|---|---|---|
OPENAI_API_KEY |
openai-compatible 必须 |
— | Bearer token。 |
OPENAI_BASE_URL |
可选 | https://api.openai.com/v1/chat/completions |
覆盖端点。 |
OPENAI_REVIEW_MODEL |
可选 | gpt-4.1-mini |
请求体里的 model id。 |
ANTHROPIC_API_KEY |
anthropic-style 必须 |
— | x-api-key 头。 |
ANTHROPIC_BASE_URL |
可选 | https://api.anthropic.com/v1/messages |
覆盖端点。 |
ANTHROPIC_REVIEW_MODEL |
可选 | claude-3-5-haiku-latest |
Model id。 |
MINIMAX_API_KEY |
minimax 必须 |
— | Bearer token。 |
MINIMAX_REGION |
可选 | global |
global → https://api.minimax.io/anthropic/v1/messages;cn → https://api.minimaxi.com/anthropic/v1/messages。 |
MINIMAX_BASE_URL |
可选 | 由 region 推导 | 完整 URL 覆盖,优先级高于 MINIMAX_REGION。 |
MINIMAX_REVIEW_MODEL |
可选 | MiniMax-M2.7 |
Model id。 |
直接调用 run_reviewer(...) 时通过 provider_options dict 传入。每个选项会覆盖对应的环境变量。
| 选项 | 默认值 | 说明 |
|---|---|---|
api_key |
从环境变量读 | 覆盖 provider 的 env key。 |
api_base |
provider 默认 | 完整 URL。 |
model |
provider 默认 | Model id。 |
max_tokens |
4096 |
这是输出长度预算,不是 200k 的上下文窗口。各家模型输出上限普遍是 8k(Haiku/Sonnet/MiniMax-M2.7),4096 留够 10+ 条 suggestion 的空间还不擦顶。 |
timeout_seconds |
30 |
HTTP 超时。 |
anthropic_version |
2023-06-01 |
Anthropic 协议的 anthropic-version 头。 |
stub_response |
— | 仅 Dummy provider 用,预置的 reviewer JSON。 |
通过 --backend 选择:
| Backend | 必须 | 说明 |
|---|---|---|
script |
无 | 确定性 Python merge,安全默认。读取 existing memory / recall,做保守增量 merge(不会洗掉稳定条目)。 |
agent:opencode |
opencode 二进制在 PATH 中 或 指定 opencode_command |
把 {batch, existing_assets, repo, contract} payload 写到临时 JSON 文件,跑 opencode run --format json --file <payload> --dangerously-skip-permissions -- <prompt>,解析 event stream 抽取 assistant 文字,剥 code fence,从中抠出首个平衡 JSON object。任何失败(二进制缺失 / 非零退出 / 超时 / 空输出 / schema 不符)都会 fallback 到 script,除非 allow_fallback=False。已对 opencode 1.4.0 验证通过。 |
| 途径 | 变量 / 选项 | 默认值 | 用途 |
|---|---|---|---|
| 环境变量 | CODEX_SELF_EVOLUTION_OPENCODE_COMMAND |
— | 空格分隔 argv,完全替代默认命令。你 opencode CLI shape 不同或需要加额外 flag 时用。 |
| 环境变量 | CODEX_SELF_EVOLUTION_OPENCODE_MODEL |
— | 附加 --model <provider/name>。默认 build 速模型偶尔产出截断 JSON 时,换一个更强模型即可。 |
| 环境变量 | CODEX_SELF_EVOLUTION_OPENCODE_AGENT |
— | 附加 --agent <name>。想锁定 agent profile 可用。 |
options["opencode_command"] |
— | env,其次 _build_default_opencode_command 构造 |
显式 argv 列表,优先级高于 env 变量。 |
options["opencode_model"] / options["opencode_agent"] |
— | 对应 env 变量 | 按单次调用覆盖 model / agent。 |
options["opencode_skip_permissions"] |
— | True |
附加 --dangerously-skip-permissions,让 agent 无 TUI 确认地调用文件读工具(headless 子进程必需)。只有你已审过 agent profile 才可以关。 |
options["opencode_timeout_seconds"] |
— | 900(15 分钟) |
子进程超时。严格小于 DEFAULT_LOCK_STALE_SECONDS,确保 agent 卡住时子进程先 timeout → backend fallback → finally 清锁,避免被下一个 preflight 当 stale 抢锁导致并发写。 |
options["allow_fallback"] |
— | True |
为 False 时,agent backend 失败不会 fallback,而是直接抛 RuntimeError。 |
Agent 路径失败时追加到 CompileArtifacts.discarded_items 的原因:
opencode_unavailable — 二进制不在 PATH 上,也没有自定义 invoker。agent_invoke_failed — 子进程抛异常(非零退出、超时等);detail 带截断后的错误信息。agent_output_invalid — stdout 不是合法 JSON,或不符合响应 schema;detail 带解析错误。Agent 响应 schema(src/codex_self_evolution/compiler/agent_io.py::COMPILE_CONTRACT):
{
"memory_records": {"user": [...], "global": [...]},
"recall_records": [...],
"compiled_skills": [...],
"manifest_entries": [...],
"discarded_items": [...]
}
在 src/codex_self_evolution/config.py 中定义:
| 常量 | 默认值 | 用途 |
|---|---|---|
DEFAULT_BATCH_SIZE |
100 |
每次 compile pass 最多 claim 的 suggestion 数。从自有调度器调用 run_compile(batch_size=...) 可覆盖。 |
DEFAULT_LOCK_STALE_SECONDS |
1800(30 分钟) |
compile.lock 的硬上限。正常 compile 应远低于此值(预期 5-10 分钟)。stale 判定细节见 Compile lock 保护。 |
PLUGIN_OWNER |
codex-self-evolution-plugin |
只有 owner 等于这个字符串的 managed skill 才允许 compiler 修改。用于拒绝写入非托管 skill。 |
<state-dir>/compiler/compile.lock 文件锁串行化 compile 运行。锁内容是 JSON:{created_at, pid}。下一次 preflight / file_lock 调用时,满足任一条件即判 stale 可回收:
| 条件 | 检测方式 | 原因 |
|---|---|---|
持锁 pid 已不存在 |
os.kill(pid, 0) 抛 ProcessLookupError |
进程被 SIGKILL / crash / 机器重启后锁成孤儿。立即清。 |
created_at 在未来(age_seconds < 0) |
utc_now() - created_at |
时钟回拨 / NTP 调整,不信任来自"未来"的锁。 |
created_at 早于 DEFAULT_LOCK_STALE_SECONDS(30 分钟)前 |
age 阈值 | 进程仍在但跑得过久,超过容忍时间。 |
设计契约(无 heartbeat):opencode_timeout_seconds(默认 15 分钟)必须严格小于 lock stale 窗口(30 分钟)。agent 卡住时 → 子进程 timeout → AgentCompilerBackend._fallback 跑 → finally 释放锁。整条链在下一个 preflight 判 stale 前完成。改动任一常量都要保持这个不变量。
lock_status(paths) 返回 {locked, stale, stale_reason, pid_alive, age_seconds, owner_pid} 便于诊断。
模板 plist:docs/launchd/com.codex-self-evolution.preflight.plist。
必须改的字段:
/Users/haha/hermes-agent/venv/bin/python3.11)要匹配你本地的 Python venv。--state-dir 改成你 runtime state 的绝对路径。作业要廉价唤醒:跑 compile-preflight,只在其返回 run 时才调 compile:
codex-self-evolution compile-preflight --state-dir data
# 如果 status == run:
codex-self-evolution compile --once --state-dir data --backend agent:opencode
| 变量 | 使用位置 | 默认值 | 用途 |
|---|---|---|---|
PYTHON |
Makefile targets | /Users/haha/hermes-agent/venv/bin/python3.11 |
make test、make preflight、make provider-smoke-* 使用的解释器。自己 venv 路径不同时请覆盖。 |
IMAGE |
make docker-* |
codex-self-evolution-e2e |
Docker 镜像 tag。 |
ENV_FILE |
make provider-smoke-* |
~/.codex-self-evolution/.env.provider |
跑真实 provider 冒烟测试前自动 source。放在插件 home 目录,与已安装的 Stop hook 共用同一份文件。如果你仍保留 repo 根的老副本,设 ENV_FILE=.env.provider 覆盖。 |
存在 .env.provider 时 Makefile 会自动 source。从模板复制到插件 home 目录:
mkdir -p ~/.codex-self-evolution
cp .env.provider.example ~/.codex-self-evolution/.env.provider
# 填上需要的 key — make provider-smoke-* 和已安装的 Stop hook 都读同一份
scripts/install-codex-hook.sh 第一次执行时会自动把 repo 根的老 .env.provider 迁移到 ~/.codex-self-evolution/.env.provider。
Reviewer 调用在 src/codex_self_evolution/review/runner.py,流程:
src/codex_self_evolution/review/prompt.md 的 prompt。dummy、openai-compatible、anthropic-style、minimax)。parse_reviewer_output(...) 解析 JSON,并用 ReviewerOutput schema 校验。非法输出会抛 SchemaError 直接拒绝。主 Stop 路径不再信任 payload 里预置的 reviewer_output;fixture 只在测试中作为替身。
pending suggestion batch
+ existing memory / recall / manifest(由 build_compile_context 读入)
-> backend.compile(batch, context, options)
-> apply_compiler_outputs(...) # 原子写入 memory / recall / skills
-> write_receipt(...)
build_compile_context 读取 memory/USER.md、memory/MEMORY.md、memory/memory.json、recall/index.json、recall/compiled.md 以及 skill manifest。文件缺失或损坏会优雅回退为空值,不会抛异常。ScriptCompilerBackend 用 compile_memory(existing_index=...) 和 `compile_recall(exi$ claude mcp add codex-self-evolution-plugin \
-- python -m otcore.mcp_server <graph>