Floorplan 在 Codex 中的完整实践:插件安装、$floorplan 绘图与只读 Ask 问答

发布时间:2026/11/2 18:52:34
Floorplan 在 Codex 中的完整实践:插件安装、$floorplan 绘图与只读 Ask 问答

【免费下载链接】floorplan

See how your app actually fits together. An interactive, plain-English map of your codebase, drawn by Claude or Codex.

项目地址:https://gitcode.com/gh_mirrors/floorplan/floorplan
点击查看免费下载

本文以 Floorplan 的 Codex 指南为主线,讲清楚三件事:如何在 Codex 应用中完成安装、如何用$floorplan生成并更新代码地图、以及地图上的 Ask 栏是怎样通过codex exec在你自己的 ChatGPT 登录态下以只读沙箱回答问题的。读完后你能独立完成安装、按需切换推理引擎、定位 CLI 路径,并清楚它与 Claude Code 版本的差异所在。

同一个技能,两套宿主

Floorplan 在 Codex 中的工作方式与在 Claude Code 中完全一致:同一份 skill、同一套脚本、同一张地图,差别只在于宿主如何加载插件、以及 Ask 栏调用哪个 CLI。整个过程不需要配置任何 API Key,使用的是你已经登录的 ChatGPT 账号。

这一点在仓库结构里可以直接看出来:Claude Code 的清单放在.claude-plugin/,Codex 的清单放在.codex-plugin/,两者version与description保持一致(发布测试tests/release.test.mjs正是校验这种一致性),而真正被两个宿主共用的技能定义只有一份,位于 skills/floorplan/SKILL.md。Codex 侧的入口描述则由 skills/floorplan/agents/openai.yaml 提供,它声明了展示名、一句话说明和默认提示词。

前置条件

  • Codex:桌面应用或 CLI 均可,需要已用 ChatGPT 账号登录。
  • Node.js 18 或更高版本。Floorplan 的所有脚本都是零依赖的普通 Node.js 程序,package.json中的engines字段即声明>=18(见 package.json)。

用一条命令确认 Node 版本:

node --version

与 Claude Code 相比,Codex 侧不需要额外安装 CLI 才能让 Ask 栏工作——Codex 应用本身已经包含 Ask 栏所依赖的能力。只有在你想手动指定可执行文件、或在服务器等场景下单独启动地图服务时,才需要关心codex命令本身是否在 PATH 上。

安装:应用内图形界面或命令行

在 Codex 应用内安装(无需终端)

  1. 打开Plugins,选择Add a marketplace。
  2. Source填入haydenschmitty/floorplan,Git ref留空,点击Add marketplace。
  3. 在列表中找到Floorplan,点+安装。
  4. 新建一个会话(插件在会话启动时加载)。

用 Codex CLI 安装

codex plugin marketplace add haydenschmitty/floorplan codex plugin add floorplan@floorplan

第一条命令把这个仓库注册为插件市场,第二条把floorplan@floorplan安装到你的环境。应用与 CLI 共享插件目录,所以在其中一侧安装,另一侧也能直接使用。

从仓库视角看,marketplace add读取的是 .agents/plugins/marketplace.json,其中把本仓库声明为一个单插件市场,插件源指向./,并设置了installed/authentication策略;而plugin add读取的是 .codex-plugin/plugin.json,它声明"skills": "./skills/",并带有"requires_local_executor": true——这正是 Floorplan 需要在你的机器上执行node脚本的原因。该文件里还有interface.defaultPrompt三个默认提示词("Draw a floorplan of this codebase"、"Update the floorplan with what we just changed"、"Show me how the frontend talks to the backend"),因此你在 Codex 的输入框里可以直接看到推荐话术。

画出第一张地图

在 Codex 中打开你的项目文件夹,然后用自然语言提问即可:

Draw a floorplan of this codebase

想按名字调用技能,输入$floorplan。之后的流程与 Claude Code 完全相同:Codex 扫描代码,为每个部分、文件和 Web 请求写名字与说明,构建地图并打开它。之后说"update the floorplan",它只重新读取发生变化的部分。

Codex 是如何被识别出来的

地图需要记住"是谁画的",这样 Ask 栏和"Fix with …"提示词才能叫对名字。识别逻辑在 skills/floorplan/scripts/lib/agent.mjs:

