In praise of –dry-run

Default behavior: dry vs. “really do it”

  • Many prefer tools to default to safe/no-op and require an explicit --commit / --execute / --really flag to make changes, especially for high‑impact scripts (DB, APIs, mass updates).
  • Others argue most everyday commands (e.g., rm, cp) should default to doing the thing, with safety handled by filesystem snapshots or selective safeguards (--no-preserve-root, interactive prompts only in dangerous cases).
  • Several people bias their own custom tools to default to dry‑run, adding flags like --no-dry-run, --live-run, or humorous variants (--safety-off, --make-it-so).

Implementation patterns and code structure

  • A common concern is avoiding if dry_run: checks scattered everywhere. Proposed solutions:
    • Inject “persistence strategies” or use builders so writes can be swapped for logging.
    • “Functional core, imperative shell”: core produces a list of actions; a single executor either logs or performs them.
    • Use database transactions: run everything normally but roll back on dry‑run.
  • Some tooling wraps REST calls or writes in a single layer so dry‑run affects only that layer.

Safety UX: confirmations and friction

  • Techniques include countdown timers, requiring typing a random code or phrase, or using parameters like --yes-delete-all-data-in=... to bind intent to a specific system.
  • Tools such as molly‑guard or tarsnap’s “type this phrase to continue” are cited as real‑world examples.
  • Several commenters note that repeated confirmations get automated away by users; true safety often requires easy undo (snapshots, versioned filesystems) rather than only extra prompts.

Limitations and nuances of dry‑run

  • A dry‑run can diverge from reality if it doesn’t exercise all hot‑path logic; it should do everything except the final side effects.
  • Race conditions: state can change between dry‑run and real run. Terraform‑style “plan then apply” with a persisted plan is praised as a stronger pattern, though some argue this can devolve into designing a mini DSL/VM.

Ecosystem and tooling

  • Examples: PowerShell’s built‑in -WhatIf / -Confirm, internal migration frameworks, CI jobs parameterized with DRY_RUN, and preview/no‑clobber flags.
  • Some mention roll‑your‑own approaches (aliases, diff-based previews, OverlayFS/Docker) when tools lack dry‑run.

Agents and convergence

  • Multiple people observe that code‑generation tools and LLMs now routinely add --dry-run options by default, potentially standardizing CLI patterns across projects.