先说这次最离谱的地方:这个项目里,我一行代码都没敲。
不是「AI 帮我写了大部分」,也不是我先搭好架子,再让它补几个函数。计划、架构、编码、测试、截图、文档、部署指南,全部由 gpt-5.6-sol/ultra 分阶段自主完成。
我干的事情只有一件:验收。
不好用就打回去,有 bug 就复现给它看,方案不顺眼就让它重新想。涉及提交、推送和部署这种有实际影响的动作,再由我授权。
第一阶段前前后后烧了十几亿 Token,五天做了 15 个提交。最后得到的不是一个只能演示的页面,而是现在每天稳定跑在我家 Rock 5B 16G 上的 Ask Codex。我可以在电脑或手机上通过 Cloudflare Tunnel 访问它,外面套着 Zero Trust 鉴权,里面继续保留 Codex 自己的沙箱和人工审批。
那时仓库已经有接近两万行 TS / TSX / MJS、300 多项测试,typecheck、lint、build 和桌面、手机界面检查也都跑过。人工手写代码仍然是 0 行。
Token 数不是软件质量指标,但至少能说明一件事:这不是「写个 Todo List 看看 AI 行不行」的一轮 Prompt,而是一次真的把模型往项目深水区里赶的实验。
后来我发现,这个实验其实还没有结束。
7 月 26 日写下这篇文章的时候,我以为真正有意思的是「AI 能不能独立把一个项目做出来」。又用了二十来天以后,问题已经变成了:
如果 AI 真能长期干活,那我应该给它什么样的工作环境?哪些经验应该留在项目里,哪些应该抽出来变成我自己的工具?
Ask Codex 后面的演化,以及后来单独整理出来的 my-skills,基本都是这个问题的答案。
0 我为什么需要一个 Codex 网页版
Codex CLI 很好用,问题是它长在那台机器上。
我经常在不同设备之间切换。有时主力电脑正在跑一个长任务,我人在另一台电脑上;有时只是想拿手机看一眼进度,批一个命令,或者继续补充两句话。为了这点事远程桌面回去,再钻进终端里,实在有点重。
我想要的东西其实很窄:
- 在浏览器里继续 Codex 原生线程,不要另造一套聊天记录。
- 能完整看到消息、推理、计划、命令、diff 和审批,不是只能收发纯文本。
- 桌面和手机都能用。
- Codex 凭据、工作区和进程都留在我自己的机器上。
- 可以远程访问,但不能顺手造出一个裸奔在公网的远程 shell。
所以 Ask Codex 不是通用 Web IDE,也不是给多人用的 SaaS。它就是一个单用户、本地优先、只服务于 Codex 的浏览器客户端。
架构也很直:
电脑 / 手机浏览器 -> Cloudflare Access + MFA -> Cloudflare Tunnel -> Ask Codex HTTP / WebSocket 网关(127.0.0.1) -> codex app-server(JSONL over stdio) -> 本地 Codex 线程、凭据和工作区底层没有去扒 Codex Desktop 的私有 IPC,也没有把终端输出当协议解析。Ask Codex 启动官方的 codex app-server --listen stdio://,通过一行一条的 JSONL 消息跟它通信。
这个选择很重要:线程仍然是 Codex 的原生线程。 CLI、编辑器和浏览器看到的是同一份会话,不需要再维护一套自己的数据库,也不用做两边历史同步。
1 真正的核心不是网页,是中间那道窄门
把 app-server 接到 WebSocket 上并不难。难的是,浏览器一旦能随便调用它,就相当于拿到了宿主机上 Codex 的控制权。
这个网页背后不是天气接口。它能读代码、改文件、运行命令,还能请求更大的权限。Cloudflare Tunnel 只是把路接通,不会自动把风险变没。
所以 Ask Codex 的网关不是透明转发,而是一道很窄的策略边界。
浏览器能调用什么、传什么参数、拿到哪些字段,都由网关重新构造,而不是把 app-server 原封不动暴露出去:未知方法拒绝,未知字段拒绝,值不合法也拒绝。
几个例子:
- 配置接口只把前端真正需要的模型、推理强度等信息投影出去。
- 创建、恢复、fork 和执行轮次时,审批与 sandbox 策略由服务端决定,浏览器只表达非常有限的意图。
- 暂不支持或无法安全校验的细粒度能力默认失败关闭。
ASK_CODEX_TOKEN不进 URL,也不会传给 Codex 子进程、MCP Server、hook 或命令。- 文件下载不是一个“给我路径我就读”的 HTTP 接口,而是只能针对当前线程工作目录里、Agent 已经明确输出过的文件,由服务端签发短期一次性 capability。
远程访问则一直坚持多层门禁:
| 位置 | 管什么 |
|---|---|
| Cloudflare Access + MFA | 先确认访问者是不是我 |
| Ask Codex token | 再确认客户端拿到了独立的应用凭据 |
| Codex sandbox / approval | 最后决定这一轮到底能干什么 |
Ask Codex 本身仍然默认只监听 127.0.0.1,家里路由器不开端口,也不需要把服务直接裸绑到公网。
Tunnel 负责把路接通,Access 负责认人,应用 token 负责守门,Codex 自己的 sandbox 和审批负责最后的执行边界。它们解决的是不同的问题,不能互相冒充。
2 它后来已经不只是一个能聊天的皮肤
7 月底刚写这篇文章的时候,Ask Codex 已经能搜索、恢复和管理原生线程,流式显示消息、推理、计划、命令、diff 和 MCP 调用,在网页里做审批和结构化提问,选择 cwd、模型与推理强度。
但真正连续用了几周以后,我发现「能聊天」其实只是最低要求。
我日常需要的是另一套东西:
我离开这台机器以后,还能不能知道项目现在在干什么;网络断了以后,界面能不能恢复;一个任务正在跑的时候,我能不能继续给它补信息;手机上能不能真正把它当工作界面,而不是偶尔看一眼。
于是后面陆续长出了很多一开始根本没规划的东西。
线程列表从单纯的会话列表变成了按工作目录分组的项目导航,有 Active、Archived,也有单独的 Activity 视图,用来集中看正在执行、等待审批、等待输入和最近完成的任务。
还有一个我很喜欢的 Skills 页面。它直接读取 Codex 官方 skills/list 的结果,按工作目录展示当前有哪些 Skill、是否启用。也就是说,后面我整理出来的 my-skills,已经可以直接在 Ask Codex 里看到。
长线程则继续做有界历史恢复;进行中的计划会固定显示在输入区附近;命令、文件修改、MCP、搜索、subagent 等机器活动被压成相对紧凑的活动流,而不是把真正的对话淹掉。
后来还增加了:
- 正在运行的 turn 可以继续 steer,不用非得等它说完再补充信息。
- 可以在受限条件下 fork 已有线程。
- 支持图片和文件输入。
- Agent 输出的工作目录内文件可以经一次性授权直接下载。
- 有单独的 Usage 面板看当前线程 token、上下文占用、账户活动和 rate limit。
- app-server 或 WebSocket 出问题以后会做只读重同步,不会为了“恢复”擅自重放不确定的写请求。
- 可以把纯文本消息放进服务端持久队列,在另一台设备上再明确发送或取消。
- 每个 turn 可以单独选择 manual / auto,而不是永久修改整个线程的安全属性。
最后这一点尤其重要。
现在的默认 manual 模式,尽量贴近 Codex 正常的 on-request + workspaceWrite 行为;如果我明确知道这一轮要让它放开手脚,可以只给这一轮打开 auto,让这一轮拿到更宽的文件系统和网络环境。
轮次结束,恢复默认。
这比一个永远开着的“YOLO 模式”靠谱得多,因为我要的不是取消安全边界,而是让安全边界跟这一次任务绑定。
3 一个特别能说明问题的 bug
项目第一次真正让我觉得这套东西经住了检验,是在 Redmi 的 Chrome 上发图片。
当时粘贴和预览都正常,一按发送就一直转圈,最后报:
paginated_threads is not supported yet很容易顺着表象去查图片上传,毕竟问题就是在「发图片」时出现的。但模型把整条链路从浏览器、临时附件、网关 RPC 一直追到了原生 app-server,最后发现:图片已经上传成功,真正失败的是新线程的第一轮。
Codex CLI 当时生成的实验性 bindings 里暴露了 historyMode: "paginated",于是之前的实现给新线程强制加了这个字段。Schema 看起来支持,真实运行时却直接说不支持。
更阴的是,只测 thread/start 还不一定能抓到,必须真的验证第一轮。
最后的修复不是看到错误就重试。thread/start 不是可以随便重放的幂等请求,乱重试可能凭空多出线程和轮次。正确做法是:
- 新线程不再强制实验性的 history mode,让 app-server 自己选择默认契约。
- 已经存在的分页线程仍然可以按原来的规则只读恢复。
- 给这条回归补测试和真实协议烟测。
- 新建 ADR 0010,正式取代之前主张强制分页的 ADR 0008。
也就是说,AI 不但改了自己写的代码,还推翻了自己之前做过的架构决定,并把为什么推翻写进了项目历史。
后面它又处理了移动 Chrome 不规范 MIME、JPEG 文件头里的填充字节,以及非完整历史快照把已经流式显示的内容覆盖掉等问题。每次都不是补一个 if 就走,而是一路补到客户端、服务端、回归测试、视觉夹具和文档。
CAUTIONSchema 里有,不等于运行时真的能用。
生成的类型只能证明「协议长这样」,真实首轮才能证明「这条路径跑得通」。AI 在这里没有迷信它刚生成的 bindings,这一点比修掉 bug 本身更重要。
前面 ADR 0008 被 ADR 0010 取代,也不是修完代码顺手补一份文档。它之所以能把旧决定、实测结果和新方案完整留下来,正是因为 AI 开工前先给自己定了一套接力规则。
4 AI 先给自己写了一套 Skill
写到这里,Ask Codex 还只是一个 AI 写出来的软件项目。真正让我觉得有意思的是,它连自己的协作方式也是自己写的。
项目开始前,我先让 gpt-5.6-sol 写了一个个人 Skill,叫 project-continuity。要解决的问题很朴素:我会在不同设备、不同 Codex 会话之间接力开发,下一次进来的 AI 不能靠猜,也不能指望上一段聊天记录永远在。
它给出的办法不是往 AGENTS.md 里塞一部长篇 Prompt,而是把不同寿命的信息分开:
AGENTS.md -> docs/context.md -> docs/progress.md -> docs/decisions/ -> docs/ideas.mdAGENTS.md 只留必须遵守的规则和导航;context.md 放稳定的目标和约束;progress.md 是可替换的当前状态快照,不是越写越长的开发日记;长期决定一项一个 ADR;还没决定的东西丢进 ideas.md,不许因为写进去了就假装已经排进路线图。
它还规定了事实来源的优先级:协议看当前 CLI 生成的 schema,安全规则看仓库指令,已经实现了什么看代码、测试和配置;README 和进度文档如果对不上,先验证,再修文档。
这套东西最对我胃口的一点是:
它不把 AI 的记忆当项目资产。
真正能跨设备的不是聊天记录,而是 Git 里的代码、测试、上下文和决策。未提交的东西仍然只在当前机器上;AI 也不能因为「我要接力」就自己 commit / push,必须等我明确授权。
5 然后,这个 Skill 真被拿去用了
写一份 Skill 不难,难的是换了设备、换了会话以后还真一直照着它做。
project-continuity 这次没停在展示里。Ask Codex 从 7 月 23 日开始正式按它接力:新会话先读规则、上下文和当前进度,再查 Git 和真实代码;一个阶段做完,才跑 typecheck、lint、测试、构建和视觉检查;只有实现状态或长期决定真的变了,才改 progress 或新增 ADR。我验收并授权后,代码和文档一起推上去,下一台设备 pull 下来接着干。
Ask Codex 后面的二十多份 ADR,其实都是这套工作方式自然长出来的。
有些决定一直保留,例如使用官方 app-server、浏览器和 Codex 之间必须有网关策略边界、Cloudflare Access 和应用 token 相互独立。
也有些决定连续被现实推翻。
比如执行模式前后改过好几版;比如移动端一度试图正规做成 PWA,真正拿受 Cloudflare Access 保护的 Android Chrome 测以后,反而变成灰色账号头像、地址栏又回来了。
最后项目干脆把 Manifest 和 PWA 安装相关内容撤掉。
因为我的真实目标根本不是拿到一个“PWA”认证,而是:
手机从桌面点进去以后,别给我浪费那一大截地址栏。
后来又直接给移动端加了 Fullscreen API 按钮。
这件事很能体现 ADR 和连续上下文的价值:不是为了证明第一次设计多正确,而是让以后的人和 AI 知道「这个看起来反常的设计为什么不能随便改回去」。
如果没有这些记录,下一次 AI 看见“怎么连 Manifest 都没有”,十有八九又会热心地帮我补一个。
6 一个 Skill 最后变成了一个 Skills 仓库
project-continuity 真正在 Ask Codex 里用顺手以后,我开始发现一个问题:
很多我反复交代 Codex 的事情,其实根本不应该每次重新写 Prompt。
它们不是某个项目的需求,而是我的工作方式。
于是后来单独建了一个仓库:
现在里面有四个 Skill。
| Skill | 干什么 |
|---|---|
project-continuity | 管跨设备、跨 session 的项目上下文、progress、ADR 和 ideas |
cc-switch-usage | 从本机 cc-switch 数据库统计 Codex Token 和估算费用 |
academic-humanizer-zh | 在不改事实、引用、术语和论断边界的前提下润色中文学术/技术文本 |
academic-md-to-docx | 把带公式、表格、引用的 Markdown 转成 Word,并检查 OOXML 结构 |
这几个东西表面上完全不像一类需求。
一个管开发项目,一个算 Token,一个改论文,一个导 Word。
但从我的角度看,它们是一类东西:
“这件事我已经知道应该怎么做了,以后不想再跟 AI 从头解释。”
比如 cc-switch-usage。
我之前经常看 cc-switch 里的输入、缓存、输出和实际消耗 Token,一看到几亿、十几亿就要重新解释什么叫 cache hit,费用怎么算,哪些记录能不能归属到 provider。
最后干脆把规则做进 Skill:只读本地 SQLite,知道 cached input 已经包含在 input 里,不能重复加;知道本地价格只是估算,不许冒充供应商账单;也知道数据库里哪些字段可能带 API key 或 endpoint,不能顺手打印出来。
再比如写论文。
“帮我降低 AI 味”这句话其实非常危险,因为模型为了让句子不像 AI,最容易做的事情就是把内容一起改掉。
所以 academic-humanizer-zh 的核心不是“人类化”,而是先保护 claim、数字、引用、术语和适用范围。宁可语言没那么漂亮,也不能为了改风格偷偷改事实。
academic-md-to-docx 也是一样。
它不是简单 pandoc xxx.md -o xxx.docx。公式直接转 Word 可编辑的 OMML,导完以后还要比较 Markdown AST 和 OOXML 里的公式、表格、图片、脚注、标题数量。
结构对得上以后,才值得进 Word 看分页、字体和视觉效果。
这些 Skill 越写越让我觉得:
Prompt 是一次性指令,Skill 更像是我给 Agent 安装的软件。
Prompt 解决“这次帮我干什么”。
Skill 解决“以后遇到这种事情,你应该按什么方法干”。
7 Ask Codex 和 Skills 最后接到了一起
这也是最近我觉得整个东西突然形成闭环的地方。
一开始是:
我 -> Codex CLI -> 某一个项目后来为了跨设备,变成:
我 -> Ask Codex -> Codex app-server -> 某一个项目再后来有了 project continuity:
我 -> Ask Codex -> Codex -> project-continuity -> 仓库里的 context / progress / ADR现在则更像:
-> project-continuity -> cc-switch-usage我 -> Ask Codex -> Codex -> academic-humanizer-zh -> academic-md-to-docx -> 项目自己的 AGENTS.md / SkillsAsk Codex 负责我怎么随时找到 Agent。
项目里的上下文文件负责Agent 怎么找到这个项目的真实状态。
Skills 负责Agent 怎么复用我已经固定下来的工作方法。
Git 则负责把这些东西跨设备同步。
这几个东西原本都不是我一开始设计好的“大系统”。
完全是使用过程中一个问题一个问题长出来的。
先是「我出门以后怎么看 Codex」。
然后是「换台电脑以后下一段 session 怎么知道上一段干了什么」。
然后是「这种规则我每个项目都要用,为什么还要复制粘贴」。
然后变成「这个需求我已经解释三次了,为什么不直接做成 Skill」。
最后 Ask Codex 甚至自己加了一个 Skills 页面,让我在手机上就能看到当前工作目录里 Codex 到底发现了哪些 Skill。
到这里,它已经不太像单独一个 Web UI 项目了。
它更像是我现在这套 Agent 工作方式的一个入口。
8 手机最后也真的变成工作终端了
我一开始做移动端,想法其实很保守:
能在手机上看进度、批审批,就够了。
结果真正开始用以后,我发现手机完全可以承担比这更多的东西。
Codex 正在干活的时候,我突然想到一个边界条件,可以直接 steer 进去;一个任务结束了,在地铁上可以看 diff、看测试结果,然后继续发下一轮。
如果主力电脑没在身边,也可以先把想说的话扔进消息队列,之后在另一台设备上确认线程状态再发。
所以后来我对移动端最敏感的反而不是“像不像 App”,而是屏幕到底有多少能拿来显示真正的工作内容。
这也是为什么前面 PWA 实验失败以后,我最后接受了一个非常不“标准答案”的方案:
不追求 WebAPK,不追求离线,不追求浏览器告诉我“恭喜,这是一款合格 PWA”。
只要 Android Chrome 从桌面打开以后没有地址栏,能把更多高度留给对话,就是成功。
然后再补一个 Fullscreen 按钮。
这就够了。
CAUTION产品需求不是技术名词。
我要的是“手机屏幕尽量都拿来干活”,不是“实现 PWA”。
如果 PWA 反而让地址栏回来,那它就是错的方案。
这种非常具体、甚至有点琐碎的东西,其实才是我后来持续用 Ask Codex 的原因。
Demo 不会在意一个地址栏。
每天用才会。
9 从多轮协作到甩手掌柜
我得先纠正一条很容易写错的「进化路线」:我不是从 Copilot 补全几行代码,突然跳到了 Codex 长任务。
在这之前,我已经在用 Claude Code + Opus 做多轮协作开发了。描述问题,让它调查和给方案;我追问几轮,再让它实现;看完结果继续指出问题,进入下一轮。强模型已经能跨文件写功能、跑测试、查 bug,远远不是代码补全。
但那时工作的最小单位仍然是一轮轮对话。
AI 很强,我也不用亲自敲多少代码,但我需要一直待在会话里提问、确认、推进,把项目从这一轮送到下一轮。
gpt-5.6-sol/ultra 带来的变化不是「一次能多写几个文件」,而是:
工作的最小单位从一轮对话变成了一个完整阶段。
Ask Codex 第一阶段里,我给出目标和少数硬约束,然后就可以把整个阶段扔给它:协议调查、方案选择、编码、测试、视觉检查、文档、ADR 和跨设备交接,它自己一路做完。
出 bug 也不用我帮它缩小到某个函数;它会沿真实协议路径追下去,发现运行结果推翻了原来的设计,就连设计一起改掉。
后面二十多天,我甚至开始把「怎么干活」本身也逐渐交给 Skill。
这已经不是单纯的代码生成。
更像是在逐渐建立一个真正可以工作的 Agent 环境。
10 关于“初级程序员被消灭”这件事,我还是原来的判断
实事求是地说,我在这个项目里并没有那么重要。
我提出了需求,实际用过界面,报告了遇到的问题,也掌握 commit / push 的最终授权。
但协议边界、功能实现、回归修复、测试和整套文档的质量,主要来自模型本身足够强,而不是因为我在旁边发挥了什么不可替代的工程作用。
换一个人,只要能说清同样的需求并做基本验收,这个项目大概率仍然能做出来。
换掉这一级别的模型,结果反而未必还能成立。
这次真正稀缺的生产力是模型,不是我。
所以我当时写下的判断,到现在没有收回:
CAUTION不管人类愿不愿意承认,初级程序员已经从事实上被消灭了。
这里说的不是明天所有挂着 Junior 头衔的人都会从公司花名册里消失。组织惯性、招聘制度和责任归属当然还会继续存在。
消失的是它作为一种技术生产角色的必要性:
拿到相对明确的需求,搭常规结构,写实现,补测试,修普通 bug,再把文档补齐。
这些工作过去需要一个初级程序员花几天甚至几周完成,现在强模型不但能更快做完,还能同时维护跨文件约束、跑完整验证、记录架构决定,并在换设备和换上下文以后继续。
模型当然会犯错。
Ask Codex 自己写出来的 bug,我这一个月已经遇到一堆。
但「会犯错」从来不是人类的护城河。
真正有意义的区别是:它能不能自己定位、承认、修正,并留下回归测试和新的决策记录。
从 Ask Codex 到后面的 Skills,我看到的答案越来越明确。
11 真正变化的不是代码生成能力
现在 Ask Codex 还是跑在那块几年前买来的 Rock 5B 上。
浏览器打开域名,先过 Cloudflare Access,再过 Ask Codex token;连上以后,看到的是这台机器上原生的 Codex 线程。
我可以在书房电脑上开工,出门拿手机看进度,换另一台机器继续。
项目状态不需要靠我把上一段聊天复制过去。
开发上下文在 Git 里。
长期决定在 ADR 里。
当前状态在 progress 里。
重复的工作方法在 Skills 里。
而 Ask Codex 只是让我随时都能碰到那个真正干活的 Agent。
这几样东西放在一起以后,我对 AI 编程最大的感受已经不是:
它越来越会写代码了。
而是:
它越来越像一个可以被组织、被配置、被交接、被安装工作方法的劳动者。
代码只是产物之一。
真正开始发生变化的是工作流。
以前我想的是怎么给模型写一个更好的 Prompt。
现在我更常想的是:
- 哪些东西应该留进仓库,成为项目事实?
- 哪些东西应该写成 ADR,避免以后重新争论?
- 哪些东西只是当前状态,应该覆盖而不是无限追加?
- 哪些工作方法已经重复两三次,值得直接做成 Skill?
- 哪些权限应该属于整个线程,哪些应该只给这一轮?
- 哪些能力应该让浏览器看到,哪些永远应该留在网关里面?
这大概也是这次实验最后真正留下来的东西。
不是十几亿 Token。
不是零行手写代码。
甚至也不只是 Ask Codex 这个项目。
而是我第一次很明确地感觉到:
以后维护的可能不只是代码仓库,还会有一套属于自己的 Agent 工作环境。
代码、上下文、决策、Skills、权限和入口,都只是这个环境的一部分。
Ask Codex 是其中第一个真正每天在用的工具。
my-skills 是第二个。
而且看起来还会继续长下去。