Simon Willison 用语音指挥 Codex 为博客构建 Newsletters 页面
A new feature for my blog, built using my voice
Simon Willison 用 ChatGPT 桌面端 Codex 语音模式,在做晚饭的半小时里几乎全靠语音为自己的博客(Django)开发上线了 Newsletters 页面,所用模型为 GPT-6 Astra High。
2026年10月9日
我今天为我的博客发布了一个新功能:Newsletters(通讯)页面,它提供了我发送过的所有通讯的索引,包括我免费的每周 Substack 和仅限赞助者的月度更新。这个功能几乎完全是用语音构建的——我做晚饭时一边对着笔记本电脑聊天一边完成的。
Codex 语音模式
我使用的是 ChatGPT 桌面应用的 Codex 标签页,使用语音对话模式,针对本地开发环境运行。它的样子是这样的:

我是通过输入以下命令,针对我本地的 simonwillisonblog 代码检出启动会话的:
Start dev server and open in browser
这给了我一个它将要处理的网站预览,也意味着我之后可以让它展示新页面,从而直观地跟踪它的进度。
然后我点击了“Start new voice chat”(开始新的语音聊天)按钮——那不是麦克风按钮,是它右边那个——并把笔记本电脑摆在厨房里,这样我就可以一边做饭一边跟它说话了。
与我的电脑对话
我很清楚自己想要构建什么,而且这是一个足够简单的 Django 功能,我确信模型(本例中是 GPT-6 Astra High)能够完成它。一个新模型、一次迁移、一些视图代码、模板,以及几个从外部来源填充数据库的导入函数。
下面是 Codex 捕捉到的我的语音转录片段:
嗯,它们没有。嗯,这将是一种新的内容类型。嗯,它不会显示……哦,等等。对,不——我不希望它显示在我的,嗯,标签页面和日期归档页面以及……其实,不,我觉得……我不希望它出现在标签页面上。我不希望它出现在,嗯,博客索引页面上。但我想我确实希望它显示在基于日期的页面上。你知道,如果你导航到9月19日,而我在那天发过一份通讯,我想我希望它显示出来。所以……这个——所以我想我们可能需要一个新模型。另一件事是我希望它们可搜索,呃,Substack 那些不可搜索,因为它们实际上只是我博客上其他内容的副本。这些月度的确实包含独特内容,而 spe- 一旦它们……发布,比如在发出一个月后公开时,我希望它们出现在我的搜索结果中。
显然这些话已经足够清晰,让模型知道我想构建什么了!你可以在这个 Gist 中阅读完整的转录内容,包括所有的不流畅之处。
我们就这样持续了大约半个小时(也就是做晚饭所需的时间)。模型会回复并不时提出澄清问题,然后着手修改代码。
我们构建了什么
我们完全通过语音就取得了惊人长的进展:
- 一个新模型和迁移,用于在 Django 中表示导入的通讯,外加相应的 Django Admin 配置
- Four working imports:
- 通过 RSS 获取最近的 Substack 条目
- 通过 Substack 未公开文档的 API 获取所有其他 Substack 条目,这个 API 是 GPT-6 Astra 本来就知道或者通过搜索找到的
- 从我的 simonw/monthly-newsletter-archive GitHub 仓库获取所有已发布的月度通讯
- 从一个私有仓库获取我最近的仅限赞助者的私有通讯
- /newsletters/ 和 /newsletters/2026/ 公共归档页面
- 通讯也会显示在按日和按月的归档页面上,但不会出现在标签页面或我的首页上
- 每周 Substack 通讯链接到 Substack;已归档的月度通讯则有自己的页面
- 与我的站内搜索引擎集成
它几乎已经可以上线了。问题出在数据导入上:Astra 提出可以从我的本地副本导出数据,以便我导入到生产环境,但我希望它能像我其他的导入脚本一样工作。由于部分数据存放在一个私有的 GitHub 仓库中,这需要创建一个新的 API key,而我知道这得在键盘前坐上一阵子。
通过代码评审收尾
当我完成“烹饪”、判断它基本功能完整之后,我让 Codex 创建了一个分支并提交了一个 pull request。
我在 GitHub PR 界面中评审了代码。它几乎就是我需要的,只是它选择在其中一个导入脚本中通过子进程调用 Git。我需要其中一个导入功能从私有 Git 仓库拉取数据,所以我觉得用 API 会更稳妥。于是我切换回打字模式,让 Codex 将其替换为基于 API 的导入方式。
你可以在PR 上的额外提交中看到我在审查期间所做的修改。我修复了导入机制,并对这些公开页面的显示做了一些微调。之后我又花了额外半小时的打字式提示,才达到满意的程度,最终合并 PR 将其部署到生产环境。
最终成果
你可以在新的新闻通讯索引页面查看最终成果,或者浏览往期月度新闻通讯页面。

索引页面将我最近的 Substack 每周新闻通讯和 GitHub sponsors 月度新闻通讯按时间倒序混合显示。页面下方还有指向我按年份归档页面的链接。
GPT-6 Astra 设计了这个页面,然后根据我在厨房里瞥了一眼本地预览后口头给出的反馈对设计进行了调整。
更适合多任务处理,而非日常主力
OpenAI 非常喜欢在 DevDay 等场合使用这类语音驱动的演示——在那种环境下它们确实表现出色。不过我不认为这会成为我的日常主力工具。
我之前曾写过遛狗时用手机上的 ChatGPT 语音模式完成了多少“工作”——主要是研究和头脑风暴,偶尔也让 ChatGPT 编写并测试一些代码片段,完成实际的开发工作。
这次的感觉不同。视觉预览的加入,加上在无法用语音表达时可以通过键盘输入或粘贴内容,使这成为一种强大得多的与编码智能体交互的方式。
不过,一旦深入到细节,我仍然会切回打字模式。能够粘贴示例和错误信息,或者直接高亮需要修改的代码或功能,依然比用语言描述更高效。
我主要在家办公,这很好,因为我可不想在共享办公空间里这样对着电脑说话!
对我来说,杀手级功能是能够同时处理多项任务。我做饭时通常会开着播客或 TikTok;现在我可以真正地构建东西了。
来源:Simon Willison · simonwillison.net