我与 Codex 的一周:从一份设计文档到一个桌面应用
WingsBlogManager 是一个 Electron + Svelte 5 桌面应用,用于可视化管理个人博客的 21 个配置文件、文章、媒体资源和部署流程。从 7 月 3 日的第一条消息到 7 月 10 日的 Release 打包,我和 Codex 一起把它从零做到了交付,来做一个小小的复盘。
展示图:

一、项目缘起
痛点
我当前的博客 WingsBlog,部署在 Cloudflare Pages 上,采用 TypeScript 配置驱动架构——所有站点设置分散在 21 个 .ts 配置文件中:
src/config/├── siteConfig.ts (220+ 行,最复杂)├── profileConfig.ts (个人资料)├── navBarConfig.ts (导航栏,含动态函数)├── sidebarConfig.ts (双侧边栏 widget 布局)├── fontConfig.ts (自定义字体)├── pioConfig.ts (Live2D + Spine 看板娘)├── friendsConfig.ts (友链,含筛选函数)├── footerConfig.ts (页脚 HTML)├── musicConfig.ts (音乐播放器)├── commentConfig.ts (评论系统,5 种后端)├── ... 还有 11 个└── i18n/languages/*.ts (5 种语言,385 个翻译 key)每次改配置都要:打开 .ts 文件 → 修改代码 → Git 提交推送 → 等 Cloudflare 重新部署。写一篇文章要在编辑器里手写 frontmatter YAML,管理图片要手动往 public 目录里丢文件。
这不是博客管理,这是代码维护。
想法
我需要一个桌面应用,把所有这些”改代码”的操作变成可视化的表单、开关、拖拽和预览。7 月 3 日,我写了一份 DESIGN.md 设计文档,然后打开 Codex,说了第一句话:
“根据设计计划内容开始开发(用户界面等设计部分可以根据你的分析做调整,做到界面对用户使用友好)”
这句话开启了一场为期一周、跨越 70+ 轮对话的密集协作。
二、开发全貌
数字概览
📅 开发周期 2026.07.03 — 2026.07.10(8 天)🗂️ 主会话 2 个(3430 行 + 2173 行 JSONL)🔀 子 Agent 会话 8 个独立子线程并行勘察📝 用户消息 71 条📦 完成阶段 P0 → P8,全部交付🧪 测试用例 298 个(Vitest)✅ TypeCheck 0 errors🔨 Build 通过📦 Release 已生成 NSIS 安装包技术栈
| 层级 | 选型 | 理由 |
|---|---|---|
| 桌面框架 | Electron 34 | 需要直接读写本地文件系统、执行 git、启动 astro dev |
| 构建 | electron-vite | Vite 驱动,支持 HMR |
| 前端 | Svelte 5 (runes) | 运行时代码量小,与 WingsBlog 同技术栈 |
| 样式 | Tailwind CSS 4 | 与 WingsBlog 保持一致 |
| Markdown | Milkdown 7 (ProseMirror) | 所见即所得,插件可扩展 |
| 配置解析 | ts-morph | TypeScript AST 级别读写 |
| Git | simple-git | Node.js Git 封装 |
| 测试 | Vitest | 服务层 + 前端 + 集成 + 组件冒烟 |
三、协作实录:从 P0 到 P8 的全过程
3.1 开局:一份设计文档 + 一个指令
我的第一条消息很简单:“根据 DESIGN.md 开始开发”。Codex 做的第一件事不是写代码,而是——派出一个子 Agent(Lorentz,explorer 角色)做只读勘察。
这个子 Agent 发现了关键问题:
-
npm run typecheck因为缺少node_modules无法执行 -
.git目录不是有效仓库 -
Svelte 模板中有潜在的运行时错误风险
这恰恰是 AI 协作中最容易被忽略的环节——代码可以写,但环境和前提条件不对,写了也跑不起来。
在第一个会话中,我明确提出了协作原则:
“当前正在开发一个较复杂的项目,对话上下文可能会逐渐变长。每次任务尽量只处理一个明确功能点。修改代码前先阅读相关文件并给出简短计划。优先做最小必要修改。重要设计决策需要沉淀到项目文档中。”
这些原则后来被写入 AGENTS.md,成为后续所有协作的基础。
3.2 P0—P2:打地基(7/3 — 7/4)
前三个阶段解决的是”能不能安全地读写配置”这个根本问题。
P0:安全补丁。Codex 发现 fontConfig.ts、friendsConfig.ts、navBarConfig.ts 和 pioConfig.ts 这 4 个文件包含多个导出或动态函数,用通用的”读第一个导出、重写整个文件”的方式会破坏数据。于是将这些标记为 safeToWrite: false,禁用通用编辑器的 Save 按钮。
P1:精确写入 + 表单编辑器。将 ConfigService 改为”只替换目标导出变量的初始化器文本”,而不是重写整个文件。同时为上述 4 个复杂配置文件开发了专用的多导出编辑器。
这里有一个让我印象深刻的细节:Codex 在开发配置写回功能时,又派出了一个子 Agent(Euler,explorer 角色)分析风险。子 Agent 给出的结论是:
“单导出纯配置文件基本可用,多导出/动态文件不适合直接写回。
fontConfig.ts、friendsConfig.ts等文件有多个导出,getDynamicNavBarConfig()是函数返回动态数据,当前工具无法安全处理。”
这种”先勘察、再开发”的模式让 Codex 的每一次改动都有理有据。
P2:Git + Cloudflare + 首次运行引导。三天时间,应用有了 Git 面板(status/diff/commit/push)、Cloudflare Pages 部署状态面板(触发/重试/监控)和首次运行的 Setup 向导。
3.3 P3—P4:打磨与扩展(7/4 — 7/5)
P3 最核心的工作是”配置编辑器去 JSON 化”。原来的实现是:每个配置文件打开就是一个 JSON 编辑器,用户看到的是裸数据。Codex 逐一为每个配置开发了专用表单编辑器:
| 配置 | 编辑器形态 |
|---|---|
friendsConfig.ts | 页面设置 + 友链表格,支持新增/编辑/删除 |
navBarConfig.ts | 搜索配置 + 链接预设表单 + 动态菜单结构可视化编辑 |
sidebarConfig.ts | 左/右/移动端 widget 布局拖拽 |
fontConfig.ts | 字体库定义 + 字体选择器 |
pioConfig.ts | Spine 模型 + Live2D widget 配置 |
最难的是 navBarConfig.ts 的动态菜单编辑器——因为导航菜单不是固定数据,而是通过 getDynamicNavBarConfig() 函数动态生成的。Codex 再次派出子 Agent(Fermat,explorer)勘察后,设计了”直接读写函数体内的 links 数组”的方案,而不是试图解析整个函数逻辑。
P4 加上了许多”让应用像正经产品”的东西:
-
键盘快捷键(Ctrl+S 保存、Ctrl+N 新建文章、Ctrl+Shift+R 刷新预览)
-
暗色模式(localStorage 持久化 + CSS 全局覆盖)
-
配置备份/导出和恢复/导入
-
全局错误边界 + 操作历史面板
-
Cloudflare Token 改用 Electron
safeStorage加密存储(之前是明文存在 settings 里)
3.4 关键一战:Ctrl+S 的脏状态管理
在开发 P3 的多导出编辑器时,出现了一个经典的状态管理 Bug:
问题:FriendsConfigEditor 同时管理”页面设置”和”友链列表”两个区块。用户改了友链后按 Ctrl+S,结果页面设置的未保存修改也被清除了。
Codex 的诊断是——只有一个全局 dirty 标记。解决方案是将脏状态按区块粒度拆分:
FriendsConfigEditor: dirty → dirtyPage + dirtyLinksFontConfigEditor: dirty → dirtyFonts + dirtySelectionNavBarConfigEditor: dirty → dirtySearch + dirtyPresets + dirtyMenu并且 Ctrl+S 的行为改为:只在恰好一个目标为脏时才自动保存;多个区块都脏时,用户必须点击对应区块的保存按钮。
我让 Codex 用子 Agent 审查这个修复。子 Agent 精准地确认了修复的正确性:
“保存一个 section 不能清除无关的未保存更改——当前实现通过分 section 的 dirty 标记正确解决了这个问题。”
这种 “主 Agent 开发 + 子 Agent 审查” 的模式在后续开发中反复使用,效果很好。
3.5 P5—P8:从”能跑”到”能用”(7/5 — 7/10)
这是一次方向性的转折。
在第二个会话中,我提出了核心诉求:
“当前项目其实并没有很好地解决原来修改配置文件需要打开 JSON 文件修改代码的复杂度。我的核心诉求是,需要以直观的方式让用户能够修改博客的各项配置,不要展现这些底层的配置文件代码和修改。”
Codex 的响应是:暂停开发,先做设计调研。它调研了 Figma 和 GitHub 上类似项目的界面设计,然后产出了一份 CONFIG_CENTER_DESIGN.md——配置中心信息架构和字段控件 Schema 设计方案。
核心设计思路:用 Schema 驱动的表单替代 JSON 编辑器。
实现了一个通用的 SchemaConfigEditor.svelte 组件,支持:
-
文本/文本域/数字/布尔/下拉/标签/数组等控件
-
条件显示(如:选择某评论后端时才显示对应配置项)
-
媒体选择器(图片/音频直接从 WingsBlog
public目录选择) -
排序数组(拖拽排序友链、音乐列表等)
-
高级 JSON 模式(给开发者留的后门)
基于这个 Schema 系统,一口气覆盖了 profile、announcement、license、plantuml、comment、music、wallpaper、analytics、cover-image、gallery、sponsor、effects、expressive-code 共 13 个配置——全部变成了可视化表单。
P5—P7 还完成了:
-
Milkdown WYSIWYG 编辑器:安装 Milkdown 7.21.2,实现所见即所得编辑、源码切换、预览模式
-
Markdown 工具栏:标题/列表/引用/代码块/表格/链接/图片,带状态高亮和键盘操作
-
表格尺寸选择器:6×6 网格 hover 选择,与 Typora 体验一致
-
表单验证增强:URL/范围/必填/长度/正则,保存前逐字段验证
-
性能优化:搜索 150ms 去抖、JSON 延迟序列化
-
297 个 Vitest 单元测试(PostService 61 + ConfigService 65 + SettingsService 44 + I18nService 22 + MediaService 25 + 集成测试 + 前端测试)
P8 及后续完善:
-
壁纸/音乐本地资源导入(文件→
public/assets自动复制) -
音乐元数据解析(
music-metadata读取标题/歌手/内嵌封面) -
预览流程重做(一键启动 WingsBlog 开发服务器,iPad/iPhone 设备预设)
-
i18n 误写保护:检测到会清空 20+ 个已有翻译时拒绝保存
-
缩放 Bug 修复(从 WebFrame zoom 改为 CSS transform 缩放)
-
UI 清理(隐藏默认菜单栏、侧边栏滚动条、页脚缩放控件)
-
Windows Release 打包(NSIS 安装程序 + 应用图标)
3.6 踩坑实录
坑 1:npm 权限地狱
Windows 下的 npm install 在 Electron 项目中频繁爆 EPERM: Access denied。经过排查,是之前的 npm 缓存和 node_modules 残留导致。清理后重新安装解决。
坑 2:structuredClone 无法克隆 Svelte Proxy
保存配置时报 Failed to execute 'structuredClone' on 'Window': #<Object> could not be cloned.。原因是 Svelte 5 的 $state 创建的 Proxy 对象无法被 structuredClone 处理。Codex 编写了专用的 cloneConfigValue() 方法来安全地深拷贝配置值。
坑 3:预览停止按钮无效
点击停止预览,页面还在显示。排查后发现是 PreviewService.stop() 用了 taskkill 但没等待进程真正退出就返回了状态。修复方案:taskkill /t /f 后轮询直到 127.0.0.1:4321 不再可达。
坑 4:i18n 配置被意外清空
切换到英文界面后,中文翻译文件 zh_CN.ts 的所有翻译被清成了空字符串。通过从 WingsBlog 的 origin/master 分支恢复了原始中文翻译,并添加了破坏性写入守卫——如果一次保存会清空 20+ 个已有翻译且超过当前非空翻译的 50%,则拒绝写入。
坑 5:Git CRLF/LF 行尾问题
Windows 环境下,Git 频繁警告 CRLF 将被替换为 LF。不影响功能,但每次提交都有噪音。后续配置了 .gitattributes 缓解。
四、Codex 协作模式复盘
4.1 子 Agent 体系
Codex 最让我惊讶的特性是它会自主派出子 Agent 做勘察和审查。在 WingsBlogManager 开发中,至少派出了 8 个子 Agent:
| 子 Agent | 角色 | 任务 |
|---|---|---|
| Lorentz | explorer | 初次勘察 Electron/Svelte 编译风险 |
| Pasteur | worker | 添加媒体管理模块 |
| Euler | explorer | 分析配置写回风险 |
| Gauss | explorer | 梳理配置编辑器与 diff 预览 |
| Fermat | explorer | 勘察动态菜单编辑器实现 |
| Laplace | explorer | 评估 Cloudflare Pages 部署可行性 |
| Lagrange | worker | 勘察 PIO 表单和多导出编辑器 |
| Hamilton | worker | 评估 P3 各项的实现影响面 |
这些子 Agent 都是只读的——它们勘察代码、分析风险、给出建议,但不直接修改文件。这让每次修改都有充分的事实基础,大大降低了”改错了再回滚”的概率。
4.2 文档驱动的上下文管理
在第一个会话中我要求 Codex 遵循的一条核心原则是:
“重要设计决策、当前进度、未解决问题和后续任务,需要沉淀到项目文档中。”
Codex 严格执行了这一点。项目最终有 6 个维护文档:
-
README.md— 项目介绍与快速开始 -
PROJECT_CONTEXT.md— 当前实现状态、风险与验证记录(最长,361 行) -
ARCHITECTURE.md— 运行时架构与模块边界 -
DECISIONS.md— 关键技术决策 -
TODO.md— 已完成与后续工作的完整追踪 -
CONFIG_CENTER_DESIGN.md— 配置中心交互与 Schema 设计
这些文档让第二个会话(跨天开启)无缝衔接——Codex 读完文档后就能准确理解当前状态,不需要我重新解释。
4.3 每个阶段的验证闭环
Codex 在每个阶段的结尾都执行了同样的验证命令:
npm run typecheck # TypeScript + Svelte 检查npm run build # Electron/Vite 生产构建npm test # Vitest 测试(最终 298 个用例)PROJECT_CONTEXT.md 中记录了 30+ 次验证通过记录,每一次都有具体的命令输出证明。
五、效率提升的真实感受
从”改配置”到”用工具”
以前改博客头像的流程:
- 打开
profileConfig.ts - 找到
avatar字段 - 把新图片放到
public目录 - 手动写路径字符串
- Git add → commit → push
- 等 Cloudflare 构建
现在的流程:
- 在 WingsBlogManager 中打开”个人资料”
- 点击头像旁边的媒体选择器,选择图片
- 点击”预览并保存”
从 6 步变成 2 步。 而且不用碰一行代码。
从”手写 frontmatter”到”WYSIWYG”
以前写一篇博客文章:
- 手动创建
.md文件 - 手写 YAML frontmatter(title、date、tags、category、description…)
- 用 VSCode 写 Markdown
现在:
- 点击”新建文章”
- 在表单中填写标题、标签(支持自动补全)
- 在 Milkdown 编辑器中所见即所得写作
- 点击保存 + Git 推送
最大的价值:降低了”维护门槛”
WingsBlogManager 最核心的价值不是技术上的,而是让一个非技术人员也能管理自己的博客。配置不再是代码文件里的神秘 JSON,而是直观的表单和开关。这正是 Codex 帮我完成的”最后一公里”——从能跑,到能用。
六、一些反思
Codex 擅长什么
-
✅ 理解设计文档并转化为实现:从 DESIGN.md 的 9 页文档到完整的 Electron 应用
-
✅ 自主勘察和风险评估:子 Agent 体系在开始编码前先做功课
-
✅ 状态管理的细粒度处理:分 section 的脏标记、i18n 破坏性写入守卫
-
✅ 技术选型和架构决策:ts-morph、Milkdown、safeStorage,每次选型都有理有据
-
✅ 持续的验证和文档同步:30+ 次验证记录 + 6 份维护文档
还需要注意什么
-
⚠️ Windows 特定问题:npm 权限、Electron 二进制下载、CRLF 行尾——这些都是 Codex 需要在真实 Windows 环境下一一解决的
-
⚠️ Svelte 5 runes 的边界情况:Proxy 对象的 structuredClone 问题说明新框架的坑需要实际踩
-
⚠️ 子进程管理:预览启动/停止、taskkill 等待——进程生命周期管理比想象的更复杂
-
⚠️ 长会话需要
/compact:第一个会话(3430 行 JSONL)接近上下文上限时,会主动提示或自动压缩
给我自己的建议
- 先写好 DESIGN.md:越详细的设计文档,Codex 的理解越准确
- 用否定句澄清偏好:“不需要 X”比”做 Y”更清晰
- 善用子 Agent:明确说”可以采用子 Agent 协作模式”,Codex 会并行勘察
- 要求文档同步:让 Codex 在每次行为变更后更新 PROJECT_CONTEXT.md,跨会话才不会丢失上下文
- 小步快跑:P0→P1→P2… 每个阶段独立验证,出问题也容易定位
七、结语
8 天,71 条消息,298 个测试用例,一个从零到交付的 Electron 桌面应用。
Codex 不是魔法——它不会自动知道你要什么,也不会一次就把复杂的状态管理做对。但它是一个极有耐心、从不偷懒、做事有理有据的协作者。它会在动手前派子 Agent 勘察代码,会在发现风险时主动报告,会在每个阶段结束时自动跑 typecheck + build + test 来验证。它不会跳过文档,不会忽略边界情况,不会为了图快而降低质量。
如果你在犹豫要不要让 AI 帮你做开发,我的建议是:先写一份好的设计文档,然后给它一个机会。
这篇文章就是用这个管理器发布的,还不错吧!当然目前还有许多需要修复的小bug,需要经过不断的迭代才能达到理想的效果.
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!










