Skip to main content
ClaudeWave
Skill91 repo starsupdated 3mo ago

dry-run

The dry-run skill allows safe testing of commands by simulating all side effects without executing them. It executes all read operations normally while previewing file writes, git operations, agent spawns, and state changes in a standardized summary format. Use the --dry-run flag on any command to inspect intended effects before committing to actual changes.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/marcusgoll/Spec-Flow /tmp/dry-run && cp -r /tmp/dry-run/.claude/skills/dry-run ~/.claude/skills/dry-run
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

<objective>
The dry-run skill enables safe command testing by simulating all side effects without execution.

**Problem**: Commands make real changes - creating files, spawning agents, modifying state, executing git operations. Testing commands on production workflows risks unintended modifications.

**Solution**: Add `--dry-run` flag that:
1. Executes all **read** operations (for accurate analysis)
2. Simulates all **write** operations (shows what would change)
3. Previews **agent spawns** (shows what Task() calls would occur)
4. Reports **state changes** (shows YAML mutations)
5. Outputs **standardized summary** (consistent format across commands)

The result: Safe command testing with full visibility into intended effects.
</objective>

<quick_start>
<flag_detection>
**Detect --dry-run in command arguments:**

```bash
# In command process section
DRY_RUN=false
if echo "$ARGUMENTS" | grep -q -- "--dry-run"; then
  DRY_RUN=true
  # Remove flag from arguments for processing
  ARGUMENTS=$(echo "$ARGUMENTS" | sed 's/--dry-run//g' | xargs)
fi
```

**Checking in command logic:**
```markdown
If DRY_RUN is true:
  - Collect intended operations in simulation log
  - Skip actual Write/Edit tool calls
  - Skip actual Task() spawns (log them instead)
  - Skip actual Bash commands with side effects
  - Execute Read/Grep/Glob normally
  - Output dry-run summary at end
```
</flag_detection>

<simulation_output_format>
**Standard dry-run output format:**

```
════════════════════════════════════════════════════════════════════════════════
DRY-RUN MODE: No changes will be made
════════════════════════════════════════════════════════════════════════════════

📁 FILES THAT WOULD BE CREATED:
  ✚ specs/004-auth/spec.md (estimated ~150 lines)
  ✚ specs/004-auth/state.yaml (workflow state)
  ✚ specs/004-auth/NOTES.md (session notes)

📝 FILES THAT WOULD BE MODIFIED:
  ✎ specs/004-auth/state.yaml
    - phase: init → spec
    - status: pending → in_progress

🤖 AGENTS THAT WOULD BE SPAWNED:
  1. spec-phase-agent: "Execute spec phase for user authentication"
  2. clarify-phase-agent: "Clarify requirements"
  3. plan-phase-agent: "Generate implementation plan"

🔀 GIT OPERATIONS THAT WOULD OCCUR:
  • git checkout -b feature/004-auth
  • git add specs/004-auth/
  • git commit -m "feat: initialize auth feature workspace"

📊 STATE CHANGES:
  state.yaml:
    phase: spec → plan → tasks → implement
    status: pending → in_progress → completed

════════════════════════════════════════════════════════════════════════════════
DRY-RUN COMPLETE: 0 actual changes made
Run without --dry-run to execute these operations
════════════════════════════════════════════════════════════════════════════════
```
</simulation_output_format>

<immediate_value>
**Why use dry-run:**

| Scenario | Without --dry-run | With --dry-run |
|----------|-------------------|----------------|
| Testing new feature | Creates real workspace | Shows what would be created |
| Debugging workflow | May corrupt state | Safe preview of operations |
| Learning commands | Trial and error cleanup | Zero-risk exploration |
| CI/CD validation | Real side effects | Validates without changes |
| Training/demos | Need fresh environment | Repeatable demonstrations |
</immediate_value>
</quick_start>

<workflow>
<step number="1">
**Detect dry-run flag**

At command start, check for `--dry-run` in arguments:

```markdown
### Step 0: Dry-Run Detection

Check for --dry-run flag:
```bash
DRY_RUN="false"
if [[ "$ARGUMENTS" == *"--dry-run"* ]]; then
  DRY_RUN="true"
  echo "DRY-RUN MODE ENABLED"
fi
```

If DRY_RUN is true:
- Initialize simulation log array
- Proceed with analysis but skip execution
- Collect all intended operations
```

**Important**: Remove `--dry-run` from arguments before parsing other flags to avoid conflicts.
</step>

<step number="2">
**Execute reads normally**

Read operations are safe and necessary for accurate simulation:

```markdown
**Safe operations (execute normally in dry-run):**
- Read tool: `Read file_path=...`
- Grep tool: `Grep pattern=...`
- Glob tool: `Glob pattern=...`
- Bash (read-only): `ls`, `cat`, `git status`, `git log`, `test -f`
- WebFetch: Documentation/API lookups
- WebSearch: Research queries

**Why**: Accurate simulation requires understanding current state.
```
</step>

<step number="3">
**Simulate write operations**

Intercept and log write operations without executing:

```markdown
**Write operations to simulate:**

**File writes** (Write tool):
```
Instead of: Write file_path="specs/001/spec.md" content="..."
Log: "WOULD CREATE: specs/001/spec.md (~150 lines)"
```

**File edits** (Edit tool):
```
Instead of: Edit file_path="state.yaml" old_string="..." new_string="..."
Log: "WOULD MODIFY: state.yaml (phase: init → spec)"
```

**Bash writes** (Bash tool with side effects):
```
Instead of: Bash command="mkdir -p specs/001"
Log: "WOULD EXECUTE: mkdir -p specs/001"

Instead of: Bash command="git commit -m '...'"
Log: "WOULD EXECUTE: git commit -m '...'"
```
```
</step>

<step number="4">
**Simulate agent spawns**

Log Task() calls without spawning:

```markdown
**Agent spawn simulation:**

Instead of:
```
Task tool call:
  subagent_type: "spec-phase-agent"
  description: "Execute spec phase"
  prompt: "..."
```

Log:
```
WOULD SPAWN AGENT:
  Type: spec-phase-agent
  Description: Execute spec phase
  Expected outputs: spec.md, updated state.yaml
```

**Why not spawn**: Agents perform real work. Dry-run must prevent cascading side effects.
```
</step>

<step number="5">
**Track state changes**

Analyze YAML state mutations:

```markdown
**State change tracking:**

Read current state.yaml, then log intended mutations:

```yaml
# Current state
phase: init
status: pending

# After command (simulated)
phase: spec
status: in_progress
phases:
  spec: completed
```

Log as:
```
STATE CHANGES (state.yaml):
  - phase: init → spec
  - status: pending → in_progress
  - phases.spec: (new) → completed
```
```
</step>

<step number="6">
*