Chapter 21: Custom Slash Command /dev
Learning Objectives
Encapsulate "orchestration logic" into a single command triggered by user input.
What is a Slash Command?
flowchart LR
User["User types /dev 1"] --> CC["Claude Code"]
CC --> Read["Reads .claude/commands/dev.md"]
Read --> Inject["Injects content into main Claude
+ Replaces $ARGUMENTS"]
Inject --> Execute["main Claude executes instructions"]
style Read fill:#fff9c4
style Execute fill:#c8e6c9→ Essentially, it's a reusable prompt template, more convenient than typing a long message every time.
File Location
Project-level: <project>/.claude/commands/<name>.md
User-level: ~/.claude/commands/<name>.md
Our dev.md Skeleton
---
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
---
## Chapter 21: 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...]
## Chapter 21: Output format
[what the trace should look like...]
Handling $ARGUMENTS
flowchart TD
Args["$ARGUMENTS"] --> Q{Value?}
Q -->|""| Mode1["auto-all"]
Q -->|Number N| Mode2["single-group N"]
Q -->|e2e| Mode3["e2e-only"]
Q -->|status| Mode4["report-only"]
Q -->|Other| Ask["Ask user for clarification"]
style Mode1 fill:#c8e6c9
style Mode2 fill:#bbdefb
style Mode3 fill:#fff9c4
style Mode4 fill:#f8bbd0→ One command, four behaviors, differentiated by arguments.
Internal "Pseudocode" Logic
When writing command files, we describe the orchestration logic using pseudocode:
loop:
if not DEV_DONE:
pickedDev = chooseDevAgent(N) # Decides whether to use sonnet or 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 will execute this section according to the pseudocode's intent. You don't need to write actual code — it's a smart LLM, pseudocode is sufficient.
Briefing Templates
What to include for the agent in each dispatch:
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/
→ The briefing is hardcoded in dev.md, and main Claude copies it every time.
Output Format (for readable traces)
We stipulate that each line of dev.md output uses fixed symbols:
| Symbol | Meaning |
|---|---|
→ |
Normal dispatch |
↻ |
Rework (another round) |
⚠️ |
Escalation / STUCK event (hooks use this to trigger notifications) |
✓ |
Complete |
✗ |
Stuck |
Example:
→ 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 Parsing
→ Clearly see "what step we're on now" at a glance.
Anti-patterns
❌ /dev command written as "do everything, figure it out"
→ No specific rules = main Claude relies on intuition
❌ Not parsing $ARGUMENTS
→ One command, one behavior only
❌ No "re-read files" step
→ Trusting agent stdout leads to being misled
❌ Stuffing all agent system prompts into dev.md
→ Duplicates content in .claude/agents/
❌ No infinite loop threshold
→ Runs forever
What You Can Do Now
- Write a
/devcommand that orchestrates the entire workflow. - Enable a single command to support multiple modes via
$ARGUMENTS. - Design an output format that makes traces readable by both humans and machines.
The next chapter discusses "reducing user effort" — semi-manual vs. fully automated.