---
name: run-<unit-name>
description: 构建、运行和驱动 <unit-name>。当要求启动 <unit-name>、运行其测试、构建它、拍摄其 UI 截图或与正在运行的应用交互时使用。
---

<One-sentence description: what this is and how an agent drives it.
Name the handle here — "drive it via
`.claude/skills/run-<unit-name>/driver.mjs` under xvfb" for a desktop
app, or "start the dev server then drive it via `chromium-cli`" for a
web app — so an agent knows where to look first.>

<If the unit isn't at repo root:>
下面所有路径相对于 `<unit-dir>/`。

## 前置条件

<System-level requirements. The exact `apt-get install` line you ran — not a generic list, the one that actually worked. Target Ubuntu.>

```bash
sudo apt-get update
sudo apt-get install -y <packages-you-actually-installed>
```

<Runtime versions if they matter:>

```bash
# 示例：通过 nvm 的 Node 20，通过 uv 的 Python 3.12，等等。
```

## 设置

<One-time setup after clone: install deps, configure, apply any patches (feature-gate overrides, config stubs) with the exact command.>

```bash
<commands>
```

<Env vars — required vs optional, with sensible defaults:>

```bash
export FOO_API_KEY=...   # 必需——从 <where> 获取
export BAR_MODE=dev      # 可选——默认为 prod
```

## 构建

<Skip if no separate build step. Otherwise the exact command:>

```bash
<command>
```

## 运行（代理路径）

<This is the section a future agent actually uses. If you built a driver/REPL/smoke script, this documents how to launch it and what it does. If the app is simple enough that `curl` or a one-liner suffices, that one-liner goes here.>

```bash
<launch-the-driver-or-smoke-script>
```

<For REPL-style drivers, show the tmux wrapping. Poll for a ready marker between send-keys and capture-pane — faster than a fixed sleep and fails loudly instead of capturing a half-rendered screen:>

```bash
tmux new-session -d -s app -x 200 -y 50
tmux send-keys -t app '<launch command>' Enter
timeout 30 bash -c 'until tmux capture-pane -t app -p | grep -q "<ready-marker>"; do sleep 0.2; done'
tmux send-keys -t app '<first driver command>' Enter
tmux capture-pane -t app -p
```

<Where artifacts land (screenshots, logs) — absolute paths:>

截图 → `/tmp/shots/`。日志 → `/tmp/<app>.log`。

<If the driver has commands, a table:>

| 命令 | 它做什么 |
|---|---|
| `<cmd>` | <description> |

## 运行（人类路径）

<If meaningfully different from the agent path. Brief — agents won't use this, humans can figure it out.>

```bash
<command>   # → <what happens>。<how to stop>。
```

## 测试

```bash
<command>
```

<Expected result — "N suites pass", or specific known-flaky tests.>

---

<Optional sections below — include only if relevant and only with content you actually hit, not generic advice.>

## 陷阱

<Non-obvious traps. The things that look like they should work but don't, with the workaround. If this section is generic, delete it.>

- **<specific thing>** — <why it breaks> → <what to do instead>

## 故障排除

<Symptom → fix. Only errors you actually encountered.>

- **<exact error message or symptom>**: <cause>。<fix>。

<!---

关于上方前置元数据的说明：
- 在 `name:` 和 `description:` 中都替换 `<unit-name>`。`name:` 变成斜杠命令（/run-<unit-name>），必须与目录名称匹配。
- `description:` 是 Claude 扫描以决定是否自动加载此技能的内容。保留动词——"启动"、"运行"、"构建"、"测试"、"截图"——它们是提问的实际用语。

关于驱动程序：
- 如果你编写了驱动程序脚本，它默认位于此同一目录（此文件旁边）。从运行章节引用它。
- 对于 Web 应用，通常没有驱动程序文件——运行章节中的 `chromium-cli` heredoc 就是整个框架。
- 如果驱动程序成长为项目测试套件想要的东西——共享的启动辅助函数、真正的 e2e 框架——将其移到单元中的 scripts/ 或 e2e/，并在此处更新路径。技能位置保持不变。

提交前删除从 `---` 以上到末尾的所有内容。--->
