mcpField
D
dev

dev

github.com/yonatangross开发30048 次安装今天更新
代码仓库

关于 dev

dev 是面向 Claude Code 开发流程的技能,用一条命令启动并管理本地开发服务器、可选模拟器和 agent-browser 会话。它按 Git worktree 隔离子域名与状态,并提供状态查看、停止及预览共享模式。

主要功能

  1. 01一键启动开发循环组件
  2. 02按分支创建 HTTPS 子域名
  3. 03预热并注册 agent-browser 会话
  4. 04支持幂等启动、状态查看和停止
  5. 05提供 tailnet 与公开预览模式

适用场景

  1. 01开始新分支时启动开发环境
  2. 02中断后恢复正在运行的开发会话
  3. 03与团队成员或相关方共享预览
  4. 04演示时限时公开本地预览

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatangross/orchestkit --skill dev

安装后在 Claude Code 中输入/dev确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

test-cases.json
references/
state-schema.md
boot-sequence.md
rules/
_template.md
lab-stack-prerequisites.md
teardown-order.md
idempotent-boot.md
_sections.md
branch-named-subdomain.md
scripts/
status.sh
boot.sh
stop.sh

详细介绍

dev — Lab-Stack 启动

一条命令即可启动 Vercel-Labs 风格开发循环中的四个组成部分:

  1. portless → 命名 HTTPS 地址 https://<branch>.localhost(不同工作树之间不会发生端口冲突)
  2. emulate → 通过 @emulators/adapter-next 在同一源上运行有状态 API 模拟器
  3. 开发服务器 → pnpm dev / npm run dev / yarn dev(自动检测)
  4. agent-browser → 预热一个以分支命名的会话

状态保存在 .claude/state/dev-stack.json 中。dev stop 会读取 PID,并按启动顺序的逆序发送 SIGTERM 信号来停止进程。

