尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

持久化Web AI编码工作区:让Claude Code/Codex会话不再断档

发布时间:2026/9/28 18:36:09

资讯中心
01
ARTICLE

持久化Web AI编码工作区:让Claude Code/Codex会话不再断档

持久化Web AI编码工作区:让Claude Code/Codex会话不再断档
如果你最近开始认真玩 vibecoding大概率是这么个状态电脑上装好 Claude Code 或 Codex开个终端把需求往对话框里一贴然后看着 AI 自己读代码、改文件、跑测试。爽是真的爽但用上几天你就会发现终端里的会话寿命短得可怕——手一抖按到 CtrlC项目刚到一半的思路就没了离开工位换台机器刚才那轮对话的进度根本带不走半夜跑一个依赖升级还得惦记着电脑别休眠。这个项目就是冲着这个问题来的。Easy Web Vibecoding 是一个专为 Claude Code / Codex 打造的持久化 Web AI 编码工作区CLI 引擎照常跑在你自己的机器上但会话的启动、续接、上下文和历史记录全部通过浏览器来管理。说白了就是把“临时起意的终端对话”变成“能存、能查、能接着干的长期项目资产”。如果你在搭 AI 编码工具链或者已经被终端断档折磨得够呛这篇文章会把从零搭建这套工作区的架构思路、关键代码、踩坑记录和使用习惯一次讲清楚。1. 为什么 vibecoding 需要一套“打不死的”工作区1.1 vibecoding 的本质不是让 AI 写代码而是让对话变成开发主线vibecoding 这个词听起来像玩笑但它的工作方式和传统写代码完全不同。传统方式是“我脑子里有方案我负责实现”vibecoding 是“我描述要的效果和边界AI 负责实现我负责判断方向和把关质量”。Claude Code 和 Codex 这类 agent 型 CLI 之所以能撑起这种玩法是因为它们不是简单的补全工具而是有完整工具循环的智能体读文件、改文件、跑命令、看报错、再改一整圈下来几乎不需要人打断。这也带来一个很实际的问题一次正经的 vibecoding 任务往往包含几十上百轮交互。这些交互本身就是项目最重要的资产——里面记录了需求的演变、AI 为什么这么做、你中途否掉了哪些方案。传统终端把这一切当成一次性聊天关掉窗口就什么都没有了。我的想法很简单能不能让这些对话像代码一样被保存、被检索、被跨设备复用答案就是给 CLI 外面套一层持久化的 Web 工作区。1.2 终端会话的三个死穴我当初决定动手写这个项目是因为被终端会话的常规用法坑了几次总结下来就三个问题窗口关闭等于进程死亡。agent 型 CLI 跑一个复杂重构任务时经常是“读代码五分钟、改代码两分钟”你看着像卡住了就手痒去按 CtrlC或者你只是换个目录、清理终端窗口后台任务直接没了。更尴尬的是半夜挂着跑一个长测试电脑自动休眠第二天醒来发现进度全丢。上下文断档。终端本身不保存任何东西。换台电脑、重启一下 CLIAI 就完全不记得上一次聊到哪了。你只能靠 CtrlUp 翻历史命令或者把上次的结论复制到剪贴板里手动带过去这跟在记事本里管代码没什么区别。长任务没有托管机制。跑构建、跑集成测试、批量迁移代码这类任务动辄十几分钟普通终端没法“挂在那里等你回来”。它既不能让你关掉浏览器出门也没法在任务结束后给你一个可靠的通知和记录。这三个问题叠加起来vibecoding 的体验就变成爽十分钟难受一整天。Easy Web Vibecoding 的定位就是把这三根刺拔掉。1.3 为什么选择 Claude Code 和 Codex 当引擎市面上能跑的 agent CLI 不少我最终锁定这两个一是因为它们各自代表了不同的编码风格二是它们都留了比较友好的可编程调用接口。维度Claude CodeCodex擅长场景跨文件深度重构、复杂逻辑推理、老代码梳理快速生成脚手架、批量替换、按明确规范执行对话接入支持 stream-json 输出流支持 exec 模式、JSON 事件输出会话续接支持 resume / 指定 session 续聊支持继续上一次会话项目记忆CLAUDE.md 自动加载AGENTS.md 自动加载两者互补性很强我处理遗留系统时更喜欢用 Claude Code 多问几个“为什么”而新建模块或做格式统一时 Codex 的响应速度更利落。工作区里我按项目维度配置 agent 类型同一个 Web 面板下想换引擎就换不需要重新搭环境。需要提醒的是CLI 的具体命令参数随版本迭代变化很快下面的命令我都以当前主流版本为准跑不通时先看一眼--help再继续。2. 架构设计浏览器只是壳真正持久化的是会话本身2.1 三个核心层引擎层、会话层、展示层动手之前我先把架构拆成了三层这样每个层的职责都很干净调试起来也容易定位问题。引擎层是最底层负责真正拉起 Claude Code 或 Codex 子进程并且一定要用伪终端PTY来接不能用普通管道。原因很直接这类 CLI 在交互模式下会渲染各种状态、清屏、控制动画普通管道拿不到这些控制字符而且很多命令在非 TTY 环境下会直接拒绝交互或者改变行为。用 PTY 等于骗过 CLI让它以为自己还在一个正经终端里。会话层是这套系统的核心负责把每一轮对话、每一次工具调用、每一条命令的原始输出都落库。它不关心你用的是哪个 agent只关心“这个 session 当前处于什么状态、历史上发生了什么”。跟你聊天的是 AI但陪你聊天的是会话层。展示层相对简单就是一个浏览器端的终端模拟器加一个会话管理界面。它唯一的特殊职责是处理一件事如果页面刷新或者网络断了怎么把这个 1:1 的交互窗口重新接回去。这层不需要知道 AI 怎么思考只需要忠实呈现流式输出并把用户的键盘输入原样传给 PTY。2.2 持久化三件套快照、消息流、项目上下文持久化不是简单把 stdout 存成文件我把需要保存的东西分成三类会话快照。每个 session 启动时的完整参数项目路径、当前工作目录、选用的 agent、环境变量、系统提示词。这相当于 Qt 里的保存存档——任何时候重启工作区都能按这些参数把会话原样拉起来。消息流。用户说的每句话、AI 回复的每个 token、agent 执行的每条工具调用都按顺序记录并打上递增的序号。这个序号很重要后面讲断线重连会专门解释。项目上下文。每次会话结束时我会让系统自动生成一段摘要追加到项目根目录的 CONTEXT 文件里。下次任何会话开始时AI 会先读这份上下文接着上一次的思路继续干活。这才是真正意义上的“持久化记忆”比单纯依赖 CLI 自己的 resume 功能可靠得多。2.3 为什么必须 WebSocket 而不是轮询早期原型版本我偷懒用过轮询前端每秒请求一次“把新输出给我”。结果是agent 输出一快界面就一卡一卡因为每次请求都要重复拉取缓冲区agent 输出一慢你又得白白浪费请求。更麻烦的是轮询很难处理“服务器主动推送状态变化”这种需求比如任务结束、进程退出、需要用户确认。WebSocket 才是为这个场景设计的。它的三个特性恰好对应我的需求全双工前端能发输入和 resize后端能推输出和状态事件互不干扰低延迟token 一产出就可以通过 WS 帧推给浏览器不用等下一次 HTTP 轮询周期连接语义清晰前端断开后我能立刻感知并决定是杀掉子进程还是让它继续跑。在实际实现里我每个 session 维护一个 WebSocket服务端把 PTY 的数据流原样透传出去前端收到后往 xterm.js 里写。这样即使用户切到别的标签页输出也不会丢。3. 从零搭起工作区环境、骨架与最小可用版本3.1 环境准备和 CLI 安装先说基础设施。整套工作区跑在 Node.js 上所以第一步是确认 Node 版本建议 18 以上我用的是 20 LTS。接着安装两个 agent CLInode -v npm install -g anthropic-ai/claude-code npm install -g openai/codex claude --version codex --version装完之后别急着写代码先把登录搞定。Claude Code 在交互式界面里执行/login走 OAuth 流程Codex 直接执行codex login。这一步做完CLI 会把凭证存在系统钥匙串或用户目录下。后面很多奇怪的报错起点都在这里。3.2 项目骨架与依赖选择创建工作目录装四个核心依赖mkdir easy-web-vibecoding cd easy-web-vibecoding npm init -y npm install express ws node-pty better-sqlite3逐个解释一下选择express 负责提供静态页面和 HTTP 接口ws 负责 WebSocketnode-pty 负责拉起伪终端better-sqlite3 负责持久化。如果你更习惯 Python 生态也可以把 express 换成 fastapi但 node-pty 在 Node 生态里最成熟所以我整套选型跟着 Node 走。最小可用版本不需要做界面浏览器端直接上 xterm.jsnpm install xterm xterm-addon-attach3.3 会话持久层把对话当数据存这是最容易偷懒也最值得做扎实的部分。我用 SQLite 建了两张核心表CREATE TABLE sessions ( id TEXT PRIMARY KEY, project_path TEXT NOT NULL, agent_type TEXT NOT NULL, -- claude 或 codex cwd TEXT NOT NULL, env TEXT NOT NULL DEFAULT {}, status TEXT NOT NULL DEFAULT idle, -- idle / running / paused / done created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ); CREATE TABLE messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL REFERENCES sessions(id), role TEXT NOT NULL, -- user / assistant / system / tool content TEXT NOT NULL, seq INTEGER NOT NULL, -- 输出游标断线重连时用 created_at INTEGER NOT NULL );打开 WAL 模式很重要PRAGMA journal_mode WAL;原因很现实浏览器翻历史记录的时候agent 可能还在往后写新消息。默认的 journal 模式会导致读和写互相锁死WAL 模式让读写并行体验完全不同。这套 schema 跑了一个月几千条消息没有任何性能问题。3.4 最小 WebSocket 桥接让浏览器握住 PTY有了持久层接下来就是把 PTY 和浏览器接起来。核心代码不长我用 node-pty 建子进程const pty require(node-pty); const child pty.spawn(agentCmd, agentArgs, { name: xterm-256color, cols: 120, rows: 40, cwd: session.cwd, env: { ...process.env, ...parsedEnv } }); child.onData(data { // 把输出存进 messages 表同时推给 WebSocket storeOutput(session.id, data); ws.send(JSON.stringify({ type: output, data })); }); ws.on(message, raw { const msg JSON.parse(raw); if (msg.type input) child.write(msg.data); if (msg.type resize) child.resize(msg.cols, msg.rows); });前端用 xterm.js 四行代码就能连上const term new Terminal({ cols: 120, rows: 40 }); const ws new WebSocket(ws://${location.host}/ws?session${id}); term.loadAddon(new AttachAddon(ws)); term.open(document.getElementById(terminal));到这里一个能跑的最小版本就出来了浏览器开一个终端输入命令agent 正常干活输出全部落库。接下来才是让它“持久化”真正好用的关键调节。4. 把 Claude Code / Codex 调教成“能续上”的 Agent关键参数与上下文4.1 两种接入方式的取舍一次性调用 vs 持久交互进程CLI 通常给两种调用方式。一种是一次性调用比如 Claude Code 的-p参数或 Codex 的 exec 模式适合脚本化触发另一种是交互式进程启动后一直等待下一轮输入适合长对话。方式典型命令适合场景代价一次性调用claude -p .../codex exec ...定时任务、单轮问答、批量处理每次都要重新加载上下文长对话不划算持久交互进程直接 spawnclaude/codexvibecoding 主线对话、跨轮次联动需要自己管理状态、输出解析、重连恢复我在工作区里默认走持久交互进程。原因很直接vibecoding 的本质是“多轮你来我往”如果每轮都新起进程AI 的记忆只能靠我们塞回去的文本Token 开销大且丢失交互细节。保持同一进程AI 内部状态是连续完整的。但如果进程被杀掉或服务器重启就得靠 4.2 的上下文方案兜底。4.2 用 CLAUDE.md / AGENTS.md 当项目的“永久记忆”这是整个项目里最值钱的一个设计。Claude Code 会在项目根目录自动读取 CLAUDE.md 作为初始上下文Codex 对应的是 AGENTS.md。我一开始只当它是文档后来才意识到这分明是“给 AI 的持久记忆卡”。我在每个项目的 CLAUDE.md 里维护这几类内容# 项目规则 - 所有时间处理统一用 dayjs不要用原生 Date - 错误信息必须带操作名比如 readFile failed: xxx - 测试文件放在 tests/unit 下命名 xx.spec.ts # 当前模块地图 utils/ - 公共工具改动需同步 axios 封装 legacy/ - 遗留代码禁止大面积重构先增加测试再动手工作区在每次开启会话前会额外生成一份临时的启动提示追加到会话第一轮输入里请先阅读 CLAUDE.md并结合 CONTEXT.md 中上一次会话的摘要继续任务。 上次进展... 待办...这样即使进程完全重启AI 也能在第一条回复里快速回到工作轨道而不是从“你是谁”开始。我试过对比有这份上下文时续接任务的第一轮有效动作通常会提前 5 到 10 分钟。4.3 身份认证与密钥管理的三个注意点第一个坑就是热搜里常出现的codex auth token is unavailable。这类报错多半是后台服务环境下CLI 默认从系统钥匙串读凭证读不到导致的。我处理方式是工作区以后台守护进程方式运行时不依赖 CLI 自己的登录态而是在启动子进程时用环境变量注入密钥export ANTHROPIC_AUTH_TOKENyour_token_here export OPENAI_API_KEYyour_token_here第二个坑是别把密钥写进项目配置文件。我专门在 .gitignore 里加了.env *.token .session-*第三个坑会在 6.1 展开讲就是当你改了 API 基础地址去接其他兼容模型服务时endpoint 路径对不上导致的连环报错。5. 持久化背后的三个关键决策选型与取舍5.1 为什么是 SQLite 而不是纯文件有人会觉得消息记录不就是往文件里 append 吗没那么简单。一次复杂任务可能产生几千条消息有用户输入、AI 回复、工具调用、状态事件我在前端要按 session 分页查、按关键词搜、按时间排序。用纯文件做这些操作要么每次全量读进内存然后手写过滤要么自己维护索引——都很容易翻车。SQLite 的价值不是存储而是查询。一个SELECT * FROM messages WHERE session_id ? ORDER BY seq就搞定了还能配合普通索引把几十万条消息的查询压到毫秒级。而且单文件备份非常方便整个工作区压缩一下就能拷走。但 SQLite 不适合当一个纯粹的“数据流”。我在落库的同时还会把每条原始输出 append 到一个 JSONL 文件里专门用来回放调试。两个系统并行SQLite 管查询JSONL 管真相。5.2 断线重连如何做到不出错这部分是我重构最多的地方。最初版本是浏览器断开WebSocket 一关我就把子进程杀掉太蠢了。用户只是关了页面agent 任务凭什么停新的逻辑是子进程的生命周期由服务端管理而不是由 WebSocket 管理。浏览器断开只影响展示不影响执行。重连时前端把session_id和last_seq一起带上服务端把messages表里所有seq last_seq的消息一次性回放回放完再挂上实时流如果子进程已经不在比如服务重启就根据最新快照重新拉起并用resume/continue等参数尝试续接上一次对话上下文。这个设计跑起来的效果是我白天在公司电脑上打开一个会话晚上回家用笔记本打开同一个 URLAI 会先把白天省略掉的输出补上然后继续等我下一句指令。5.3 多设备访问时的安全边界持久化 Web 工作区意味着“能被浏览器访问”这套便利必须配好边界不然就是给自己挖矿。我的默认配置是只监听 127.0.0.1保证只有本机浏览器能连。如果确实需要局域网或远程访问我不会直接裸开端口而是用反向代理加一层基础认证WebSocket 也走同一个代理路径。同时所有密钥只存在服务端环境变量里浏览器端拿到的永远是渲染后的会话数据页面里绝不出现令牌或配置明文。启动时服务端会在终端打印一个带一次性 token 的 URL类似“浏览器打开这个地址完成授权”。这个机制既是便利也是门槛——总比任何拿到 IP 的人都能直连要强。6. 实测中踩过的三个坑和完整排查过程6.1 codex endpoint 请求失败从日志挖出来的路径问题有段时间我为了让 Codex 接一个第三方兼容模型服务在本地加了一层 API 网关配置。结果每问到一半就报错错误信息大意是“请求 /responses 这个 endpoint 时失败”。最气人的是它不告诉你为什么失败。排查思路按顺序来先开 CLI 的 verbose 日志确认请求到底打到了哪个完整 URL对比日志里的请求路径和网关层实际支持的路由发现网关把请求转发到了/v1/chat/completions而 Codex 发的是/v1/responses路径对不上直接 404修正网关路由映射把/v1/responses正确指向后端同时调大超时时间因为流式响应本身就是要长时间连接的。这个坑的教训是改任何 API 基础地址之前先搞清楚目标服务的接口风格是 chat/completions 还是 responses否则即使认证通过也会在请求层失败。6.2 “authentication required; reopen the url printed by ...”这类认证提示这套工作区用了一段时间后我在一次浏览器缓存清理后碰到了一个很经典的认证提示页面提示需要认证要求重新打开终端里打印的 URL。排查过程其实不复杂看服务端日志确认请求是否带上了正确的授权参数发现是我清理了 Cookie而工作区的授权态存在 HttpOnly Cookie 里重新打开启动时打印的那个带一次性 code 的 URL重新完成授权为避免再犯给授权加了一个较长的有效期并支持用固定入口重新获取。这类问题的本质是“会话凭证存在浏览器侧”如果直接杀掉浏览器进程或者清 Cookie就得重新走一遍授权流程。我的建议是把启动时打印的授权 URL 写进项目目录的 README 里方便以后找回。6.3 输出乱码和长任务中断两个表面上像神迹的故障乱码问题。有个项目里混进了 GBK 编码的日志文件agent 跑测试时把非 UTF-8 内容打到了终端整个输出流被一串锟斤拷中断。PTY 是字节流不负责给你解编码。解决办法是在前端渲染前做一次容忍度高的解码把非法字节替换成占位符而不是让整个 stream 卡死。长任务中断。浏览器断线后子进程虽然继续跑但如果整个服务被重启比如系统自动更新子进程还是会被带走。我的处理是两层防护一是给子进程起独立的进程组服务重启时自动继承会话快照并重新拉起二是定时把当前输出进度写进快照恢复时从最后一条完整记录继续。最终效果是依赖升级这种一小时级任务中途服务重启也不会从头再来。7. 跑了一个月之后我的实际用法和建议7.1 现在的典型工作流这套系统现在是我每天的主力入口。典型的早上是这样的打开浏览器进入工作区首页选择“home 自动化”项目点进昨天的会话。AI 根据 CONTEXT.md 自动恢复上下文先回一段“当前进度依赖打包脚本已完成还剩两个模块的单测命名没统一”然后我直接回复“继续处理那两个模块”。中午出门前我开一个会话让它跑一次全量回归测试然后关掉笔记本。下午用手机打开同一个 URL虽然屏幕小但能看输出、能下指令基本等同于随身带了个开发环境。这个过程放在以前是不可想象的——要么抱着电脑要么牺牲一整个下午的进度。7.2 适合与不适合 Web 工作区的场景跑了一个月我也摸清了这套方案的边界适合的场景不适合的场景长时间重构和大范围代码迁移只改一行字的小操作终端更快后台跑测试、构建、依赖升级依赖 TUI 强交互、需要方向键精细操作的工具跨设备切换、多人轮流看一个会话需要本地 GUI 或桌面通知的工具链联动需要长期追踪项目决策过程离线环境、无浏览器可用的轻量场景手机上看会话只建议“看一眼进度、回一句指令”真做精细 review 还是得回电脑端。这个边界不是工具的缺陷是交互形态本身决定的。7.3 接下来想扩展的方向目前在工作区里跑的还只是单人单会话我很清楚它离“完整产品”还差很多。接下来最想做的是这三个方向一是多用户协作。同一个会话可以生成一个只读分享链接同事打开就能看到 AI 的实时输出不用再截图发聊天软件。二是自动会话摘要。现在每条消息都存但几千条消息找起来还是累。我计划每隔 50 轮自动压缩一次历史生成“阶段性摘要”既保留细节又降低检索成本。三是跟 Git 状态联动。目前 AI 改完代码我还得自己去看 diff。理想状态是在 Web 面板上直接展示改动的文件列表和关键 diff甚至一键回滚某个会话版本。最后分享一个我自己最受用的小技巧每次开始新任务之前先让 AI 把当前git status和 TODO 列表读一遍再生成一份 session-brief 文件。把这句话写进 CLAUDE.md 之后我的会话续接成功率明显高了一截。工具做得再花哨真正让 vibecoding 变成生产力的往往就是这些不起眼的流程细节。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。