Shell Confirm Hygiene
The default is to run commands directly. Pausing is the exception, not the rule — but when in doubt, pause once.
Pause for confirmation when any of these hold
- Destructive / irreversible:
rm -rf, git push --force, git reset --hard, DROP TABLE, deleting branches, mass file deletes, docker system prune -a.
- Modifies state outside the working tree: installs/uninstalls, system config, env vars on a host,
git config (global), changing shared resources.
- Network egress with side effects: deploys, publishes (
npm publish), webhook calls, anything hitting a production API.
- Shell expansion / subexpressions: commands containing
$(), backticks, Invoke-Expression, or dynamic argument construction where input could expand unexpectedly. The risk is hidden injection, not the command itself.
- Crosses a trust boundary: runs downloaded code, executes a file the user did not author, shells out to a remote script.
- First occurrence of a command shape you'll repeat many times — confirm once so the user can allowlist the shape; subsequent identical runs stay silent.
cd combined with a path-bearing operation. A leading cd can relocate the effective working directory before a subsequent path resolves, so the path the user reads and the path actually used can diverge. This is a distinct risk class from raw subexpression injection — treat compound cd <dir>; <uses-a-path> as its own confirm trigger.
Do NOT pause for
- Read-only inspection:
ls, cat, git status, git log, git diff, Get-PSDrive, Measure-Object, df, find, rg.
- Builds, tests, linters, formatters — these are reversible and expected.
- Edits inside the working tree you were already asked to make.
- Commands the user explicitly typed or approved in their message.
How to pause
State in one line: what the command does and the one concrete risk. Offer: proceed / proceed and don't ask again for this shape / cancel. Don't lecture; the user already knows the command.
After a "don't ask again" approval
Record the allowed shape mentally by its command head + intent (e.g. "Get-PSDrive C with Measure-Object count"). Re-prompt only if a later call adds a materially riskier operation (network, delete) on top.
Principle
Every pause costs flow. Every skipped pause on a risky command costs trust. Bias toward pausing on the first risky occurrence of a shape, then let the allowlist carry the repetition.
1---2name: shell-confirm-hygiene3description: Decide when to pause for user confirmation before running a shell command, and how to keep flow afterward. Use before running commands that are destructive, irreversible, cross trust boundaries, contain shell expansion/subexpressions, touch the network, or modify state outside the working tree.4---56# Shell Confirm Hygiene78The default is to run commands directly. Pausing is the exception, not the rule — but when in doubt, pause once.910## Pause for confirmation when any of these hold1112- **Destructive / irreversible:** `rm -rf`, `git push --force`, `git reset --hard`, `DROP TABLE`, deleting branches, mass file deletes, `docker system prune -a`.13- **Modifies state outside the working tree:** installs/uninstalls, system config, env vars on a host, `git config` (global), changing shared resources.14- **Network egress with side effects:** deploys, publishes (`npm publish`), webhook calls, anything hitting a production API.15- **Shell expansion / subexpressions:** commands containing `$()`, backticks, `Invoke-Expression`, or dynamic argument construction where input could expand unexpectedly. The risk is hidden injection, not the command itself.16- **Crosses a trust boundary:** runs downloaded code, executes a file the user did not author, shells out to a remote script.17- **First occurrence of a command shape you'll repeat many times** — confirm once so the user can allowlist the shape; subsequent identical runs stay silent.18- **`cd` combined with a path-bearing operation.** A leading `cd` can relocate the effective working directory before a subsequent path resolves, so the path the user reads and the path actually used can diverge. This is a distinct risk class from raw subexpression injection — treat compound `cd <dir>; <uses-a-path>` as its own confirm trigger.1920## Do NOT pause for2122- Read-only inspection: `ls`, `cat`, `git status`, `git log`, `git diff`, `Get-PSDrive`, `Measure-Object`, `df`, `find`, `rg`.23- Builds, tests, linters, formatters — these are reversible and expected.24- Edits inside the working tree you were already asked to make.25- Commands the user explicitly typed or approved in their message.2627## How to pause2829State in one line: what the command does and the one concrete risk. Offer: proceed / proceed and don't ask again for this shape / cancel. Don't lecture; the user already knows the command.3031## After a "don't ask again" approval3233Record the allowed shape mentally by its command head + intent (e.g. "Get-PSDrive C with Measure-Object count"). Re-prompt only if a later call adds a materially riskier operation (network, delete) on top.3435## Principle3637Every pause costs flow. Every skipped pause on a risky command costs trust. Bias toward pausing on the first risky occurrence of a shape, then let the allowlist carry the repetition.