How Can a Command-Line Tool Support a Dry Run?
From the earlier reference collection. Read the current software blog.
A dry run should report the changes a command would make while preventing file writes and external requests.
Define the boundary clearly
A dry run is useful only when its promise is precise. State which effects are suppressed: file creation, replacement, deletion, network requests, or all of these. Users should not have to guess whether --dry-run merely avoids the final write while still contacting a remote service or modifying a cache.
For an import command, a useful dry run might read a local archive, validate its structure, and report the planned destination without creating or replacing output files. If checking the remote source itself would require a request, make clear whether dry run avoids that request too.
Separate planning from execution
Structure the command as two stages. First build a plan: identify inputs, validate options, determine intended outputs, and collect actions. Then pass that plan to an execution step that performs side effects only when dry run is disabled. This reduces the chance that a validation helper quietly writes a temporary file before the command reaches its dry-run check.
For example, the plan might report: Would replace cache/stops.csv using feed.zip; 3 tables selected. In execution mode, the same plan drives the actual replacement. Keeping the plan shared means the preview describes the action the program is designed to perform.
Show meaningful details without pretending
A dry-run summary should name relevant paths, counts, and decisions, while avoiding claims that depend on an action the command did not perform. If the tool has not made a network request, it cannot truthfully report the remote file’s current checksum. If it has not opened an output file, it cannot promise that the destination is writable.
Use wording such as would download and would replace, rather than success language. Return an appropriate status for validation errors even in dry-run mode; suppressing side effects should not suppress detection of a bad plan.
Verify the guarantee
Run a dry-run example in a disposable directory and compare its contents before and after. Inspect network behavior if the contract says the command makes no external requests. The output should clearly state that it is a preview, and tests or operational checks should cover the side effects the promise excludes.
A trustworthy dry run is more than an extra flag. It gives the operator a reviewable account of intended changes, uses the same planning logic as execution, and keeps its guarantees narrow enough to verify.