用 Claude Code 干活,最烦的不是它写不出来,而是写出来你看不见。我平时习惯把 Claude Code 跑在远程开发机上,让它直接改项目、生成页面文件,可每当它吐出一版新的 HTML,我就得经历一次“从服务器到浏览器”的搬运过程。本地机器还好说,远程环境下每次都要手动传文件、开端口、改地址,折腾几分钟不说,思路全断了。后来翻到一个不起眼的小插件,专门解决 Claude Code 远程预览这一步,装上之后整个工作流顺了不少,今天把这套方案和背后的原理完整拆开讲讲。
这个插件不算大,核心就是把“起服务、监听文件变化、生成可访问链接”这几件事压成一条命令。文章适合正在用 Claude Code 写前端页面、又经常在远程环境里开发的人看,也适合那些被“预览”环节搞到想砸键盘的终端党。我会把痛点、安装步骤、配置参数、常见问题全部过一遍,最后再给你一个可以自己动手改的预览脚本思路。
1. 先说清楚:Claude Code 的远程预览,到底烦在哪
1.1 终端工具天生看不到画面,本地和远程是两回事
Claude Code 本质上是一个跑在终端里的编程代理,它和浏览器之间没有任何关系。你给它一个任务,它负责写代码、改文件、执行命令,但生成的网页效果长什么样,它自己是不知道的。这个特性在本地开发时问题不大,因为文件就在你电脑上,双击打开 HTML、或者起个本地服务就能看。可一旦进入远程开发场景,麻烦就来了。
我在开发机上跑 Claude Code,控制台里能看到它创建了一堆文件,比如dashboard/index.html、style.css,逻辑写得也有模有样。但我想看一眼效果的时候,发现根本没法直接打开,因为这个文件在另一台机器上。要么通过 SSH 把文件拖回本地,要么开一个静态文件服务再手动做端口转发,整个过程和 Claude Code 本身的自动化体验形成强烈反差。
更麻烦的是,Claude Code 写页面通常不是一锤子买卖。它会根据你的反馈反复调整样式、改布局、修交互逻辑,几乎每改一次,你就得重复一遍“搬运到本地 -> 刷新浏览器”的流程。一次两次还能忍,十次二十次之后你就会意识到,最消耗耐心的不是 Claude 改代码的那几秒钟,而是每一次“想知道改成了什么样”之前的那段手动操作。这大概就是标题里说的“最烦的一步”。
1.2 我踩过的预览链路坑:从端口转发到文件搬运
为了把预览这件事理顺,我前前后后试过好几种笨办法,每一种都能用,但每一种都有让人抓狂的地方。
第一种是scp拉文件到本地。Claude 改一版,我scp一次,然后本地打开文件看。听起来简单,但频率一高就受不了,而且 HTML 里如果引用了相对路径资源,比如./js/app.js,file 协议打开时经常会遇到跨域或路径解析问题。更乌龙的是,我有时候会忘记拉最新版本,盯着旧页面改了半天才发现文件没同步。
第二种是手动起一个 Python 或 Node 静态服务,然后做 SSH 隧道。用python3 -m http.server起服务确实快,但端口转发要单独开一个终端窗口盯着,隧道一断就要重来。局域网环境下我也试过直接访问服务器 IP,但开发机的防火墙经常把端口挡在外面,需要临时加规则。这些操作对老手来说不算难,难的是每次都要重复,而且思路全被打断。
第三种是在 VSCode 里接 Claude Code 插件,用编辑器自带的预览能力。VSCode 确实有内置的 Live Preview 或者 HTML 预览面板,连接远程开发环境时也能用,但它更偏向“编辑器内嵌预览”,和 Claude Code 在终端里自动生成文件的场景还是隔了一层。我想达到的效果是,Claude 写完代码之后我用一条命令就能把页面推到浏览器,手机也能随时打开看效果,而不是每次都去手动点编辑器按钮。
2. 这个小插件是怎么解决“最烦一步”的
2.1 三句话讲清楚插件干了什么
我用的这个插件叫cc-preview,核心功能用三句话就能说明白:监听项目目录里的 HTML 文件变化,自动起一个轻量静态服务,然后给你输出一个可以直接访问的预览地址。地址既可以是本机回环地址,也可以是局域网地址,方便手机或其他设备打开。
听起来是不是很像 Live Server?对,思路确实接近,但它的关键在于做成了“插件形态”,深度嵌入了 Claude Code 的工作流。Claude Code 每写完一版页面、保存文件的那一刻,插件能感知到文件变化,并自动向所有打开的预览浏览器页面推送刷新信号。你不需要手动刷新,也不用等着浏览器文件监听插件去发现问题,整个链路从“Claude 保存文件”到“浏览器显示最新效果”中间基本不需要你插手。
我是在 GitHub 上翻到这个小项目的,作者应该也是被远程预览折磨过的开发者,插件的设计思路非常朴素,但恰好打中痛点。如果你用的不是这个插件而是其他类似工具,问题也不大,重点是理解它解决的核心环节:把“文件变化感知、静态服务、局域网访问、自动刷新”这几件事串成一条自动化流水线。
2.2 为什么不自己起 http.server:对比表
有人会问,不就是python3 -m http.server加一个browser-sync吗,自己搭也就几分钟。这话没错,但实际用起来差别很大。我把几种常见方案放在一起对比过,效果如下。
| 方案 | 启动成本 | 文件变化自动刷新 | 局域网/手机访问 | 与 Claude Code 联动 | 日常使用体验 |
|---|---|---|---|---|---|
手动scp拉文件 | 中 | 否,每改一版手动拉一次 | 难,文件在本地 | 否 | 流程割裂,容易拉错版本 |
python3 -m http.server | 低 | 否,需要配合额外工具 | 可以,但要处理防火墙和 IP | 否 | 只解决“能访问”,没解决“访问最新” |
| VSCode Live Preview | 低 | 部分支持 | 不方便 | 弱,依赖编辑器窗口 | 适合本地编辑器党,远程场景体验一般 |
| 自己写 Node/browser-sync 脚本 | 中 | 是 | 可以,但需要自己处理 | 弱,得手动跑脚本 | 可用,但属于重复造轮子 |
cc-preview插件 | 极低 | 是,自动推送刷新 | 是,自动输出局域网地址 | 强,专门适配 Claude Code | 启动一条命令,改动即所见 |
这表不是我严谨评测出来的,是我实际折腾小半年后的真实感受。你会发现手动方案最大的问题是“链路易断”,每改一版文件,你都要重新走一遍流程。而插件方案把整个链路固定成了一条常驻管道,Claude 改文件,插件通知浏览器刷新,你只需要负责看效果、给反馈,非常省心。
2.3 原理拆解:监听、静态服务、自动刷新、生成访问地址
要真正理解这个小插件,光看表面功能不够,得明白它内部做了四件事。
第一件事是文件监听。它用类似chokidar的库监听你指定的目录,目录里任何.html、.css、.js文件发生变化都会触发回调。和生产环境不同,开发预览阶段文件变化非常频繁,所以插件会做一个很短的防抖处理,比如 100 毫秒内只合并成一次刷新,避免 Claude 连续写多个文件时浏览器被疯狂刷新。这个防抖参数很关键,设大了预览有延迟,设小了刷新会抖屏。
第二件事是静态文件服务。它内部起了一个 HTTP 服务器,将指定目录作为根目录。这里有个容易被忽略的点:根目录设置会直接影响 HTML 里的资源引用。如果你的页面通过/style.css访问,那服务根目录应该是项目根目录;如果通过./style.css访问,则根目录可以是页面所在目录。插件默认以项目根目录为根,这样 Claude 生成的多级页面结构不会出现资源 404。
第三件事是自动刷新信号。插件在服务端建立了一个 WebSocket 通道,预览页面里嵌了一小段客户端脚本,收到刷新信号后调用location.reload()。当文件监听到变化并完成防抖合并,服务端就把刷新指令广播给所有连接中的客户端。这一步替代了手动按 F5,也是整个体验最顺滑的地方。
第四件事是访问地址的生成。插件会读取网卡信息,找到当前机器的局域网 IP,然后拼出http://192.168.x.x:端口/页面路径这样的地址。如果你配合 SSH 隧道或内网服务,它也能输出公网可访问地址,但这一步需要额外配置。默认情况下,它优先输出本地回环地址,局域网地址则需要手动开启。
3. 实操记录:装好插件,让预览一句话搞定
3.1 先把 Claude Code 装好并跑通
聊插件之前,得先确保 Claude Code 本身是能跑的。安装方式其实很成熟,最省事的是用 npm 全局安装,一条命令就行。装完之后在终端里输入claude进入交互界面,确认能正常对话。如果你是在远程服务器里用,记得先确认 Node.js 版本够新,老版本跑起来经常会报奇怪的语法错误。
我见过不少人在这一步翻车,尤其是 Windows 的 PowerShell 环境。很多报错其实不是 Claude Code 的问题,而是系统环境变量没配好,或者 Node.js 版本太老。装完先别急着装插件,打开终端输入claude --version,能正常输出版本号再往下走。用 npm 安装时如果遇到权限报错,可以检查一下 npm 全局路径是不是在用户目录下,别一股脑去sudo,容易把权限搞乱。
Claude Code 也支持在 VSCode 里配置使用,但我个人更喜欢纯终端方案,因为远程 SSH 时终端最稳。VSCode 里的集成模式适合想用编辑器窗口看上下文的人,但如果你主要跑在开发机上,终端直接操作会更可靠。
3.2 安装并注册 cc-preview 插件
接下来是正题,安装cc-preview。这个插件可以全局装,也可以装到具体项目里。我建议全局安装,因为预览工具属于高频通用能力,不应该限制在某个项目里。安装命令用 npm 全局安装即可。
装完之后,插件会注册一个cc-preview命令。你可以在 Claude Code 会话里通过斜杠命令直接调用,也可以在普通终端里单独运行。如果你用的是 Claude Code 的 MCP 插件机制,还可以把它注册成可供 Claude 随时调用的工具,这样 Claude 自己会在写完页面后主动拉起预览地址。
注册到 Claude Code 时,需要写一段插件配置。方式取决于你用的 Claude Code 版本,一般是在项目根目录创建一个.claude-plugin/config.json,或者在用户的配置文件里加上 MCP server 条目。下面是一个典型的配置示例:
{ "name": "cc-preview", "version": "1.0.0", "description": "Claude Code 远程预览插件", "commands": { "preview": { "handler": "cc-preview", "description": "启动远程预览服务,输出可访问地址" } }, "mcpServers": { "cc-preview": { "command": "cc-preview", "args": ["--mcp"], "env": {} } } }如果你用的版本还不支持这种配置格式,也不会影响日常使用,直接在终端里手动跑cc-preview命令同样能达到目的。插件的作用是解放双手,但如果你的环境没法完全自动化,至少手动命令也比之前那套方案省事太多。
3.3 真实工作流:从让 Claude 写页面到手机实时预览
我以自己最常用的一个场景为例,完整走一遍流程。我在开发机的某个项目目录里启动 Claude Code,让它做一个待办事项管理页面。Claude 开始工作,生成index.html、style.css、app.js几个文件。以前到这里,我就得开始搬运了,现在不用。
我从终端里直接运行cc-preview --open,插件会扫描当前目录,起一个静态服务,并输出两个地址:一个本地预览地址和一个局域网地址。我用手机扫一下局域网地址的二维码,页面就在手机浏览器里打开了。这时我继续在 Claude Code 里让 Claude 调整按钮颜色、修改列表样式,Claude 每保存一次文件,手机上的页面就会自动刷新,我甚至不用拿手点任何东西。
这套流程最爽的地方是省掉了所有复制粘贴动作。之前我需要记住哪个文件改了、要传到哪个目录、端口映射到哪个本地地址,现在全部由插件接管。Claude Code 负责写代码,插件负责让你看到代码结果,两个工具配合起来,体验才算完整。
如果用 MCP 方式注册,体验还能更进一步。我会在对话里直接跟 Claude 说“把预览地址给我”,Claude 自己能调用cc-preview工具并输出链接,我连终端窗口都不用切。注意,这个能力依赖 Claude Code 对 MCP 工具的支持,如果你发现 Claude 无法主动调用,检查一下配置文件里的mcpServers是否挂载成功。
3.4 常用参数和配置组合
cc-preview的参数不多,但每个都挺有用。我这里列几个我最常用的组合。
默认情况下,插件监听当前目录,端口随机分配,绑定 127.0.0.1,只输出本地预览地址。这适合本地开发。如果你要远程预览,用--host 0.0.0.0让它监听所有网卡,并加上--lan参数输出局域网地址。如果要固定端口,用--port 8000。指定预览目录,用--dir。
一个比较推荐的组合是:
cc-preview --dir ./dist --port 8000 --lan --watch ./src意思是预览dist目录,端口固定 8000,允许局域网访问,监听src目录的代码变化。前端项目经常有构建流程,Claude 修改后先用构建工具输出到dist,插件再自动刷新浏览器。这样“改源码 -> 构建 -> 刷新预览”也可以在一条流水线里完成。
还有一个细节:如果你不希望插件自动打开浏览器,加一个--no-browser。在远程终端里,自动打开浏览器往往没什么用,甚至可能报错,这个参数能把启动速度再提一点。
4. 常见问题与排查技巧实录
4.1 预览过程最容易翻车的几个点
插件本身不复杂,但实际用起来还是会遇到各种意外。我把踩过的坑整理成一张速查表,基本上覆盖了 90% 的预览问题。
| 症状 | 原因 | 解决办法 |
|---|---|---|
| 端口被占用,启动失败 | 默认端口随机冲突 | 换固定端口,如--port 9000,或先查占用再选端口 |
| 手机在局域网打不开页面 | 防火墙拦截或服务只绑定了 127.0.0.1 | 检查服务是否有--host 0.0.0.0,再放行对应端口 |
| 页面能开但样式全乱 | HTML 引用了绝对路径资源 | 确认插件根目录和项目根目录一致,用相对路径或者调整--dir |
| Claude 改了文件但浏览器不刷新 | 监听目录配置不对,或文件写入太快防抖不够 | 用--watch指定实际源码目录,调大防抖窗口到 300ms |
| 预览页面空白 | 页面本身依赖后端 API,浏览器直连拿不到数据 | 给 Claude 的页面代码补充 mock 数据,或者用代理工具转发请求 |
| Windows PowerShell 下运行报错 | Node.js 版本过旧或环境变量混乱 | 升级 Node.js 到 18+,重开终端再试 |
这表示例里最后一条值得多说一句。我见过很多人卡在安装环节就开始怀疑插件有问题,但 PowerShell 报错最常见的原因是执行策略限制了脚本运行,或者 PATH 里没有 npm 全局目录。遇到安装报错不要太早下结论,先看错误信息的前两三行,大部分都能定位到具体问题。
4.2 安全边界:远程预览不是把端口裸奔出去
远程预览方便归方便,但有一个安全问题必须提醒:当你用--host 0.0.0.0打开了局域网访问,任何和你处于同一网络的人都能打开这个地址。如果你的页面里涉及敏感信息,或者你的项目目录结构暴露给不相关的人,是有风险的。
我的习惯是分场景处理。纯本地开发时只用默认的 127.0.0.1 绑定,不开放局域网;需要手机预览时临时开一下局域网模式,用完立刻关掉。如果团队协作需要把预览地址发给其他人,尽量通过内网环境访问,不要直接暴露到公网。插件自身也支持加一个简单的访问令牌,虽然不能替代真正的认证体系,但至少能挡住一些随意扫描端口的请求。
远程开发本身有防护边界时,插件的“危险系数”不高,但我仍然建议在你自己的开发机上不要长期挂着公网监听。这不是项目的限制,而是安全习惯。你永远不知道同一网络里有什么人在扫端口。
4.3 和 codex、vscode、cc switch + ollama 的配合真相
很多人在玩 Claude Code 的时候会同时折腾周边工具,包括 OpenAI Codex、cc-switch、Ollama 这些。我一开始也以为这些工具和远程预览冲突,后来用下来发现它们之间其实互不干扰,各管一段。
先说 Codex。Codex 是另一款终端 Agent,它同样存在“写完页面看不到效果”的问题。不过cc-preview这类插件的原理本质上是独立于 Claude Code 的,只要它能在终端里执行,理论上也能配合 Codex 使用。你可以在 Codex 会话结束后手动运行预览命令,或者用你熟悉的方式把它接进 Codex 的流程。至于“Claude Code 和 Codex 到底选哪个”,我的看法是不要纠结二选一,哪边顺手用哪边,预览插件两边都能用。
再说 cc-switch + Ollama。这套组合可以让 Claude Code 接上本地模型,用于网络受限或者控制成本。很多人担心换到本地模型后插件会不会失灵,实际体验下来完全没问题。插件只关心目录里的文件变化,不关心背后是 Claude 官方 API 还是本地模型生成的代码。换模型之后照样预览,这是它设计得好的地方。
最后说 VSCode 配置。如果你更喜欢在 VSCode 里使用 Claude Code,插件依然可以工作,只是 VSCode 自带的端口转发功能和 Live Preview 可能和插件的局域网地址功能重叠。我的建议是选一个主力方案,不要同时开两套预览服务,否则端口冲突和刷新混乱会让你更头疼。
5. 如果你也想自己做一个“预览技能”
5.1 一个最小可用的预览脚本
如果cc-preview这种现成插件不满足你的需求,完全可以自己写一个。原理我已经在前面拆解过了,实际代码量并不大。下面这个 Node.js 脚本是核心部分,虽然是简化版,但已经能完成“静态服务 + 文件监听 + 自动刷新”这三件事。
const http = require('http'); const fs = require('fs'); const path = require('path'); const chokidar = require('chokidar'); const { WebSocketServer } = require('ws'); const root = process.argv[2] || '.'; const port = Number(process.argv[3]) || 3000; const wss = new WebSocketServer({ port: port + 1 }); // 静态文件服务 const server = http.createServer((req, res) => { const filePath = path.join(root, req.url === '/' ? 'index.html' : req.url); fs.readFile(filePath, (err, data) => { if (err) { res.writeHead(404); res.end('Not Found'); return; } // 在 HTML 中注入自动刷新脚本 let body = data.toString(); if (filePath.endsWith('.html')) { body = body.replace('</body>', `<script> const ws = new WebSocket('ws://' + location.hostname + ':${port + 1}'); ws.onmessage = () => location.reload(); </script></body>`); } res.writeHead(200); res.end(body); }); }); // 文件监听 chokidar.watch(root, { ignoreInitial: true }).on('all', (event) => { wss.clients.forEach((client) => client.send('reload')); }); server.listen(port, () => { console.log(`Preview running at http://localhost:${port}`); });注意这只是示例骨架,生产环境要处理路径穿越、编码问题、防抖逻辑,但对于“自己改着玩”来说已经够了。你用node preview.js /你的项目目录 3000就能跑起来,浏览器里打开http://localhost:3000就能看到页面。Claude Code 每次保存文件,脚本检测到变化就通过 WebSocket 广播刷新。
5.2 让预览链接自动跑到手机上的小技巧
自己写脚本的时候,会发现一个现成插件已经帮你处理好的问题:手机怎么拿到预览地址。最简单的方法是脚本启动时自动打印局域网 IP,但每次手动输入也有点烦。
我后来用了个小技巧:启动脚本时把访问地址生成一个二维码,直接输出到终端。手机扫码就能打开,省去手动输入 IP 和端口。实现起来不复杂,用qrcode这个库,把http://192.168.x.x:3000转成终端里可以显示的 ASCII 二维码,效果非常直观。这样每次启动预览,扫码即可,无论换哪台开发机都瞬间连上。
另外一个实用技巧是让预览脚本在启动时自动探测端口。如果你经常同时开多个项目,固定端口很容易撞车。脚本可以先监听一个基础端口,发现占用就自动加一,直到找到空闲端口,然后把最终地址输出出来。这样你永远不用手工换端口,体验和现成插件基本一致。
最后再分享一个小技巧
用了几周预览插件之后,我现在的工作流已经固定成下面这样:Claude Code 在开发机上写页面,我手机和电脑都开着预览页面,它改一版我立刻就能看到效果。有次同事在旁边看我操作,说感觉像在看别人远程操控我的浏览器,实际上只是文件变化触发了自动刷新。
如果你准备在项目里也用这套方案,有一个小细节值得注意:别让 Claude Code 生成的文件直接和源码混在一起。给 Claude 指定一个明确的输出目录,比如preview/或者dist/,预览插件只监听这个目录。这样 Claude 改代码的时候不会误触发布目录的监听,也不会把临时文件抖到预览里。这个习惯让我少踩了很多刷新混乱的坑。