第 21 章 | 自定义 slash 命令 `/dev`
💡 进群学习加 wx: agentupdate
(申请发送: 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 全自动。