第 21 章 | 自定义 slash 命令 `/dev`

更新于 2026/5/12
💡 进群学习加 wx: agentupdate
(申请发送: agentupdate)

第 21 章:自定义 slash 命令 /dev

学习目标

把"编排逻辑"封装成一个可由用户敲一次触发的命令。

slash 命令是什么

flowchart LR
    User["用户敲 /dev 1"] --> CC["Claude Code"]
    CC --> Read["读 .claude/commands/dev.md"]
    Read --> Inject["把内容注入 main Claude
+ 替换 $ARGUMENTS"] Inject --> Execute["main Claude 按指令执行"] style Read fill:#fff9c4 style Execute fill:#c8e6c9

→ 本质上是可复用的提示模板,比每次手敲一长段话方便。

文件位置

项目级:  <project>/.claude/commands/<name>.md
用户级:  ~/.claude/commands/<name>.md

我们的 dev.md 骨架

---
description: Run the orchestrated implementation workflow on the active OpenSpec change.
---

# /dev — Orchestrated Implementation

Run the multi-agent implementation workflow defined in `CLAUDE.md`.

ARGS: $ARGUMENTS

---

## What you (main Claude) must do

You are the dispatcher. Follow CLAUDE.md "Implementation Workflow" exactly.

### Step 1: Resolve active change
\`\`\`bash
openspec list --json
\`\`\`
Pick the change that has `archived: false`.

### Step 2: Resolve mode (from $ARGUMENTS)

| Argument | Mode |
|---|---|
| empty | auto-all |
| number (e.g. `3`) | single-group |
| `e2e` | e2e-only |
| `status` | report-only |

### Step 3: Build state snapshot
[reading rules...]

### Step 4: Act per mode
[per-mode logic...]

### Step 5: Briefing rules
[what to put in each agent's briefing...]

### Step 6: After every dispatch, RE-READ files
[trust files, not agent stdout...]

### Step 7: TDD groups
[TDD-flagged groups need tester first...]

### Step 7.5: Escalation routing
[chooseDevAgent / chooseTesterAgent...]

### Step 7.6: Architect dispatch
[when to invoke architect...]

### Step 8: Hard stop conditions
[what makes the loop stop...]

## Output format
[what the trace should look like...]

$ARGUMENTS 的处理

flowchart TD
    Args["$ARGUMENTS"] --> Q{值?}
    Q -->|""| Mode1["auto-all"]
    Q -->|数字 N| Mode2["single-group N"]
    Q -->|e2e| Mode3["e2e-only"]
    Q -->|status| Mode4["report-only"]
    Q -->|其他| Ask["问用户澄清"]

    style Mode1 fill:#c8e6c9
    style Mode2 fill:#bbdefb
    style Mode3 fill:#fff9c4
    style Mode4 fill:#f8bbd0

同一个命令、4 种行为,靠参数区分。

内部"伪代码"逻辑

写命令文件时,我们用伪代码描述编排逻辑:

loop:
  if not DEV_DONE:
    pickedDev = chooseDevAgent(N)         # 决定用 sonnet 还是 opus
    dispatch pickedDev
  if not TEST_PASSED:
    pickedTester = chooseTesterAgent(N)
    dispatch pickedTester
    if FAIL:
      testFailRound[N]++
      continue (loop back to dev)
  if not APPROVED:
    dispatch reviewer
    if REJECTED:
      reviewerRound[N]++
      continue
  break (group APPROVED)

→ main Claude 读到这段会按伪代码意图执行。你不需要写真代码——它是个智能 LLM,伪代码就够。

Briefing 模板

每次 dispatch 都要给 agent 带什么:

For developer:
  - All `- [ ]` tasks under that group
  - Required reading: design.md, spec.md
  - Prior-round feedback (if loopback)

For developer-deep:
  - Same as developer, PLUS:
  - Why escalated: e.g. "testFailRound=3"
  - Full review/N.md history
  - Explicit instruction: "you may flag spec defect via PATH=A"

For tester:
  - Diff summary
  - Scenario list
  - Test report path: test-reports/N.md

For reviewer:
  - Full diff
  - Required reading: proposal.md, design.md, spec.md
  - Round number; if >= 2, include previous review/N.md

For e2e-tester:
  - Default input: examples/install-claude-code.md
  - Forbidden paths: src/, tests/, openspec/specs/

briefing 写死在 dev.md 里,主 claude 每次照抄。

输出格式(让 trace 可读)

我们规定 dev.md 输出每行用固定符号:

符号 含义
正常 dispatch
回炉(再来一轮)
⚠️ 升级 / STUCK 事件(hook 用此触发通知)
完成
卡住

例子:

→ Group 2: dispatch developer (sonnet)        ... done
→ Group 2: dispatch tester (sonnet)           ... FAIL (2/8)
↻ Group 2: dispatch developer (sonnet) R2     ... done
⚠️ Group 2: escalating to developer-deep (reason: testFailRound=3)
✓ Group 2: Markdown 解析

→ 一眼看清"现在到哪一步"。

反模式

❌ /dev 命令写成 "do everything, figure it out"
   → 没具体规则 = main Claude 凭直觉

❌ 不解析 $ARGUMENTS
   → 一个命令只能一个行为

❌ 没有"重读文件"步骤
   → 信 agent 的 stdout,会被骗

❌ 把所有 agent 的 system prompt 塞进 dev.md
   → 重复了 .claude/agents/ 里的内容

❌ 没有死循环阈值
   → 跑到天荒地老

你现在能做什么

  • 写一份能把整套 workflow 串起来的 /dev 命令
  • 通过 $ARGUMENTS 让一个命令支持多种模式
  • 设计输出格式让 trace 可被人和机器同时读

下一章讲怎么"让用户少操心"——半手动 vs 全自动。