关于 browser-preview
browser-preview 是一项说明预览服务启动后如何在界面中查看和排查问题的技能,面向使用 Preview 面板的用户与 Agent。它提供运行服务登记、历史查询和资源路径排错流程,并明确用户应通过预览 URL 访问,而不是 localhost。
主要功能
- 01说明 Preview 面板操作
- 02查询运行服务与历史记录
- 03诊断预览服务状态
- 04排查静态资源绝对路径
- 05提供预览重启流程
适用场景
- 01找回消失的预览标签
- 02排查白屏或资源加载失败
- 03从历史记录重启项目预览
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ starchild-ai-agent/ official-skills --skill browser-preview安装后在 Claude Code 中输入/browser-preview确认已加载。
详细介绍
浏览器预览
你已经了解 preview_serve 和 preview_stop。本技能补上了其中的空缺:preview_serve 返回 URL 后会发生什么——用户实际上如何查看预览。
什么是预览面板
前端右侧有一个面板,包含两个标签页:文件和预览。预览标签页会在 iframe 中渲染预览 URL。调用 preview_serve 时,前端会自动打开一个加载该 URL 的预览标签页。(作业现在由独立的模态框管理,可从左侧边栏访问,不再位于右侧面板中。)
要点:
- 每次调用
preview_serve都会创建一个预览标签页 - URL 格式:
https://<host>/preview/{id}/ - 预览面板有一个 ⋮ 菜单(右上角),其中显示“运行中的服务”列表
- 用户可以关闭预览标签页,但不会停止后端服务
- 后端服务停止后,预览标签页会显示错误页面
⚠️ 关键:切勿让用户访问 localhost
用户的浏览器无法访问 localhost 或 127.0.0.1。 这些地址指向服务器容器,而非用户的计算机。预览架构使用反向代理:
User's Browser → https://<host>/preview/{id}/path → (reverse proxy) → 127.0.0.1:{port}/path
规则:
- 切勿让用户访问
http://localhost:{port}或http://127.0.0.1:{port}——他们无法访问 - 始终引导用户访问预览 URL:
/preview/{id}/(或完整 URLhttps://<host>/preview/{id}/) curl http://localhost:{port}仅用于你自己的服务器端诊断——切勿建议用户用它来“测试”预览- 预览运行时,告诉用户:“检查预览面板,或刷新预览面板”
- 如果需要向用户提供 URL,请使用
preview_serve返回的url字段(格式:/preview/{id}/)
⚠️ 静态资源必须使用相对路径
由于预览位于 /preview/{id}/ 下,HTML/JS/CSS 中的绝对路径会失效。反向代理会在转发到后端前移除 /preview/{id} 前缀,但浏览器会从域名根目录解析绝对路径。
问题示例:
<script src="/static/app.js"></script>
<script src="static/app.js"></script>
<script src="./static/app.js"></script>
需要修复的常见模式:
| 错误(绝对路径) | 修复后(相对路径) |
|---|---|
"/static/app.js" | "static/app.js" 或 "./static/app.js" |
"/api/users" | "api/users" 或 "./api/users" |
"/images/logo.png" | "images/logo.png" 或 "./images/logo.png" |
url('/fonts/x.woff') | url('./fonts/x.woff') |
fetch('/data.json') | fetch('data.json') |
检查路径出现的所有位置:
- HTML 的
src、href属性 - JavaScript 的
fetch()、XMLHttpRequest、动态导入 - CSS 的
url()引用 - JavaScript 字符串字面量(例如模板字符串或字符串拼接中的
'/static/') - 框架配置文件(例如
publicPath、base、assetPrefix)
⚠️ 请彻底检查——常见情况是修复了 CSS 的 url(),却漏掉了 JS 字符串字面量中的 '/static/'(使用单引号)。请搜索所有文件类型中绝对路径的所有出现位置。
⚠️ 请勿浏览文件系统来调试预览
切勿查看 preview/、output/ 等工作区目录或其他随机文件夹来了解预览状态。这些是用户数据,不是预览服务状态。
唯一可信的信息来源:
- 注册表文件:
/data/previews.json(运行中的服务) - 历史记录文件:
/data/preview_history.json(所有过往服务) preview_serve/preview_stop工具- 通过
curl检查端口(仅限服务器端,用于诊断)
请勿使用 ls/find 检查工作区目录来诊断预览问题。请勿调用 list_scheduled_tasks 等无关工具。请专注于预览问题。
分步操作:诊断预览问题
用户报告任何预览面板问题时,请严格按以下顺序操作:
第 1 步:读取注册表(运行中的服务)
cat /data/previews.json 2>/dev/null || echo "NO_REGISTRY"
⚠️ 你的 bash CWD 是 /data/workspace/。注册表位于 /data/previews.json(绝对路径,在上一级目录)。请始终使用绝对路径。
JSON 结构:
{
"previews": [
{"id": "f343befc", "title": "My App", "dir": "/data/workspace/my-project", "command": "npm run dev", "port": 9080, "is_builtin": false}
]
}
步骤 2:根据注册表状态分支
如果注册表中有条目 → 转到步骤 3(验证服务) 如果注册表为空或不存在 → 转到步骤 4(检查历史记录)
步骤 3:注册表中有条目 — 验证并修复
对于注册表中的每个预览,检查端口是否在服务端响应(这是你的诊断操作,不是给用户做的):
curl -s -o /dev/null -w "%{http_code}" http://localhost:{port}
如果端口有响应(200):
- 服务正在运行。告诉用户:
- “你有一个正在运行的服务:{title}”
- “点击 Preview 面板右上角的 ⋮ 菜单,然后在 RUNNING SERVICES 列表中点击该服务以重新打开”
- Preview URL:
/preview/{id}/
- 如果用户说 ⋮ 菜单为空或没有显示该服务 → 前端同步丢失。通过重新创建来修复:
preview_stop(id),然后使用注册表中的信息调用preview_serve(dir, title, command)。这会强制前端重新注册标签页。
如果端口没有响应:
- 进程已崩溃,但注册表条目仍存在。重新创建:
preview_stop(id="{id}") preview_serve(dir="{dir}", title="{title}", command="{command}")
步骤 4:没有正在运行的服务 — 先检查历史记录,再扫描工作区
没有正在运行的服务时,使用两层查找来寻找用户可以预览的项目:
第一层:读取预览历史记录(首选 — 快速且准确)
cat /data/preview_history.json 2>/dev/null || echo "NO_HISTORY"
JSON 结构:
{
"history": [
{
"id": "f343befc",
"title": "Trading System",
"dir": "/data/workspace/my-project",
"command": "python main.py",
"port": 8000,
"is_builtin": false,
"created_at": 1709100000.0,
"last_started_at": 1709200000.0
}
]
}
preview_stop 不会删除历史记录条目 — 它们会在重启后保留。只有在项目目录不再存在时,条目才会自动清理。
如果历史记录中有条目:
- 向用户列出所有历史记录条目,包括标题、目录和上次启动时间
- 询问他们想重启哪个项目
- 使用历史记录条目中的
dir、title和command调用preview_serve
如果用户说历史记录中缺少某个项目 → 转到第二层。
第二层:扫描工作区(备用 — 历史记录为空或不完整时)
find /data/workspace -maxdepth 2 \( -name "package.json" -o -name "index.html" -o -name "*.html" -o -name "app.py" -o -name "main.py" -o -name "vite.config.*" \) -not -path "*/node_modules/*" -not -path "*/skills/*" -not -path "*/memory/*" -not -path "*/prompt/*" -not -path "*/.git/*" 2>/dev/null
然后:
- 列出发现的项目并简要描述
- 询问用户想预览哪个项目
- 使用相应目录调用
preview_serve
不要只说“没有正在运行的服务”就此打住。 务必先检查历史记录,再进行扫描,并提供可选项。
快速参考
| 用户说 | 你的操作 |
|---|---|
| “标签页消失了” / “tab 不见了” | 步骤 1 → 2 → 3 或 4 |
| “空白页” / “白屏” | 检查端口(服务端);如果无响应 → 重新创建;如果有响应 → 检查绝对路径问题 |
| “没有更新” / “内容没更新” | 建议点击 Preview 标签页中的刷新按钮,或重新创建预览 |
| “端口冲突” / “端口冲突” | preview_stop 旧服务 → preview_serve 新服务 |
| “看不到服务” / “⋮ 菜单为空” | 调用 preview_stop + preview_serve,强制重新注册 |
| “我的项目在哪” / “我构建了什么” | 读取 /data/preview_history.json 并列出条目 |
| “资源加载失败” / “JS/CSS 404” | 检查绝对路径(/static/、/api/),将其改为相对路径 |
你无法执行的操作
- 无法直接打开、关闭或刷新 Preview 标签页(前端 UI)
- 无法强制刷新 iframe
- 无法读取 iframe 中显示的内容
无法执行某项操作时,告诉用户需要手动执行的操作(例如,“在 Preview 标签页中点击刷新”)。如果手动操作无效,则使用 preview_stop + preview_serve 重新创建预览。
应避免的常见错误
- ❌ 告诉用户“访问 http://localhost:18791/” — 用户无法访问 localhost
- ❌ 说“刷新 localhost 上的页面” — 对用户来说毫无意义
- ❌ 只修复 CSS
url()路径,却漏掉含有绝对路径的 JS 字符串字面量 - ❌ 忘记检查所有文件类型(HTML、JS、CSS、配置)中的绝对路径
- ✅ 面向用户时始终使用
/preview/{id}/作为 URL - ✅ 仅将
curl localhost:{port}用于你自己的服务端诊断 - ✅ 修复路径后,调用
preview_stop+preview_serve重启,然后告诉用户检查 Preview 面板