codex-image-to-eagle
Archive Codex-generated images from the current user's Codex generated_images directory into Eagle with the prompt saved as annotation. Use when the user asks to save, archive, import, or sync Codex generated images to Eagle with prompts, tags, and folders.
1How It Works & Mechanism
The core is a Node script: it scans the Codex generated image directory, selects images, builds the item_add payload, and writes the image paths and prompts into the Eagle library.
Archive images generated by Codex into Eagle and preserve the prompt as searchable metadata.
There are two communication pathways to Eagle: by default, it uses a local HTTP loopback endpoint; if an Eagle stdio MCP entry exists in the local Codex configuration, it automatically switches to stdio (spawning a child process).
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.
The HTTP path performs a POST /api/tools/call against a local loopback address, with a JSON request body of {tool, params}.
path: '/api/tools/call',
The stdio path uses child_process.spawn to launch the command defined in the config, passing the host's entire process.env through to the child process (overlaid with any env in the config).
this.child = spawn(this.config.command, this.config.args || [], {
Folder resolution relies on 'exact parent-child paths' rather than just names: it first resolves the root folder upward, then searches for date folders under the root by name+parentId to prevent accidental cross-linking between identically named folders.
- Folder safety: resolve folders by exact parent-child path, not by name alone.
Concurrency safety uses local file locks (a lock directory named after a parameter hash under os.tmpdir) to serialize the critical section of 'check folder → create folder'.
const lockDir = path.join(os.tmpdir(), `codex-image-to-eagle-${hashKey(key)}.lock`);
Prompts and provenance metadata are written into Eagle's annotation field using a fixed text template, establishing searchable review metadata.
'- source: Codex',
Idempotency and deduplication: if multiple date folders with the same name already exist under the same root folder, it reuses the oldest one and reports duplicates instead of creating a new one.
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.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| 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) |
4Recommended Governance & Evidence
- scripts/: Executes local script or command: node scripts/archive-codex-image-to-eagle.js (bundled script triggered by agent via Bash(node *))
- 网络端点: Declared external network access: Local loopback only: HTTP POST http://127.0.0.1:41596/api/tools/call (can be overridden by EAGLE_SERVER_URL)
- 本地工作目录: File I/O and artifact output: Local only: creates/deletes <hash>.lock directories under os.tmpdir() to serialize folder creation; does not write images or modify source files
5Second-Pass Verification
- [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 —— 预览路径无写入,结论成立。
6Verdict & Scenarios
5914cacc5fbf46dc…