const DETECT = { claude: () => false, // the default codex: (env) => !!(env.CODEX_THREAD_ID || env.CODEX_SESSION_ID), };

优先级是--agent <name>参数 →FLOORPLAN_AGENT环境变量 → 环境变量探测 → 默认claude。传入无法识别的值时会被忽略并回落到探测结果,这一行为在 tests/agents.test.mjs 中有明确断言(例如detectAgent({ agent: 'gpt' }, { CODEX_THREAD_ID: 'abc' })仍返回codex)。

识别结果写入graph.json的meta.agent,构建日志会打印AGENT Codex: questions on the map run through Codex(见 skills/floorplan/scripts/build.mjs)。打开的地图页面随后根据它决定按钮文案:skills/floorplan/assets/viewer.html 中,当服务器引擎或地图构建者被判定为 codex 时,界面使用{ id: 'codex', name: 'Codex', app: 'Codex' },登录提示也改成"打开 Codex 应用(或运行codex login)后重试"。

沙箱与地图服务器

Codex 打开地图时会要求把地图的服务器放到沙箱之外运行。原因有两层:服务必须在命令结束后继续存活,而 Ask 栏又需要访问网络才能连到 Codex。如果你不想授权,可以在项目目录里自行启动:

node floorplan/serve.mjs

服务只监听127.0.0.1,默认端口 4378,并在启动后打印实际 URL。它还会校验请求的Host头必须是自己机器的名字,并给每个会话生成随机 token——即使网页发起 DNS 重绑定把域名指向127.0.0.1,也拿不到/api/*的访问权(实现见 skills/floorplan/assets/serve.mjs)。

Ask 栏:在你自己的机器上运行 Codex

地图上的 Ask 栏会在你本机运行codex exec,进入 Codex 的read-only沙箱,工作目录是你的项目文件夹,使用的是你的 ChatGPT 登录态。它阅读地图和源码来作答,且无法修改任何文件。这些运行不会写入你的 Codex 历史;追问时,服务会把最近几轮问答一起带上。

这些描述在源码里逐条可以对应上。codexRun(skills/floorplan/assets/serve.mjs)构造的参数是:

const args = [...cli.args, 'exec', '--json', '--sandbox', 'read-only', '--skip-git-repo-check', '--ephemeral', '--output-schema', mode.file, '-C', root]; if (model) args.push('--model', model); args.push('-');

逐项解释:

参数作用带来的实际约束
exec非交互式执行一次请求一次提问一次进程
--json输出 JSONL 事件流服务按行解析,转成进度与最终答案
--sandbox read-only只读沙箱确认是 CLI 层面强制的只读,而非提示词约束
--skip-git-repo-check跳过 git 仓库校验非 git 目录也能用
--ephemeral不落盘为历史会话不污染 Codex 历史记录
--output-schema <file>用文件指定输出结构Codex 从文件读取 schema
-C <root>指定工作目录固定为地图所在的项目根
-从标准输入读提示词请求内容经 stdin 送入

结构化输出为什么要"改写"一次

--output-schema指向.cache/下的 JSON 文件,由load()在启动与每次重建地图时写出。关键在于:OpenAI 的结构化输出要求对象里每个属性都在required中,且不允许额外属性。因此serve.mjs在写盘前会递归地"收紧" schema:

function strict(s) { if (s?.type === 'object' && s.properties) return { ...s, properties: Object.fromEntries(Object.entries(s.properties).map(([k, v]) => [k, strict(v)])), required: Object.keys(s.properties), additionalProperties: false }; if (s?.type === 'array') return { ...s, items: strict(s.items) }; return s; }

可选列表在这里一律变成"必填但可以为空"——这正是"可选的列表就返回空数组"的实际含义。测试 tests/ask.test.mjs 会遍历整份 schema,断言每个 object 都满足additionalProperties: false且required与properties的键集合一致,并确认steps、followups都在必填之列。

也因为 Codex 是"从文件读 schema"的引擎,ENGINES.codex里带有schemaFile: true标记(skills/floorplan/assets/serve.mjs),写盘逻辑据此只在 Codex 引擎下执行。

追问如何保持上下文

由于--ephemeral让每次运行彼此独立,服务用一个内存表convos维护对话:每轮结束后保存{ q, a },其中问题截断到 500 字符、答案截断到 1500 字符,只保留最近 4 轮:

convos.set(session, [...turns, { q: question.slice(0, 500), a: String(a.answer || '').slice(0, 1500) }].slice(-4));

下一轮把这段内容以Earlier in this conversation:的形式拼进提示词。测试同时验证了两点:首轮提示词里不含该段,第二轮才出现;传入一个不认识的 session 会开启全新对话而不是复用旧上下文。会话 ID 是 16 位十六进制随机串。

引擎选择与 CLI 定位

服务端使用哪一个引擎,遵循如下顺序(skills/floorplan/assets/serve.mjs):

  1. --engine claude|codex,或环境变量FLOORPLAN_ENGINE;
  2. 否则用构建这张地图的那个 agent(读graph.json的meta.agent);
  3. 都不匹配则默认claude;
  4. 随后按顺序尝试定位 CLI,第一个找到的胜出——但显式指定--engine时不再回退,找不到就直接报cli_missing。

在地图由 Claude 构建、但机器上只装了 Codex 的场景里,回退机制让 Ask 栏依然可用;而想强制走某个引擎时,显式指定就是硬性约束。强制指定 Codex:

node floorplan/serve.mjs --engine codex

CLI 的查找范围:codex在 PATH 上(which/where),以及在 Windows 上 Codex 桌面应用自带的 CLI——它位于版本化目录%LOCALAPPDATA%\OpenAI\Codex\bin\<version>\codex.exe下,代码会按修改时间倒序取最新的一个(codexApp())。如果你的 Codex 装在别处:

node floorplan/serve.mjs --codex /path/to/codex

模型方面,--model <name>(或环境变量FLOORPLAN_MODEL)会决定调用哪个模型;不指定时由你的 Codex 设置决定。

一个容易被忽略的细节:子进程环境清理

服务器本身可能是从 Codex 会话内部启动的。如果原样把环境变量传给子进程,CLI 会误以为自己被嵌套在另一个会话里。服务因此在派生子进程前会剥掉一批变量(skills/floorplan/assets/serve.mjs):

for (const k of Object.keys(env)) if (/^CLAUDE_?CODE_(SESSION|ENTRYPOINT|CHILD|MESSAGING|HOST|SDK)|^CLAUDECODE$|^CODEX_(THREAD_ID|SESSION_ID|TOOL_CALL_ID|CI$|SANDBOX)/.test(k)) delete env[k];

注意CODEX_THREAD_ID、CODEX_SESSION_ID、CODEX_SANDBOX都在清理列表中——识别地图作者用它们,回答问题时不带它们。

出错时用户看到什么

failCode()会把错误归类为三种:登录相关(not logged in、401、sign in等)→not_logged_in;额度相关(429、rate limit)→rate_limited;其余 →cli_error。界面据此给出对应提示,Codex 的登录提示是"打开 Codex 应用或运行codex login"。测试用一个提示词里含SIGNED-OUT的假 CLI 复现了未登录路径,断言事件类型为failure且 code 为not_logged_in,并确认此时不会产出answer。

和 Claude Code 的三处差异

一、不写任何笔记文件

在 Claude Code 中,Floorplan 会在CLAUDE.local.md里维护一小段带标记的说明,指向地图与query.mjs的几个查询命令。这段逻辑在 skills/floorplan/scripts/lib/claudemd.mjs 中:块由<!-- floorplan:start -->与<!-- floorplan:end -->包裹,只重写自己的块,其余内容不动,并把该文件加入仓库本地的.git/info/exclude(而非.gitignore),因此不会影响已跟踪文件。

Codex 没有等价的"个人、不提交"的笔记文件——AGENTS.md是与团队共享的。所以 Codex 下 Floorplan 不碰你的项目笔记。测试对此有双重断言:用--agent codex构建后,CLAUDE.local.md和AGENTS.md都不存在;而用--agent claude构建后,CLAUDE.local.md中能看到/floorplan/query.mjs的引用。

二、没有 Claude app 这条发布路径

把地图发布到 Claude app 是 Claude 的特性。在 Codex 中,地图就是在你的浏览器里打开,由你本机的服务提供。对应的离线替代方案是"导出":node floorplan/serve.mjs --export [<file>] [--include flows,notes,recent,health],默认只带flows与notes,导出的单文件 HTML 会去掉 Ask 栏、本机路径与 git remote 信息(见 skills/floorplan/assets/serve.mjs)。这在你需要把地图发给别人看时最实用。

三、修复提示词改成对着 Codex 说

Health 面板里现成的修复提示词,在 Codex 版本中是给你粘贴进 Codex 的;蓝图上的Build this with Codex同理。工具栏的Change开关同样让 Codex 在只读沙箱中运行:Codex 返回更新后的计划,由地图服务器负责保存。

这条链路的实现值得展开,因为它展示了"只读的 agent 也能改计划"是怎么做到的。changePlan()(skills/floorplan/assets/serve.mjs)先把请求交给runAgent,再把返回的完整plan.json与architecture.json交给applyChange():先做快照(保留最近 20 份,用于 Undo),写盘,然后用技能自带的脚本校验并重绘——plan.mjs,build.mjs --check,最后build.mjs --no-claude-md。若检查不通过(例如有规划文件落在任何节点的 glob 之外),快照会被回滚,并把问题回喂给模型重试一次。整个过程有并发保护:changing为真时再次提交会返回busy。只有声明了structured: true的引擎才会出现 Change 开关,因为整条链路依赖 CLI 严格遵守 schema。

更新、移除与本地副本

更新

在应用内打开Plugins,找到 Floorplan 市场,选择Upgrade;或在终端执行:

codex plugin marketplace upgrade floorplan codex plugin add floorplan@floorplan

移除

codex plugin remove floorplan@floorplan codex plugin marketplace remove floorplan

地图本身不受影响——它们留在各项目的floorplan/目录里,直到你主动删除。

试用本地工作副本

把 Codex 指向本地克隆而不是远端仓库:

codex plugin marketplace add /path/to/floorplan codex plugin add floorplan@floorplan

这里有一个与 Claude Code 的重要差异:当添加本地插件时,Codex 会把插件复制进自己的缓存;Claude Code 则是直接从文件夹运行。这意味着你改完插件后必须重新执行codex plugin add floorplan@floorplan并开启新会话,改动才会生效。安装后的缓存路径形如~/.codex/plugins/cache/floorplan/floorplan/<version>(见 docs/is-it-safe.md),可用codex plugin list查看当前版本。

如果你在开发 Floorplan 本身,--agent claude|codex(在build.mjs上)与--engine claude|codex(在serve.mjs上)可以让你从任意环境模拟任一宿主的产物,这一点在 docs/development.md 中有说明。

命令速查

目的命令
添加插件市场codex plugin marketplace add haydenschmitty/floorplan
安装插件codex plugin add floorplan@floorplan
升级市场codex plugin marketplace upgrade floorplan
移除插件codex plugin remove floorplan@floorplan
移除市场codex plugin marketplace remove floorplan
自行启动地图服务node floorplan/serve.mjs
强制走 Codex 作答node floorplan/serve.mjs --engine codex
指定 Codex 可执行文件node floorplan/serve.mjs --codex /path/to/codex
指定模型node floorplan/serve.mjs --model <name>
停止后台服务node floorplan/serve.mjs --stop
导出可分享副本node floorplan/serve.mjs --export [<file>]
查看安装情况codex plugin list

serve.mjs还接受--port(默认 4378,端口被占用时会自动往后试到 +20)、--no-open(不自动打开浏览器)与--idle-exit <分钟>(最后一个标签页关闭后多久退出,后台启动时open.mjs用的是 120 分钟)。

常见问题定位

  • Ask 栏提示需要 Codex:服务在 PATH 中找不到codex,且(Windows 上)也没找到桌面应用自带的 CLI。安装 Codex CLI,或用--codex /path/to/codex指定路径。
  • 提示未登录:打开 Codex 应用,或在终端运行codex login后用 ChatGPT 账号登录,然后重新提问。
  • 地图没打开,或 Ask 在 Codex 打开地图后失效:Codex 在沙箱中执行命令,而地图服务需要持续运行并访问网络。在 Codex 询问时允许服务在沙箱外运行,或自己在项目目录里执行node floorplan/serve.mjs。
  • node不被识别:安装 Node.js 18+,然后重启会话让 Codex 重新读取 PATH。
  • Change 开关不出现:它只出现在蓝图(从 PRD 规划出来的地图)上,且必须通过node floorplan/serve.mjs打开、并且可用的引擎支持结构化输出。真实代码的地图没有 Change——先让 Codex 改代码,再更新地图。

更多排障条目见 docs/troubleshooting.md,安全性说明与可自行校验的安装指纹见 docs/is-it-safe.md,地图上每个按钮与面板的用法见 docs/using-the-map.md,地图是如何从扫描到渲染的见 docs/how-it-works.md。

【免费下载链接】floorplan

See how your app actually fits together. An interactive, plain-English map of your codebase, drawn by Claude or Codex.

项目地址:https://gitcode.com/gh_mirrors/floorplan/floorplan
点击查看免费下载

相关推荐

上一篇:如何用Nova3D搭建机器人训练环境?从文本提示词到仿真农场采摘的完整实战
下一篇:Monid快速上手教程:5分钟让你的AI Agent接上网页搜索与数据工具(从Deno环境到真实调用)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考