--- name: dry-run description: Preview command effects without making changes. Simulates file writes, git operations, agent spawns, and state changes. All reads execute normally for accurate preview. Use --dry-run flag on any command. --- 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. **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 ``` **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 ════════════════════════════════════════════════════════════════════════════════ ``` **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 | **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. **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. ``` **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 '...'" ``` ``` **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. ``` **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 ``` ``` **Output standardized summary** Format all collected operations: ```markdown **Summary template:** At command end, output: 1. **Header** with dry-run banner 2. **Files created** (new files that would be written) 3. **Files modified** (existing files that would change) 4. **Agents spawned** (Task() calls that would execute) 5. **Git operations** (commits, branches, pushes) 6. **State changes** (YAML mutations) 7. **Footer** with execution instructions Use consistent emoji prefixes: - 📁 Files created - 📝 Files modified - 🤖 Agents spawned - 🔀 Git operations - 📊 State changes ``` **Execute normally in dry-run mode:** | Operation | Tool | Why Safe | |-----------|------|----------| | Read file | Read | No side effects | | Search code | Grep | No side effects | | Find files | Glob | No side effects | | Check status | Bash (git status) | Read-only | | View logs | Bash (git log) | Read-only | | Test existence | Bash (test -f) | Read-only | | List files | Bash (ls) | Read-only | | Fetch docs | WebFetch | Read-only | | Search web | WebSearch | Read-only | **All reads provide accurate context for simulation.** **Simulate (log but don't execute) in dry-run mode:** | Operation | Tool | Simulation Output | |-----------|------|-------------------| | Create file | Write | "WOULD CREATE: path (~N lines)" | | Edit file | Edit | "WOULD MODIFY: path (old → new)" | | Make directory | Bash (mkdir) | "WOULD EXECUTE: mkdir ..." | | Git commit | Bash (git commit) | "WOULD EXECUTE: git commit ..." | | Git branch | Bash (git checkout -b) | "WOULD EXECUTE: git checkout -b ..." | | Git push | Bash (git push) | "WOULD EXECUTE: git push ..." | | Run script | Bash (python/node) | "WOULD EXECUTE: python ..." | | Spawn agent | Task | "WOULD SPAWN: agent-type" | | Ask user | AskUserQuestion | "WOULD ASK: question text" | **All writes are logged with expected effects.** **Execute carefully in dry-run mode:** | Operation | Approach | |-----------|----------| | State validation | Run validation, report errors | | Prerequisite checks | Execute checks, report status | | File existence checks | Execute, use result for simulation | | Git status queries | Execute, use for accurate preview | **Some operations need execution for accurate simulation while being side-effect-free.** **Standard pattern for command integration:** Add to command frontmatter: ```yaml --- argument-hint: "[args] [--dry-run]" --- ``` Add to command process section: ```markdown ### Step 0: Mode Detection **Detect dry-run mode:** ```bash DRY_RUN="false" CLEAN_ARGS="$ARGUMENTS" if [[ "$ARGUMENTS" == *"--dry-run"* ]]; then DRY_RUN="true" CLEAN_ARGS=$(echo "$ARGUMENTS" | sed 's/--dry-run//g' | xargs) echo "═══════════════════════════════════════════════════════════════════" echo "DRY-RUN MODE: No changes will be made" echo "═══════════════════════════════════════════════════════════════════" fi ``` **Initialize simulation log (if dry-run):** If DRY_RUN is true, initialize arrays: - FILES_CREATED=() - FILES_MODIFIED=() - AGENTS_SPAWNED=() - GIT_OPERATIONS=() - STATE_CHANGES=() ``` Add before each operation: ```markdown If DRY_RUN is true: Log operation to appropriate array Skip execution Else: Execute operation normally ``` Add at command end: ```markdown ### Final Step: Dry-Run Summary (if applicable) If DRY_RUN is true: Output dry-run summary using format from skill Exit without actual changes ``` **Example: /feature command integration:** ```markdown ### Step 0: Mode Detection **Detect flags:** ```bash DRY_RUN="false" DEEP_MODE="false" CLEAN_ARGS="$ARGUMENTS" if [[ "$ARGUMENTS" == *"--dry-run"* ]]; then DRY_RUN="true" CLEAN_ARGS=$(echo "$CLEAN_ARGS" | sed 's/--dry-run//g') fi if [[ "$ARGUMENTS" == *"--deep"* ]]; then DEEP_MODE="true" CLEAN_ARGS=$(echo "$CLEAN_ARGS" | sed 's/--deep//g') fi CLEAN_ARGS=$(echo "$CLEAN_ARGS" | xargs) # Trim whitespace ``` ### Step 1.1: Initialize Feature Workspace If DRY_RUN is true: ``` Log: "WOULD CREATE: specs/NNN-feature-slug/state.yaml" Log: "WOULD CREATE: specs/NNN-feature-slug/NOTES.md" Log: "WOULD EXECUTE: python .spec-flow/scripts/spec-cli.py feature '...'" ``` Skip actual execution Else: Execute normally ``` **Input**: `/feature "add user dashboard" --dry-run` **Output**: ``` ════════════════════════════════════════════════════════════════════════════════ DRY-RUN MODE: No changes will be made ════════════════════════════════════════════════════════════════════════════════ 📁 FILES THAT WOULD BE CREATED: ✚ specs/005-add-user-dashboard/state.yaml ✚ specs/005-add-user-dashboard/NOTES.md ✚ specs/005-add-user-dashboard/interaction-state.yaml ✚ specs/005-add-user-dashboard/domain-memory.yaml ✚ specs/005-add-user-dashboard/spec.md (after spec-phase-agent) ✚ specs/005-add-user-dashboard/plan.md (after plan-phase-agent) ✚ specs/005-add-user-dashboard/tasks.md (after tasks-phase-agent) 🤖 AGENTS THAT WOULD BE SPAWNED: 1. initializer → Initialize domain memory for feature 2. spec-phase-agent → Generate specification 3. clarify-phase-agent → Resolve ambiguities 4. plan-phase-agent → Create implementation plan 5. tasks-phase-agent → Break down into TDD tasks 6. worker (N times) → Implement each feature atomically 7. optimize-phase-agent → Run quality gates 8. ship-staging-phase-agent → Deploy to staging 9. finalize-phase-agent → Archive and document 🔀 GIT OPERATIONS THAT WOULD OCCUR: • git checkout -b feature/005-add-user-dashboard • git add specs/005-add-user-dashboard/ • git commit (multiple, after each phase) • git push origin feature/005-add-user-dashboard 📊 WORKFLOW PHASES: init → spec → clarify → plan → tasks → implement → optimize → ship → finalize ════════════════════════════════════════════════════════════════════════════════ DRY-RUN COMPLETE: 0 actual changes made Run `/feature "add user dashboard"` to execute these operations ════════════════════════════════════════════════════════════════════════════════ ``` **Input**: `/implement --dry-run` **Output**: ``` ════════════════════════════════════════════════════════════════════════════════ DRY-RUN MODE: No changes will be made ════════════════════════════════════════════════════════════════════════════════ 📋 CURRENT STATE: Feature: specs/004-auth-system/ Phase: implement Tasks remaining: 8 of 12 📝 FILES THAT WOULD BE MODIFIED: ✎ specs/004-auth-system/domain-memory.yaml - features[F001].status: pending → completed - features[F002].status: pending → in_progress ✎ specs/004-auth-system/state.yaml - phase: implement (unchanged during execution) ✎ src/services/auth.ts (implementation) ✎ src/services/auth.test.ts (tests) ✎ src/routes/login.ts (implementation) ✎ src/routes/login.test.ts (tests) 🤖 AGENTS THAT WOULD BE SPAWNED: 1. worker → Implement F001: User login endpoint 2. worker → Implement F002: Session management 3. worker → Implement F003: Password validation 4. worker → Implement F004: Token refresh (... 4 more workers for remaining features) 🔄 TDD CYCLE PER TASK: For each worker: 1. Write failing tests 2. Implement feature 3. Verify tests pass 4. Update domain-memory.yaml 5. Commit changes ════════════════════════════════════════════════════════════════════════════════ DRY-RUN COMPLETE: 0 actual changes made Run `/implement` to execute 8 remaining tasks ════════════════════════════════════════════════════════════════════════════════ ``` **Input**: `/ship --staging --dry-run` **Output**: ``` ════════════════════════════════════════════════════════════════════════════════ DRY-RUN MODE: No changes will be made ════════════════════════════════════════════════════════════════════════════════ 📋 PRE-FLIGHT CHECKS (would execute): ✓ Build verification ✓ Test suite (127 tests) ✓ Type checking ✓ Security scan ✓ Environment variables 🔀 GIT OPERATIONS THAT WOULD OCCUR: • git push origin feature/004-auth-system • gh pr create --base staging --head feature/004-auth-system • Wait for CI to pass • gh pr merge --auto 📦 DEPLOYMENT THAT WOULD OCCUR: • Merge to staging branch triggers deploy-staging.yml • Vercel/Railway builds from staging • Health check endpoints verified • Deployment URL: https://staging.example.com (estimated) 📊 STATE CHANGES: state.yaml: - phases.ship: pending → completed - deployment.staging.status: pending → deployed - deployment.staging.pr_number: (new) → #42 🤖 AGENTS THAT WOULD BE SPAWNED: 1. ship-staging-phase-agent → Execute staging deployment ════════════════════════════════════════════════════════════════════════════════ DRY-RUN COMPLETE: 0 actual changes made Run `/ship --staging` to deploy to staging environment ════════════════════════════════════════════════════════════════════════════════ ``` **Input**: `/quick "fix typo in README" --dry-run` **Output**: ``` ════════════════════════════════════════════════════════════════════════════════ DRY-RUN MODE: No changes will be made ════════════════════════════════════════════════════════════════════════════════ 📋 TASK ANALYSIS: Type: Documentation fix Scope: Single file Estimated changes: <10 lines 📝 FILES THAT WOULD BE MODIFIED: ✎ README.md (typo fix) 🔀 GIT OPERATIONS THAT WOULD OCCUR: • git add README.md • git commit -m "docs: fix typo in README" 🤖 AGENTS THAT WOULD BE SPAWNED: 1. quick-worker → Execute atomic change with tests ════════════════════════════════════════════════════════════════════════════════ DRY-RUN COMPLETE: 0 actual changes made Run `/quick "fix typo in README"` to execute ════════════════════════════════════════════════════════════════════════════════ ``` **Problem**: Accidentally executing write operations in dry-run mode **Bad approach**: ```markdown If DRY_RUN: echo "Would write file" Write file... # WRONG: Executes regardless of dry-run! ``` **Correct approach**: ```markdown If DRY_RUN: Log: "WOULD CREATE: file.md" Else: Write file_path="file.md" content="..." ``` **Rule**: Always wrap write operations in dry-run conditional. **Problem**: Spawning Task() agents defeats dry-run purpose **Bad approach**: ```markdown If DRY_RUN: echo "Would spawn agent" Task(spec-phase-agent) # WRONG: Agent runs and makes changes! ``` **Correct approach**: ```markdown If DRY_RUN: Log: "WOULD SPAWN: spec-phase-agent" Log: "Expected outputs: spec.md" Else: Task(spec-phase-agent) ``` **Rule**: Never spawn agents in dry-run mode. **Problem**: Missing operations from dry-run output **Bad approach**: ```markdown DRY-RUN OUTPUT: Would create spec.md # Missing: state.yaml changes, git operations, other files ``` **Correct approach**: ```markdown DRY-RUN OUTPUT: FILES CREATED: spec.md, state.yaml, NOTES.md FILES MODIFIED: state.yaml (phase: init → spec) GIT OPERATIONS: checkout -b, add, commit AGENTS: spec-phase-agent, clarify-phase-agent ``` **Rule**: Log ALL operations that would occur. **Problem**: Skipping reads makes simulation inaccurate **Bad approach**: ```markdown If DRY_RUN: Skip reading state.yaml # WRONG: Can't accurately simulate! Guess at current state ``` **Correct approach**: ```markdown # Always read current state (safe operation) STATE=$(cat specs/NNN/state.yaml) CURRENT_PHASE=$(yq eval '.phase' ...) If DRY_RUN: Log: "Current phase: $CURRENT_PHASE → would transition to: spec" ``` **Rule**: Execute reads for accurate simulation context. Dry-run implementation is correct when: 1. **Zero side effects**: No files created/modified, no git operations, no agents spawned 2. **Accurate preview**: All intended operations listed in output 3. **Consistent format**: Standard output format across all commands 4. **Readable output**: Clear emoji prefixes, organized sections 5. **Actionable**: Output tells user how to execute for real 6. **Complete**: Shows files, agents, git ops, state changes Before considering dry-run implementation complete: - [ ] --dry-run flag detected and removed from arguments - [ ] All Write tool calls wrapped in dry-run conditional - [ ] All Edit tool calls wrapped in dry-run conditional - [ ] All Task() calls wrapped in dry-run conditional - [ ] All Bash writes (mkdir, git commit, etc.) wrapped - [ ] Read operations execute normally for context - [ ] Output uses standard format with emoji prefixes - [ ] Output includes all operation categories - [ ] Output shows how to run without dry-run - [ ] No actual changes occur in dry-run mode **Commands that support --dry-run flag:** | Command | Dry-run shows | |---------|---------------| | `/feature` | Workspace creation, all phases, agents | | `/epic` | Epic workspace, sprint planning, parallel execution | | `/quick` | Quick fix changes, commit | | `/plan` | Plan.md creation, research | | `/tasks` | Tasks.md generation | | `/implement` | Worker spawns, file changes, tests | | `/optimize` | Quality gate execution, reports | | `/ship` | Deployment operations, PR creation | | `/finalize` | Archival, cleanup, documentation | **Usage**: Add `--dry-run` to any command: ```bash /feature "add auth" --dry-run /implement --dry-run /ship --staging --dry-run ``` The dry-run skill is successfully applied when: 1. **Flag detection**: `--dry-run` recognized by command 2. **Zero execution**: No files created, modified, or deleted 3. **No agents spawned**: Task() calls logged but not executed 4. **No git changes**: No commits, branches, or pushes 5. **Accurate preview**: All operations that WOULD occur are listed 6. **Standard format**: Consistent output format with clear sections 7. **Actionable output**: User knows how to run command for real 8. **Safe exploration**: Users can test any command without risk 9. **CI/CD ready**: Can validate commands in automation pipelines 10. **Repeatable**: Same dry-run produces same output (deterministic)