与 expect 配套使用: dev 预热的 agent-browser 会话,也是 expect(以及 M125 #2 自动触发功能)所连接的会话——首次 UI 测试无需再承受第二次启动延迟。

何时调用

情况命令
在新分支上开始工作dev
会话中断后恢复dev(幂等——跳过已运行的进程)
删除分支前停止服务dev stop
检查状态dev status
与利益相关者共享预览dev --share(tailnet)或 dev --funnel(公开)
限时现场演示dev --live 4(公开 funnel,有效期为 4 小时)

恢复转入后台的开发会话(CC 2.1.144+): 通过 claude --bg 启动的会话现在会与交互式会话一同显示在 /resume 中,并标记为 bg——崩溃或会话结束后,请使用 /resume 直接恢复,而无需浏览 Agent 视图。

后台 Shell 会话(CC 2.1.154+): 在 claude agents 中,输入 ! <command> 即可将 Shell 命令作为后台会话运行,你可以连接或断开该会话——也可通过 claude --bg --exec '<command>' 运行。适用于需要监控但不想一直占用终端的长时间开发循环进程(监视器、构建任务、服务器)。

模式(M127)

标志包装的命令可访问范围是否需要 Tailscale CLI
(无)portless <slug> <pkg-mgr> run dev仅限 https://<branch>.localhost不需要
--shareportless --tailscale ...tailnet 成员可通过 https://*.ts.net 访问需要
--funnelportless --funnel ...可在互联网公开访问需要
--live Nportless --funnel ... + N 小时有效期公开可访问,记录在 live-demos.jsonl 中需要

Tailscale 是可选的——仅在使用 --share/--funnel/--live 时需要。对于不共享预览的用户,默认的 dev 行为保持不变。

检测到 turbo.json 或 package.json 工作区时(#1562),启动过程会使用裸 portless(零配置),自动发现每个工作区的开发脚本,并通过任务图分配子域名。状态文件会显示 mode: "monorepo";可通过 portless list 或 dev status 列出子域名。

启动顺序

portless 是一个包装器,而非伴随进程——portless <slug> <pkg-mgr> run dev 是一个融合命令,负责管理开发服务器的生命周期。boot.sh 会跟踪包装器的 PID;stop.sh 会遍历其进程树以清理子进程。

0. Detect package manager      pnpm > yarn > bun > npm   (lockfile-based)
1. Resolve subdomain slug      <branch> → lower → / to - → DNS-safe → ≤63 chars
2. portless proxy start         (idempotent — skipped if `portless list` already responds)
3. emulate --seed <yaml>        (sidecar, optional — only if emulate.config.yaml exists)
4. portless <slug> <pkg-mgr> run dev   (FUSED — wrapper owns dev server's lifecycle)
5. portless get <slug>          (poll up to 30s for the route to register)
6. wait-on <baseUrl>            (poll up to 30s for the dev server through the proxy)
7. AGENT_BROWSER_SESSION=<slug> agent-browser open <baseUrl>   (warm + register session)
8. atomic state write           (.claude/state/dev-stack.json via jq + temp + mv)
9. print summary

完整的注释版说明:references/boot-sequence.md。

状态文件结构

{
  "bootedAt": "2026-04-27T12:34:56Z",
  "branch": "feat/m125-lane-b",
  "subdomain": "feat-m125-lane-b.localhost",
  "baseUrl": "https://feat-m125-lane-b.localhost",
  "mode": "single",
  "processes": {
    "portlessWrapper": {
      "pid": 86104,
      "command": "portless feat-m125-lane-b pnpm run dev"
    },
    "agentBrowser": { "sessionName": "feat-m125-lane-b" },
    "emulate":      { "pid": 86200, "command": "emulate --seed emulate.config.yaml" }
  },
  "emulators": ["github", "stripe"],
  "share": null,
  "notes": "portless proxy daemon is shared and not tracked here — stop.sh leaves it running."
}

使用 --share / --funnel / --live 时(M127 #1561 / #1565),share 会变为:

"share": {
  "mode": "tailscale",
  "tailscaleUrl": "https://app.your-tailnet.ts.net",
  "expiresAt": "2026-05-03T20:00:00Z"
}

mode 为 "single"(默认)或 "monorepo"(检测到 turbo.json/工作区时)。请注意,使用的是 portlessWrapper(而不是 portless + devServer)——portless 负责管理开发服务器。完整架构:references/state-schema.md。

自动显示的提示(M127)

启动 dev 时,它会检查 package.json 并显示提示:

  • 检测到 @json-render/*(#1560)→ 输出 devtools 适配器导入行,以便在开发环境中启用检查器面板(Spec / State / Actions / Stream / Catalog / Pick)。生产构建会通过摇树优化移除相关代码。
  • 检测到 @clerk/*(#1563)→ 如果 emulate.config.yaml 中有 clerk,则输出模拟登录 URL(http://localhost:4012);否则提示运行 emulate-seed --auto。

前置条件 + 平稳无操作

$ dev
✓ portless     found
✓ agent-browser     found
✓ jq     found
[1] slug       feat-m125-lane-b

# OR with a missing prereq:
✗ portless not found.   Install: npm i -g portless

Skipping boot — install missing tools and re-run.

需要 portless、agent-browser 和 jq。emulate 是可选项——仅当 emulate.config.yaml 存在时才需要。启动时必须满足所有必需条件;如果没有 emulate 配置,启动会在不启用模拟器的情况下继续。

CI=1 会让启动流程提前结束(立即以 0 退出)。

状态 + 拆除

$ dev status
ork:dev — feat/m125-lane-b
  ✓ portlessWrapper    portless feat-m125-lane-b pnpm run dev
  ✓ agentBrowser       feat-m125-lane-b
  base url:  https://feat-m125-lane-b.localhost
  booted:    2026-04-27T19:36:54Z
  portless:  route registered ✓

$ dev stop
ork:dev — sending SIGTERM in reverse boot order…
  ✓ agent-browser session "feat-m125-lane-b" closed
  ✓ portless wrapper (pid 86104) + 21 descendant(s) stopped
Cleared .claude/state/dev-stack.json

Note: portless proxy daemon left running (shared). Run `portless proxy stop` if you really mean to stop the daemon.

停止时会遍历包装器的进程树(递归调用 pgrep -P),并从叶节点开始向上向后代进程发送 SIGTERM,因为 portless 并不总能正确传递信号。portless 代理守护进程本身是共享基础设施,dev stop 绝不会将其杀掉。

工作树行为

每个 git 工作树都有自己的子域名——feat-foo.localhost 和 feat-bar.localhost 可以在同一台机器上共存。状态文件位于各自工作树的 .claude/state/ 下,因此从一个工作树运行 dev 时看不到另一个工作树的进程。

幂等性

如果服务栈已在运行,再次运行 dev 不会执行任何操作:

$ dev
ork:dev — feat/m125-lane-b already running.
  https://feat-m125-lane-b.localhost  (uptime 2h 14m)
Run dev stop to tear down, or dev status for detail.

存活探测:针对每个已跟踪的 PID 调用 process.kill(pid, 0)。如果有进程已停止运行,该技能会显示具体进程,并提供清理状态并重新启动的选项。

agent-browser 如何协同工作

会话名称等于子域名——如果只连接了一个会话,针对该会话的 agent-browser 命令无需添加 --session 标志:

agent-browser open "https://feat-m125-lane-b.localhost/dashboard"
# implicit session = "feat-m125-lane-b" because it's the only one

expect(M125 #2)会读取开发栈状态文件并复用同一个会话,无需再次握手。

与 expect(M125 #2)集成

在编辑 .tsx 文件后触发 auto-expect 时,它会:

  1. 读取 .claude/state/dev-stack.json,查找 agent-browser 会话和基础 URL。
  2. 根据文件路径计算受影响的路由(app/dashboard/page.tsx → /dashboard)。
  3. 使用实时会话,通过 <baseUrl><route> 操作 agent-browser。
  4. 将 ARIA 快照记录到以 (route, parentCommit) 为键的记忆中(M125 #6)。

如果开发栈未在运行,auto-expect 会静默跳过——dev 是前置条件,而非硬依赖。

不适用的情况

  • CI — 设置 CI=1;该技能会以 0 退出,不会启动服务。
  • 生产部署 — 绝不适用;这仅用于开发循环。
  • 非 Vercel-Labs 服务栈 — 会回退到安装提示;你仍可手动运行底层工具。
  • 处于 tmux -CC 会话中 — agent-browser 仪表板与 iTerm2 tmux 集成不兼容。

脚本

脚本功能
scripts/boot.sh检查所有前置条件,全部满足后按 9 个步骤启动。具备幂等性(如果已在运行则不执行任何操作)。在 CI 中遵循 CI=1 跳过启动。
scripts/stop.sh按启动顺序的逆序发送 SIGTERM,5 秒后回退为 SIGKILL。最后移除状态文件。
scripts/status.sh显示格式化状态。使用 --quiet 仅检查存活状态(运行时退出 0,已停止时退出 1)。供 boot 检查幂等性时使用。

dev 会调用 scripts/boot.sh;stop → stop.sh;status → status.sh。Shell 脚本是唯一可信来源。

参考资料

文件用途
references/boot-sequence.md按步骤说明启动流程并附带命令
references/state-schema.md完整的 JSON 结构及字段语义

规则

规则影响适用场景
rules/lab-stack-prerequisites.mdCRITICAL每次启动
rules/branch-named-subdomain.mdHIGH子域名解析
rules/idempotent-boot.mdHIGH服务栈运行时再次启动
rules/teardown-order.mdMEDIUM调用 stop 时

使用 /goal 无人值守运行

使用 /goal(CC 2.1.139+)设置完成条件后,该技能会在多轮对话中持续工作,直至满足条件。适用于交互模式、-p 和 Remote Control。覆盖面板会实时显示已用时间、轮数和令牌数。

此技能的完成条件示例:

/goal until services.running == 4, or stop after 5 turns

满足以下条件时停止:全部 4 个开发循环服务(portless + emulate + dev-server + agent-browser)都在各自端口/套接字上报告健康状态。兼容 claude.ai Remote Control 运行。

相关技能

  • expect — 感知差异的浏览器测试;复用此技能预热的 agent-browser 会话
  • emulate-seed — 生成步骤 3 使用的模拟器配置
  • portless(技能)— 底层工具文档
  • browser-tools(技能)— agent-browser 命令参考

评论

支持 Markdown