---
title: "Show a dry run and ask before destructive · Agent Wranglers"
url: https://agentwranglers.se/playbook/desktop-apps/command-line-tools/dry-run
id: DSK-25
level: Recommended
updated: 2026-10-22
tokens: 925
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Show a dry run and ask before destructive commands

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Command-line tools](https://agentwranglers.se/playbook/desktop-apps/command-line-tools.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: DSK-25
- Level: Recommended
- Chapter: [Command-line tools](https://agentwranglers.se/playbook/desktop-apps/command-line-tools.md)
- Rule: Give every command that deletes, overwrites or sends something a `--dry-run` flag that lists what it would do. Ask for confirmation before it acts, unless `--yes` is passed.
- Check: A test runs each destructive command with `--dry-run` on a test copy, and nothing changes. The list it printed matches what the same command then changes with `--yes`.
- How: Agents and tired people run commands they meant to check first. A dry run shows the exact list of records, files or messages, with a count. Make the dry run use the same code path as the action, so the list matches what happens. Without a terminal, the confirmation follows [never wait for input when no person is there](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/non-interactive-mode.md). Infrastructure tools follow the same idea with a plan, as [review the plan and apply only from CI](https://agentwranglers.se/playbook/infrastructure/infrastructure-as-code/plan-in-review.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Python example

```python
def delete_drafts(older_than_days: int, dry_run: bool, assume_yes: bool) -> None:
    drafts = invoices.drafts_older_than(older_than_days)
    for draft in drafts:
        print(f"would delete {draft.number}" if dry_run else f"deleting {draft.number}", file=sys.stderr)
    if dry_run or not confirm(f"Delete {len(drafts)} drafts?", assume_yes):
        return
    invoices.delete_many([d.id for d in drafts])
```

### Go example

```go
func deleteDrafts(olderThanDays int, dryRun, assumeYes bool) error {
	drafts := invoices.DraftsOlderThan(olderThanDays)
	for _, d := range drafts {
		fmt.Fprintf(os.Stderr, "would delete %s\n", d.Number)
	}
	if dryRun || !confirm(fmt.Sprintf("Delete %d drafts?", len(drafts)), assumeYes) {
		return nil
	}
	return invoices.DeleteMany(ids(drafts))
}
```

## Related rules

- DSK-23 [Never wait for input when no person is there](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/non-interactive-mode.md) in Desktop apps, extensions and CLIs
- INF-3 [Review the plan and apply only from CI](https://agentwranglers.se/playbook/infrastructure/infrastructure-as-code/plan-in-review.md) in Infrastructure and environments

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/desktop-apps/command-line-tools/dry-run">Agent Wranglers desktop apps, extensions and CLIs playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Take secrets from the environment or a file instead of a flag](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/no-secrets-in-flags.md)
- Next: [Give every command help with an example and a version flag](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/cli-help.md)
- [Command-line tools](https://agentwranglers.se/playbook/desktop-apps/command-line-tools.md)
