- 人工智能
- AI Agent
- 代码智能体
- 多智能体
- MCP Clients
- Agent 编排
【免费下载链接】oh-my-openagent
OmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.
install-codex是 oh-my-openagent(OmO)项目中专用于 Codex CLI Light 版的插件安装器:它负责把omo插件及其捆绑的 Agent、MCP 清单、Hook 信任哈希与 CLI 入口完整写入用户的~/.codex/目录,并同步改写~/.codex/config.toml。本文以仓库中的 packages/omo-opencode/src/cli/install-codex/AGENTS.md 为主线,结合其底层实现(位于 packages/omo-codex/src/install/)逐阶段拆解安装流程、产物布局与设计约束,读完即可理解该安装器的全部内部机制,也能独立排查安装产物与卸载残留问题。
一、定位:一个指向规范实现的 OpenCode CLI 适配垫片
文档开篇即点明这个目录的本质——它不再是独立的安装器实现,而是一个 OpenCode CLI adapter shim(适配垫片)。真正的安装器源码被收敛到packages/omo-codex/src/install/,而packages/omo-opencode/src/cli/install-codex/下的同名文件只做一件事:从@oh-my-opencode/omo-codex/install/install-codex与@oh-my-opencode/omo-codex/install/types重新导出,例如 packages/omo-opencode/src/cli/install-codex/install-codex.ts 全文只有一行export * from "@oh-my-opencode/omo-codex/install/install-codex",types.ts 同理。这种"垫片 + 规范实现"的双层结构让 OpenCode CLI 侧只保留命令路由入口,所有安装逻辑单点维护,避免双实现漂移。
安装的触发方式有两种等价命令(文档明确给出):
bunx oh-my-openagent install --platform=codex- 别名形式:
npx lazycodex-ai install
入口函数是runCodexInstaller(),它接收一个可选的CodexInstallOptions参数并返回CodexInstallResult,这两个类型定义在 packages/omo-codex/src/install/types.ts。
二、目录结构与关键文件
install-codex目录内共 39 个文件,文档以表格形式给出了最核心的 8 个文件及其职责,这是理解整个安装器的最小清单:
| 文件 | 职责 |
|---|---|
install-codex.ts | 主编排器runCodexInstaller()——解析路径、遍历 marketplace 插件、驱动 cache/install/config 各阶段 |
types.ts | CodexInstallOptions、CodexInstallResult、MarketplaceManifest、PluginManifest、InstalledPlugin等类型 |
codex-marketplace.ts | 读取packages/omo-codex/marketplace.json与各插件的.codex-plugin/plugin.json,校验路径段 |
codex-cache-install.ts | 构建源码、拷贝到临时缓存目录、执行npm ci --omit=dev、改写 MCP 清单、原子提升到~/.codex/plugins/cache/{marketplace}/{name}/{version}/ |
codex-cache-bins.ts | 发现package.json的bin条目,把组件 CLI 链接进 bin 目录;写入omo运行时包装器(POSIX shell / Windows.cmd) |
link-cached-plugin-agents.ts | 发现components/*/agents/下捆绑的 Agent TOML,拷贝到~/.codex/agents/,保留既有model_reasoning_effort与service_tier,写.installed-agents.json清单 |
codex-marketplace-snapshot.ts | 把本地 marketplace 快照写入~/.codex/.tmp/marketplaces/{marketplace}/ |
codex-config-toml.ts | 改写~/.codex/config.toml:启用特性、写入 marketplace/plugin/agent/hook-trust 块、可选的自主任权限 |
codex-cleanup.ts | 卸载编排器:移除 cache、agents、config 块与项目本地残留 |
需要提醒的是:上表中的文件路径在规范实现仓库中全部位于 packages/omo-codex/src/install/ 下(如 codex-cache-install.ts、codex-config-toml.ts、codex-cleanup.ts 等),OpenCode 垫片目录里只有转发的薄壳,阅读源码时应以omo-codex包为准。
三、安装入口与配置项:CodexInstallOptions 全解
runCodexInstaller的默认路径解析逻辑集中在 install-codex.ts:
const repoRoot = resolve(options.repoRoot ?? findRepoRoot({ importerDir: import.meta.dir, env })) const codexHome = resolve(options.codexHome ?? env.CODEX_HOME ?? join(homedir(), ".codex")) const projectDirectory = resolve(options.projectDirectory ?? env.OMO_CODEX_PROJECT ?? process.cwd()) const binDir = resolveCodexInstallerBinDir({ binDir: options.binDir, codexHome, env }) const versionOverride = env.LAZYCODEX_DEV_VERSION?.trim() || undefined从这段代码可以看出四个关键路径的优先级:显式参数 > 环境变量 > 默认值。
repoRoot:安装器的工作根目录,通过findRepoRoot向上最多探测 7 层父目录,寻找同时满足packages/omo-codex/plugin/.codex-plugin/plugin.json存在的目录(见findRepoRootFromImporter与isRepoRootWithCodexPlugin,install-codex.ts);也支持用OMO_WRAPPER_PACKAGE_ROOT环境变量直接指定包装包根目录。codexHome:默认为~/.codex,可被CODEX_HOME覆盖,所有安装产物都落在该目录内。projectDirectory:项目目录,默认取OMO_CODEX_PROJECT或当前工作目录,用于后续"项目本地 Codex 产物修复"阶段。binDir:由resolveCodexInstallerBinDir解析(涉及CODEX_LOCAL_BIN_DIR等环境变量),是组件 CLI 与omo运行时包装器的落盘位置。versionOverride:开发期可用LAZYCODEX_DEV_VERSION强制覆盖插件版本号。
CodexInstallOptions的完整字段(types.ts)如下:
| 选项 | 类型 | 含义 |
|---|---|---|
codexHome | string | Codex 主目录,默认~/.codex |
binDir | string | CLI 链接目录,默认由resolveCodexInstallerBinDir决定 |
repoRoot | string | 仓库/包装包根目录 |
projectDirectory | string | 项目目录,用于项目本地清理 |
platform | CodexInstallPlatform | 目标平台,默认process.platform |
env | { [key: string]: string \| undefined } | 环境变量快照 |
gitBashResolver | GitBashResolver | Windows 下 Git Bash 解析器(仅 win32 使用) |
autonomousPermissions | boolean | 是否写入 Codex 自主任权限块,默认true(非 false) |
reasoning | string | 统一的 omo 配置推理等级,覆盖捆绑目录中的model_reasoning_effort(off映射为none) |
astGrepInstaller | RunAstGrepSkillInstall | ast-grep 安装器(供 LSP 类技能使用) |
runCommand | RunCommand | 命令执行器,默认为defaultRunCommand |
log | (message: string) => void | 日志回调,默认空操作 |
runCodexInstaller返回CodexInstallResult(types.ts):marketplaceName、installed(InstalledPlugin[])、configPath、codexHome、gitBashPath、projectCleanup。
四、安装主流程:九阶段编排逐层拆解
文档给出了安装流程的完整示意,runCodexInstaller()的 9 个阶段与源码一一对应(install-codex.ts):
runCodexInstaller() 1. resolve repoRoot / codexHome / binDir / projectDirectory 2. git-bash.ts: Windows Git Bash preflight(仅探测发现,不自动 winget/system 安装) 3. codex-marketplace.ts: 读取 marketplace.json + 插件清单 4. lazycodex-version-stamp.ts: 从发行清单解析插件版本 5. 对每个 marketplace 插件: a. codex-cache-install.ts: 构建、拷贝、npm ci、改写 MCP 清单、提升到 cache b. codex-cache-bins.ts: 链接组件 CLI + omo 运行时包装器 c. link-cached-plugin-agents.ts: 拷贝 Agent TOML 到 ~/.codex/agents/ 6. codex-cache-prune.ts: 清理过期插件 + 旧 marketplace 缓存 7. codex-config-toml.ts: 改写 ~/.codex/config.toml 8. codex-project-local-cleanup-best-effort.ts: 修复项目本地 .codex/config.toml 冲突 9. Telemetry: 记录 install_completed4.1 阶段 1-2:路径解析与 Windows Git Bash 预检
路径解析见上文第三节。Git Bash 预检只针对win32平台调用prepareGitBashForInstall(install-codex.ts),如果gitBashResolution.found为false,安装会直接抛出带installHint的错误。值得注意的设计是:预检是"发现优先"(discovery-first),GitBashResolution的source字段标注了发现途径(not-required/env/program-files/program-files-x86/path),安装器只探测并报告,不会自动执行 winget 或系统级安装——这是文档明确强调的边界。
4.2 阶段 3:读取 marketplace 与插件清单
readMarketplace读取 packages/omo-codex/marketplace.json,其真实内容为:
{ "name": "sisyphuslabs", "interface": { "displayName": "Sisyphus Labs" }, "plugins": [ { "name": "omo", "source": "./plugins/omo", "category": "Developer Tools", "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" } } ] }校验逻辑在 codex-marketplace.ts:name必须是非空字符串,plugins必须是数组;每个插件的source支持字符串路径或{ source: "local", path }对象,且本地路径必须以./开头、不得包含..路径穿越段(validateLocalSourcePath)。validatePathSegment则用正则^[A-Za-z0-9._+-]+$校验 marketplace 名、插件名与版本号,并拒绝.与..——这套校验直接作用于后续缓存目录的路径拼接,是防止路径注入的关键一环。
随后readPluginManifest读取每个插件根目录下.codex-plugin/plugin.json(name、可选version、可选hooks),并在安装器内强制校验manifest.name === entry.name,不一致即抛错。
4.3 阶段 4:版本解析与发行清单打戳
resolveLazyCodexPluginVersion综合manifestVersion、marketplaceName、pluginName、发行清单(distribution manifest)与LAZYCODEX_DEV_VERSION覆盖值,确定最终安装版本;随后validatePathSegment(version, "plugin version")再次校验。对sisyphuslabsmarketplace 的omo插件,安装完成后还会执行stampLazyCodexPluginVersion与writeLazyCodexInstallSnapshot(install-codex.ts),并在插件根记录 binDir 位置writeInstalledCodexBinDir——源码注释解释了原因:CODEX_LOCAL_BIN_DIR常是一次性覆盖(one-shot override),卸载时无法从环境变量重新计算该位置,因此必须在安装期落盘存档。
4.4 阶段 5a:缓存安装——构建、拷贝、npm ci、改写 MCP 清单、原子提升
这是安装器的核心阶段,实现于installCachedPlugin(codex-cache-install.ts):
- 构建:默认先对源插件执行
npm install与npm run build(maybeRunNpmInstall/maybeRunNpmBuild,均以package.json存在为前提;buildSource: false时跳过构建并改为后续执行npm run sync:skills)。 - 拷贝到临时目录:目标路径为
{codexHome}/plugins/cache/{marketplace}/{name}/{version},临时目录是它的兄弟目录.tmp-{basename}-{pid}-{Date.now()}。拷贝时过滤掉.git、node_modules,并且绝不拷贝嵌套组件里的.mcp.json——因为 Codex 只从插件根目录的.mcp.json加载 MCP 服务器,嵌套清单里的相对 daemon 路径在拍平后的缓存布局中会悬空(isNestedComponentMcpManifest)。 - 改写本地依赖与运行时:
rewriteCachedPackageLocalFileDependencies把file:本地依赖改写为缓存内路径;copyBundledMcpRuntimeDists/copyRootRuntimeDists把仓库dist/cli、dist/cli-node等运行时拷入;copyCanonicalPromptSources把packages/prompts-core/prompts/ultrawork/codex.md等规范提示词固化到插件根,避免sync-skills在缓存布局下解析不到仓库相对路径。 - npm ci 依赖安装:改写本地依赖会令
package.json与package-lock.json漂移,npm ci会以 EUSAGE 中止(源码注释引用 lazycodex#137,方案归功于 oh-my-openagent#6202 的社区修复),因此:- 改写过依赖 → 用
npm install --omit=dev --no-audit --no-fund让 npm 自行调和 lock; - 未改写 → 走确定性更快的
npm ci --omit=dev。 同时sanitizeNpmInstallEnv会过滤掉npm_config_allow_scripts,防止脚本执行策略被意外放宽。
- 改写过依赖 → 用
- 校验与清单改写:
rewriteCachedMcpManifest重写 MCP 清单、rewriteCachedManifestRoot把根路径改写为最终缓存路径;assertHookCommandTargets校验 Hook 命令目标不越界;assertNoRemovedSparkshellPromptReferences还会在.codex-plugin、agents、bundled-rules、hooks、skills等提示面目录中扫描已移除的 sparkshell 引用,发现即中止安装。 - 原子提升:
promoteDirectory采用"先拷临时兄弟目录 →rename()提升 → 失败恢复备份"的原子策略:已有目标先改名为.backup-*,提升失败则回滚备份,成功才删除备份(codex-cache-install.ts)。
4.5 阶段 5b:CLI 链接与 omo 运行时包装器
linkCachedPluginBins(codex-cache-bins.ts)递归扫描插件根目录下所有package.json的bin字段(跳过node_modules、.git、dist),生成链接:
- POSIX:创建符号链接(
symlink); - Windows:写入带
COMMAND_SHIM_MARKER标记的.cmdshim(windowsCommandShim)。
其中有一组保留名RESERVED_NESTED_BIN_NAMES:omo、omo-agent-toolkit、lazycodex、lazycodex-ai、oh-my-opencode、oh-my-openagent——嵌套包(非插件根)声明的这些 bin 名会被跳过,避免子组件抢占顶层命令名。此外 bin 目标必须解析在包根内(resolvePackageBinTarget拒绝..越界与\0),assertSafeCommandName则拒绝空名、.、..、路径分隔符等非法命令名。
对omo插件,还会额外执行linkRootRuntimeBin(codex-cache-bins.ts)生成omo-agent-toolkit运行时包装器:POSIX 下写 shell 包装并chmod 0o755,Windows 下写.cmd;包装器内容带RUNTIME_WRAPPER_MARKER标记,旧版omo遗留包装器会被安全移除。若仓库缺少dist/cli/index.js,安装器仅记录 warning 而不会失败。
4.6 阶段 5c:Agent 配置落盘与设置保留
linkCachedPluginAgents(link-cached-plugin-agents.ts)扫描插件根components/*/agents/下的全部*.toml,逐个拷贝到~/.codex/agents/(以拷贝而非符号链接的方式落盘),并执行两个关键的用户设置保留动作:
restorePreservedReasoning:安装前先用capturePreservedAgentReasoning记录用户已有的model_reasoning_effort,拷贝后写回;restorePreservedServiceTier:同理保留service_tier。
这是"升级不丢用户偏好"的核心机制。若存在lazycodex-worker-medium.toml,还会调用installDefaultAgentRole安装默认角色。最终把已安装 Agent 路径写入.installed-agents.json清单,供卸载阶段精确回收。文档还提示当前受管(managed)的 Codex Agent 名单为explorer、librarian、metis、momus、plan。
4.7 阶段 6:缓存剪枝与旧 marketplace 清理
pruneMarketplaceCache删除当前 marketplace 下不再被引用的插件版本;legacyCacheMarketplaces(install-codex.ts)在安装sisyphuslabs时会额外清理旧 marketplacelazycodex与code-yeongyu-codex-plugins的缓存。同时reapLspDaemons会尽力回收遗留的 Codex LSP daemon,失败仅记录 warning 不阻断安装。
4.8 阶段 7:config.toml 改写
updateCodexConfig(codex-config-toml.ts)是字符串级 TOML 改写(通过toml-section-editor.ts逐段编辑,不引入 TOML 解析器依赖),按顺序完成:
- 先移除旧 marketplace(
lazycodex等)遗留的 marketplace 块、插件块与 hook 状态块,以及当前 marketplace 中过期插件的块; - 移除不再受管的 Agent 配置块(
removeStaleManagedAgentBlocks); - 依次确保开启
plugins、plugin_hooks、multi_agent特性(ensureFeatureEnabled); - 移除不支持的旧版 multi-agent mode 配置,写入基于模型目录(
readCodexModelCatalog)的 reasoning 配置,支持options.reasoning覆盖(off→none); - 写入 multi-agent v2 配置(
ensureCodexMultiAgentV2Config); autonomousPermissions !== false时写入自主任权限块(ensureAutonomousPermissions);- 写入 marketplace 块(本地源,
sourceType: "local",指向缓存根); - 逐个启用插件(
{plugin}@{marketplace})与内置 MCP 策略(ensureOmoBuiltinMcpPolicies); - 写入每个可信 Hook 状态的哈希(
ensureHookTrusted); - 写入每个 Agent 的
config_file = ./agents/xxx.toml引用。
最终通过writeFileAtomic原子落盘(config.trimEnd() + "\n"),配置不存在时从空串开始构建。
4.9 阶段 8-9:项目本地修复与遥测
repairProjectLocalCodexArtifactsBestEffort从projectDirectory向上扫描,修复项目本地.codex/config.toml与全局配置的冲突——只做"尽力而为",发现遗留项目产物只记录不删除。最后trackCodexInstallTelemetry记录install_completed事件,并返回完整的CodexInstallResult。
五、安装产物:WHAT IT WRITES 全表
安装完成后~/.codex/(或自定义CODEX_HOME)下的布局如下:
| 路径 | 内容 |
|---|---|
~/.codex/plugins/cache/{marketplace}/{plugin}/{version}/ | 构建完成的插件缓存(已 npm 安装、MCP 清单已改写、原子提升) |
~/.codex/.tmp/marketplaces/{marketplace}/ | 本地 marketplace 快照(插件源码拷贝 +marketplace.json) |
~/.codex/agents/*.toml | 从捆绑组件拷贝的 Agent 配置 |
~/.codex/config.toml | 被改写:marketplace 块、插件启用、特性开关、Agent 配置、hook 信任哈希、MCP 策略 |
~/.local/bin/(自定义 home 时为~/.codex/bin) | 组件 CLI 的符号链接或.cmdshim +omo包装器 |
值得注意的是~/.local/bin/是默认 binDir(由resolveCodexInstallerBinDir决定),只有自定义 home 时才回退到~/.codex/bin。
六、设计约定与反模式
文档归纳了三条必须遵守的设计约定(CONVENTIONS):
- TOML 改写一律基于字符串:经由
toml-section-editor.ts做文本级操作,刻意不引入 TOML 解析器依赖(ANTI-PATTERNS第一条:Never use a real TOML parser); - 原子目录提升:先拷贝到临时兄弟目录再
rename(),失败时恢复备份,绝不允许直接写活缓存(ANTI-PATTERNS第二条:Never skip the temp-and-rename promotion); - 平台差异:Windows 用
.cmdshim,POSIX 用符号链接。
第三条例外约束同样重要:新增受管 Agent 时,必须同步更新MANAGED_CODEX_AGENT_NAMES(同时存在于codex-config-agents.ts与codex-cleanup-config.ts),否则卸载时无法精确回收对应 Agent 文件(ANTI-PATTERNS第三条:Never hardcode new agent names)。此外,文档还强调兼容性负担:保留的 legacy purge 代码仍在追踪已退役的 reviewer agent,用于清理旧版本安装残留的陈旧配置与 Agent 文件。
七、卸载:与安装严格对称的清理编排
虽然文档正文聚焦安装,其产物与约定同样定义了卸载语义。cleanupCodexLight(codex-cleanup.ts)是卸载编排器,与安装形成镜像:
- 先读后删:在删除任何受管目录前,先读取
.installed-agents.json与安装期记录的 binDir(readInstalledCodexBinDir)——因为清单文件本身就位于将被删除的受管树内; - Agent 回收:结合
MANAGED_CODEX_AGENT_NAMES与清单路径(.tmp/marketplaces/sisyphuslabs/plugins/omo/.installed-agents.json及各缓存版本下的清单)收集 Agent 路径,逐条安全校验(必须在~/.codex/agents/内、文件名必须匹配受管名单)后移除; - 受管状态目录:删除
plugins/cache/sisyphuslabs、.tmp/marketplaces/sisyphuslabs、runtime/ast-grep、runtime/node、plugins/data/omo-sisyphuslabs/bootstrap,并以 glob 兜底(深度 ≤ 5)清理布局漂移的 bootstrap 目录;源码注释明确安全不变量——只删受管子树,绝不整体删除runtime/; - 安全校验:
validateManagedCleanupTarget会拒绝指向文件系统根或越界的清理目标(codex-cleanup-safety.ts),bin 链接清理同理; - 项目本地修复:复用与安装相同的
repairProjectLocalCodexArtifactsBestEffort; - 重试语义:
removeManagedPathBestEffort采用"单次重试"策略——正在运行的 bootstrap worker 可能在首次删除后重建状态,若重试后仍存在,命令依然以 0 退出,再次执行lazycodex-ai uninstall即可清干净。
结语
install-codex安装器的设计可以概括为三个关键词:原子性(temp-and-rename 提升与原子 config 写入)、可逆性(.installed-agents.json清单 + 安装期记录的 binDir,让卸载能精确还原)、兼容性(保留旧 marketplace 清理、旧 Agent 追踪与 sparkshell 引用扫描,平滑迁移历史安装)。如果你要在自己的 Codex 环境里排查插件问题,建议按本文第三节的路径优先级检查CODEX_HOME、CODEX_LOCAL_BIN_DIR、OMO_CODEX_PROJECT等环境变量,再对照第五节的产品表核对每个目录是否存在;若需彻底重装,则走npx lazycodex-ai uninstall,它会依据清单精确回收全部受管产物。
- 人工智能
- AI Agent
- 代码智能体
- 多智能体
- MCP Clients
- Agent 编排
【免费下载链接】oh-my-openagent
OmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.
相关推荐
CANN/asc-devkit创建算子工程指南
创建算子工程<a name="ZH CN_TOPIC_0000001618617245" </a CANN开发套件包中提供了自定义算子工程生成工具msOpGen
人工智能AI Agent代码智能体多智能体MCP ClientsAgent 编排用 Codex app-server 做一手钩子验证:oh-my-openagent 的 Codex 插件 QA 通道全解析
用 Codex app server 做一手钩子验证:oh my openagent 的 Codex 插件 QA 通道全解析 本篇文章围绕 oh my open
人工智能AI Agent代码智能体多智能体MCP ClientsAgent 编排如何通过 Codex 插件市场安装 LazyCodex omo 插件并批准 hooks?
如何通过 Codex 插件市场安装 LazyCodex omo 插件并批准 hooks? 如果你已经在使用 OpenAI Codex CLI,想完全在 Code
人工智能AI Agent代码智能体多智能体MCP ClientsAgent 编排
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考