Chapter 21 | Customizing Slash Commands `/dev`

10 MIN READ | UPDATED: 2026-05-15

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 /dev command 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.