1实现原理 · 为什么它能做到
核心是一条 Node 脚本:扫描 Codex 生成图目录,选图,组装 item_add 载荷,把图片路径与提示词写入 Eagle 素材库。
Archive images generated by Codex into Eagle and preserve the prompt as searchable metadata.
与 Eagle 的通路有两条:默认走本地 HTTP 回环端点;若本机 Codex 配置里有 Eagle stdio MCP 条目,则自动改走 stdio(spawn 子进程)。
Stdio mode: the script reads the current user's `~/.codex/config.toml`, prefers `[mcp_servers.eagle]`, and can auto-detect other Eagle-like stdio MCP entries. Use `--transport http` to force the legacy HTTP path.
HTTP 路径就是对一个本地回环地址做 POST /api/tools/call,请求体是 {tool, params} 的 JSON。
path: '/api/tools/call',
stdio 路径用 child_process.spawn 拉起配置里的命令,并且把宿主的整个 process.env 透传进子进程(再叠加配置里的 env)。
this.child = spawn(this.config.command, this.config.args || [], {
文件夹解析按「精确父子路径」而非名字:先向上解析根目录,再只在根下按 name+parentId 找日期目录,避免同名串台。
- Folder safety: resolve folders by exact parent-child path, not by name alone.
并发安全用本地文件锁(os.tmpdir 下以参数哈希命名的 lock 目录)串行化「查目录 → 建目录」临界区。
const lockDir = path.join(os.tmpdir(), `codex-image-to-eagle-${hashKey(key)}.lock`);
提示词与溯源信息以固定文本模板写入 Eagle 的 annotation 字段,构成可检索的复盘元数据。
'- source: Codex',
幂等与防重复:同一根目录下若已存在多个同名日期目录,复用最旧的那个并报告重复,而不是再造一个。
If more than one matching date folder already exists under the same root, reuse the oldest existing folder ID and report the duplicate instead of creating another one.
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| package | Node.js(无 npm 依赖,仅内置 fs/path/http/os/child_process) |
| network | Eagle MCP Server(本地回环 HTTP) |
| network | Eagle MCP Server(本地回环,README 侧写为 localhost 同端口) |
| cli | Eagle 桌面应用 + Eagle MCP 插件(第三方,必须运行才能写入) |
| cli | stdio MCP 代理子进程(从 ~/.codex/config.toml 解析出的 command/args,如 mcp-proxy.js) |
4风险提醒 风险提醒:橙色 · 评估后使用
- 执行面来自本机配置:脚本会读取 ~/.codex/config.toml 并 spawn 其中的命令,且透传全量环境变量。 — spawn(this.config.command, ...) 无白名单校验;若配置文件被改写或含非 Eagle 条目被误判(looksLikeEagleMcpConfig 兜底扫描),会拉起非预期进程。
- 强依赖第三方桌面软件与插件,非自包含。 — Eagle 未运行 / MCP 插件未启用时链路直接失败;Skill 自身不含任何图片处理能力。
- 写入不可逆地与素材库耦合:重复归档会在 Eagle 产生重复素材。 — README 自述『未建议随意反复测试实际写入命令,因为会在 Eagle 中产生重复素材』;脚本无去重比对(同图重复导入不会被识别)。
- 隐私面:图片内容与提示词会进入 Eagle 的本地素材库(含文件夹层级与日期)。 — annotation 里还写入 original_path(本机绝对路径),若素材库被同步/分享会暴露路径结构。
5第二遍独立确认
- [ok] 每条外部依赖的反查 — Node 依赖:脚本 require 仅 fs/path/http/os/child_process,无 node_modules、无 package.json;Eagle 回环端点:DEFAULT_SERVER 常量 + callTool() 的 http.request 两处互证;stdio 子进程:spawn 调用点 + README 的 mcp-proxy.js 示例互证。
- [ok] 是否有被遗漏的网络调用 — 全文件仅 import http 一处,唯一 http.request 出现在 httpRequest(),被 callTool() 以 DEFAULT_SERVER 构造的 hostname/port 使用;无 fetch/https/axios/WebSocket。
- [ok] 凭证读取结论的反例搜索 — process.env 命中集中在配置项(图片目录/服务地址/文件夹 ID/MCP 参数/锁超时),未见读取密钥文件、keychain、.env 或打印敏感值;但 spawn 透传全量 env 确认成立,故归入橙档依据之一。
- [ok] 文件夹安全规则 vs 代码实现 — SKILL 第 1–5 条规则均可在代码定位:fixedFolderId 短路、folder_get(getAllHierarchy/fullDetails)、findFolderByNameAndParent(name+parentId)、folder_create(parentId)、复用最旧(按 createdAt 升序取 matches[0])。
- [ok] 默认服务地址描述一致性 — SKILL.md/脚本为 127.0.0.1:41596 并说明优先 IPv4 回环的原因;README 写 localhost:41596。二者同端口不同写法,已分别作为独立条目取证,不视为出入。
- [ok] 功能声明与实现相符度 — description 承诺的 save/archive/import/sync + prompt/tags/folders 全部有对应实现(item_add 载荷含 tags/items、annotation、folders);『不泛化为任意素材库迁移』与代码仅面向 Eagle 相符。
- [ok] dry-run 是否真的不写库 — resolveFolderPath() 在 dryRun 时直接返回伪造的 folder-path 字符串,main() 在 dryRun 分支提前 return,未调用 item_add —— 预览路径无写入,结论成立。
6结论
5914cacc5fbf46dc…fcee81beb6