cli-wizard-pattern
Add an opt-in interactive wizard mode to an existing script, CLI, or Taskfile task, or build a new script whose required arguments are supplied by the user at run time. Use when the user asks to add i
SKILL.mdskills/cli-wizard-pattern/SKILL.md
GitHubCLI Wizard Pattern
Add a guided, opt-in wizard to a command so a human can select values instead of memorizing flags, without changing how automation calls that command.
When to Use
- Add
-i/--interactiveto an existing script or Taskfile task. - Build a new script whose required arguments come from the user.
- Convert free-text prompts into numbered selection menus.
Not for steps only a human can perform against a third party (use the wizard
skill for those); this skill is about a command's own argument surface.
Core Principles
1. Opt-in, never auto-detected
Interactive mode MUST require an explicit flag. Never fall back to interactive mode when required arguments are missing.
Why: agents and CI run commands with no arguments to probe behavior. If a missing argument silently launches a wizard, the process hangs on a prompt that nothing will ever answer. Fail fast instead.
| Invocation | Behavior |
|---|---|
cmd (no args, missing required) |
Exit non-zero with a usage error |
cmd -i |
Launch the wizard |
cmd --branch foo |
Non-interactive, unchanged |
2. Prefer numbered menus over free text
Every value the tool can compute MUST be offered as a numbered selection. Free text is the last resort, reserved for values that cannot be enumerated.
Why: menus are discoverable, typo-proof, and testable. Free text makes users guess valid values and forces the parser to validate arbitrary input.
Discover options from the environment before prompting: list registered worktrees, local branches, remotes, available databases, installed SDKs, known environments, files matching a pattern. If the set is empty, fail with guidance rather than prompting for a value the user cannot know.
3. Offer escape hatches and safe defaults
- Binary choices render as
1. Yes/2. Nowith the default marked. - Any enumerable list that may legitimately be absent (a remote to fetch, an
optional scope) gets an explicit
(skip)/(none)entry. - Blank input accepts the documented default.
4. Confirm before mutating
After gathering inputs, print a summary of every resolved value and ask for a final yes/no. This is the user's last chance to catch a wrong selection before an irreversible operation runs.
5. Cancel cleanly at any step
An interruption at any prompt MUST exit without side effects and without a
non-zero error. Provide a quit token (q) on selection prompts and treat a
declined confirmation as a clean cancel.
6. Gather args, then reuse the existing path
The wizard resolves values into the command's normal parameters and then calls the unchanged non-interactive logic. Do not fork the core operation.
Why: one execution path means one place for bugs, and the non-interactive path stays provably intact.
Transformation Workflow
Inventory the argument surface. List every required and optional parameter. Classify each as enumerable (can be discovered) or free-form (must be typed). Decide which need prompts.
Add the opt-in flag. Introduce a boolean interactive switch, aliased to
-i. Keep it mutually exclusive with the identification arguments where the parameter system supports sets. Do not make existing required parameters mandatory in a way that blocks the flag from being reached.Build the wizard. For each parameter, in dependency order:
- Discover candidate values from the environment.
- Render a numbered menu (or typed prompt when unavoidable).
- Validate the selection inside a loop; never trust a single read.
- Assign the resolved value to the parameter the core path already reads.
Print a confirmation summary and gate the run behind a yes/no.
Wire the task runner (if a Taskfile or wrapper invokes the script). Add a pass-through variable and forward the flag conditionally. Ensure the runner does not force a non-interactive shell mode that would break prompting.
Test both paths. Verify the non-interactive path is byte-for-byte unchanged, and exercise the wizard's cancellation and confirmation gates.
Testing Checklist
- Non-interactive invocation with full args behaves exactly as before.
- Invocation with missing required args and no flag fails fast (no prompt).
- Wizard: every menu renders the discovered options; invalid input re-prompts.
- Wizard: quitting at each prompt exits 0 with no side effects.
- Wizard: declining the confirmation exits 0 with no side effects.
- Wizard: empty option sets produce a clear error, not an empty menu.
Anti-Patterns
| Anti-pattern | Why it fails |
|---|---|
| Auto-entering interactive mode when args are missing | Hangs agents and CI on an unanswerable prompt |
| Free-text prompts for values that can be enumerated | Typos reach the operation; users guess valid inputs |
| Changing the non-interactive path's behavior | Breaks automation and scripted callers |
| Prompting without a final confirmation | A wrong menu pick executes an irreversible operation |
| Assuming a single discovered value is an array/collection | Single-result collections break count/size checks |
| Exiting non-zero on a user-initiated cancel | Cancel is a valid outcome, not an error |
Language References
- PowerShell / Taskfile:
references/powershell-pattern.md — ready-to-adapt
helper functions for numbered menus, yes/no selection, confirmation summaries,
array-safe discovery, the
-Interactiveparameter block, and Taskfile wiring.
Add a sibling reference file (for example references/python-pattern.md) when
another language's implementation is needed; keep this guide as the single home
for the principles above.