给 Hexo 博客加一个 Codex 可用的后台预览流程
这篇文章记录一次很小但挺实用的工作流改造:让 Codex 在修改 Hexo 博客之后,可以自己启动本地预览,拿到 http://localhost:4000/,继续做页面验证,而不是卡死在前台 hexo server 里。
问题本身不复杂。很多开发命令本来就是给人坐在终端前用的。人启动它,看完页面,按 Ctrl+C 退出。可 Agent 不一样,它需要在命令结束之后继续工作。如果命令永远不返回,后面的构建检查、页面截图、结果汇报就都没了。
一开始的问题
Hexo 的本地预览一般是:
1 | hexo server |
或者项目里封装过的:
1 | npm run server |
它们的行为都很正常:启动一个本地服务,然后一直挂在前台,等用户手动停止。
这对人来说没问题。对 Codex 来说就很尴尬。执行器会一直等命令结束,可 hexo server 正常情况下不会自己结束。于是一个本来只是想看页面的步骤,会直接把整个任务流程堵住。
之前的规则只能退一步:Codex 修改完站点后运行 npm run clean 和 npm run build,本地预览交给我手动开。能用,但不顺。每次改完都要人接一棒,Agent 的连续工作能力被打断了。
第一版尝试
最直接的想法是用 PowerShell 的 Start-Process 把 Hexo 放到后台,然后当前脚本轮询 http://localhost:4000/,确认页面可访问后就退出。
听起来很合理。实际跑起来之后,还是卡过一次。
后来回头看,问题大概率不在 Hexo,而在进程和执行器之间的牵连。后台 Node 进程虽然已经启动,但当前命令这层仍可能因为控制台句柄、输出重定向或子进程关系没有干净返回。对人来说这类差别不明显,对自动化来说就很要命。
这次失败倒是把方向暴露出来了:不能只是把 hexo server 从前台挪到后台,还要让它和当前执行器彻底隔离。
最后的方案
最后用的是一个两层结构。
第一层是启动器:tools/start-hexo-preview.ps1。它检查端口,清理旧预览,启动宿主,轮询端点,最后输出 JSON。
第二层是宿主:tools/hexo-preview-host.ps1。它在隐藏的 PowerShell 进程里真正运行:
1 | hexo server -p 4000 |
这样当前执行器不直接托管 Hexo。它只负责把宿主拉起来,等 http://localhost:4000/ 返回 200,然后拿着结果继续工作。
对应的 npm scripts 是:
1 | npm run preview:start |
preview:start 成功后会输出类似这样的信息:
1 | { |
Codex 可以直接使用里面的 url 做 HTTP 检查、浏览器验证、DOM 检查或者截图。最后回复时也可以把它作为 Web preview 交给我。
进程怎么收尾
这个地方不能靠感觉。我一开始以为停掉监听端口的 Node 进程就够了,后来一想,不够。
如果 preview:start 连续调用两次,第一次创建的宿主进程不能随缘退出。否则久了之后可能留下看不见的 PowerShell 进程,虽然资源不大,但这就是工作流里的灰尘。
所以现在的逻辑是:
- 检查
4000端口。 - 如果监听者是可识别的 Hexo/Node 进程,先停止它。
- 读取上一次写下的
state文件。 - 如果旧宿主 PID 还活着,显式停止它。
- 删除旧
state文件。 - 再启动新的宿主,写入新的
state文件。
第二次 preview:start 会先完整回收第一次的预览,再开新的服务。后来实际测试时,第二次启动确实打印了旧 Node 进程和旧宿主 PowerShell 的 PID,并把它们都停掉了。
preview:stop 做的是同一类清理,只不过它不会再启动新的服务。它会确认端口上的进程确实是 Hexo,再停止监听进程和对应宿主。端口上如果是别的东西,它不会硬杀。
这里宁可啰嗦一点。自动化脚本不应该为了方便,把用户机器上任何占用 4000 的进程都当成自己可以处理的东西。
规则也要跟上
脚本跑通之后,还改了 AGENTS.md。
现在规则变成了:任何会影响站点内容、主题配置、主题样式、依赖或构建产物的有效修改后,都要按顺序运行:
1 | npm run clean |
preview:start 成功后,Codex 必须用输出的 URL 做必要验证,并在最终回复里给出:
1 | Web preview: http://localhost:4000/ |
默认不在最终回复前 preview:stop,因为我需要能打开这个页面看结果。
还有一个保险:如果我让 Codex 提交或推送,一般就表示这轮功能已经确认完成了。这个时候 Codex 要先运行 npm run preview:stop,再执行 git commit 或 git push。预览阶段结束了,就把后台服务收掉。
写完之后的感觉
这件事本身只是几个 PowerShell 脚本。但它解决的是 Agent 工作流里很常见的一类问题:很多传统开发命令默认是交互式、前台、长驻的,而 Agent 需要命令返回结果,留下日志,还能被清理。
人用工具时,可以凭经验盯着终端看。Agent 用工具时,最好让每一步都有清楚的输入和输出。启动后返回什么?日志在哪里?端口被占了怎么办?下一次启动会不会泄露进程?什么时候该保留预览,什么时候该关闭?
这些问题不大,但都要回答。
我越来越觉得,给 Agent 改造项目工具链时,最重要的不是把命令包装得多花哨,而是把生命周期讲清楚:什么时候开始,什么时候可用,什么时候结束,失败时留什么证据。
这次的 preview:start / preview:stop 就是这么一个小闭环。它没有改变 Hexo,也没有改变博客的部署方式,只是把原来只适合人手动操作的本地预览,变成了 Codex 可以接管的一步。
写博客时少按几次命令,听起来不是什么大事。
但如果每次修改、验证、截图、汇报都能少一次人工接力,Agent 就更像一个真正能连续工作的工程助手,而不是跑到一半就把终端递回来的人。






