refactor(wizard): cut the no-ops about time estimates

Telling the agent not to give minutes, in a template that has no
minutes, pays load to say nothing — and naming the banned behaviour
makes it more available, not less. The absence does the work.

- SKILL.md: drop the "never give a time estimate" paragraph and the
  "stage takes no duration" note; the example stage already shows it.
- template.sh: drop the two comments about not printing minutes.
- docs: drop the sentence about there being no estimate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Pocock
2026-08-06 14:56:50 +01:00
co-authored by Claude Opus 5
parent c0fd1e973e
commit cb7db0eeb6
4 changed files with 6 additions and 9 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
"mattpocock-skills": patch "mattpocock-skills": patch
--- ---
wizard: never give a time estimate. The template drops `TOTAL_MINUTES` and the time-remaining display, `stage` takes a name only, and progress is counted in stages. wizard: remove the time estimate. The template drops `TOTAL_MINUTES` and the time-remaining display, `stage` takes a name only, and progress is counted in stages.
+1 -1
View File
@@ -25,7 +25,7 @@ None to generate one. The wizard it writes runs on bash, and uses `gh` when a st
## Stages ## Stages
A **stage** is one focused task on one screen. The script clears the terminal between stages, so a stage that overflows the screen loses the part that scrolled away. You author stages in dependency order and set `TOTAL_STAGES`, which drives the progress display. There is no time estimate anywhere: progress is counted in stages, never in minutes. A **stage** is one focused task on one screen. The script clears the terminal between stages, so a stage that overflows the screen loses the part that scrolled away. You author stages in dependency order and set `TOTAL_STAGES`, which drives the progress display.
Scoping happens before a line is written. The [skill](https://www.aihero.dev/ai-coding-dictionary/skill) reads the repo instead of asking cold: `.env*`, `docker-compose*`, framework config, and every `secrets.*` / `vars.*` reference in `.github/workflows/` — each of those is a value the wizard has to produce. It then shows you the ordered stage list to confirm, and only after that maps each stage to the exact path a human follows ("Dashboard → Developers → API keys → Reveal test key → copy"). Where it doesn't know the current UI, it asks you or checks the docs rather than inventing clicks. Scoping happens before a line is written. The [skill](https://www.aihero.dev/ai-coding-dictionary/skill) reads the repo instead of asking cold: `.env*`, `docker-compose*`, framework config, and every `secrets.*` / `vars.*` reference in `.github/workflows/` — each of those is a value the wizard has to produce. It then shows you the ordered stage list to confirm, and only after that maps each stage to the exact path a human follows ("Dashboard → Developers → API keys → Reveal test key → copy"). Where it doesn't know the current UI, it asks you or checks the docs rather than inventing clicks.
+1 -3
View File
@@ -7,8 +7,6 @@ description: Generate an interactive bash wizard that walks a human through step
A **wizard** is a bash script that walks a human, step by step, through a manual procedure that's tedious to do by hand and tedious to re-explain to an AI every time. It opens each URL, says exactly what to click and copy, captures the values, writes them where they belong (`.env`, GitHub secrets), confirms at every stage, and shows how many stages are left. It might configure third-party services, run a one-off migration, or move the project from one state to another. A **wizard** is a bash script that walks a human, step by step, through a manual procedure that's tedious to do by hand and tedious to re-explain to an AI every time. It opens each URL, says exactly what to click and copy, captures the values, writes them where they belong (`.env`, GitHub secrets), confirms at every stage, and shows how many stages are left. It might configure third-party services, run a one-off migration, or move the project from one state to another.
**Never give a time estimate.** No minutes in the script, in the stage headers, or in what you tell the user — not for a stage, not for the wizard as a whole. Progress is measured in stages only.
The delightful UX is already solved by [template.sh](template.sh) — stage-by-stage progress, confirmation gates, cross-platform URL opening (including WSL), hidden secret entry, idempotent `.env` upserts, `gh secret`/`gh variable` writes, and a closing summary. **Your job is only to scope the procedure and author its stages.** The library above the `STAGES` marker is identical in every wizard; that consistency is the point — never hand-edit it. The delightful UX is already solved by [template.sh](template.sh) — stage-by-stage progress, confirmation gates, cross-platform URL opening (including WSL), hidden secret entry, idempotent `.env` upserts, `gh secret`/`gh variable` writes, and a closing summary. **Your job is only to scope the procedure and author its stages.** The library above the `STAGES` marker is identical in every wizard; that consistency is the point — never hand-edit it.
A wizard is ephemeral by default — built for one run, saved to a scratch or `scripts/` path, deleted when the job's done. Commit it only when the user wants a repeatable setup path that should live in the repo. A wizard is ephemeral by default — built for one run, saved to a scratch or `scripts/` path, deleted when the job's done. Commit it only when the user wants a repeatable setup path that should live in the repo.
@@ -34,7 +32,7 @@ For each stage, write the precise path a human follows: which URL to open, what
### 3. Author the wizard ### 3. Author the wizard
Copy `template.sh` to the target path. Replace the example stage with one `stage` per step, in dependency order. Use the library helpers — `stage`, `say`/`step`, `open_url`, `ask`/`ask_secret`, `write_env`, `set_secret`/`set_var`, `pause`/`confirm` — and set `TOTAL_STAGES` to the number of stages you wrote (this drives the progress display). Give `stage` a name only; it takes no duration. Copy `template.sh` to the target path. Replace the example stage with one `stage` per step, in dependency order. Use the library helpers — `stage`, `say`/`step`, `open_url`, `ask`/`ask_secret`, `write_env`, `set_secret`/`set_var`, `pause`/`confirm` — and set `TOTAL_STAGES` to the number of stages you wrote.
Hold the bar the template sets: open the URL before asking for its value, use `ask_secret` for anything secret, `write_env` every persisted value, `set_secret` only the values CI actually needs, and `confirm` before any irreversible action. Each `stage` clears the screen so only the current step is visible — keep a stage to one focused task so nothing the human needs scrolls away. Don't touch the library above the marker. Hold the bar the template sets: open the URL before asking for its value, use `ask_secret` for anything secret, `write_env` every persisted value, `set_secret` only the values CI actually needs, and `confirm` before any irreversible action. Each `stage` clears the screen so only the current step is visible — keep a stage to one focused task so nothing the human needs scrolls away. Don't touch the library above the marker.
+3 -4
View File
@@ -35,7 +35,7 @@ _clear() {
if command -v tput >/dev/null 2>&1; then tput clear; else printf '\033[2J\033[3J\033[H'; fi if command -v tput >/dev/null 2>&1; then tput clear; else printf '\033[2J\033[3J\033[H'; fi
} }
# banner "Title" — opening frame: what this wizard does. Never a time estimate. # banner "Title" — opening frame: what this wizard does.
banner() { banner() {
_clear _clear
printf '\n%s%s %s%s\n' "$BOLD" "$BLUE" "$1" "$RESET" printf '\n%s%s %s%s\n' "$BOLD" "$BLUE" "$1" "$RESET"
@@ -46,8 +46,8 @@ banner() {
pause "Ready to start?" pause "Ready to start?"
} }
# stage "Name" — clear the screen, then announce a stage and show progress as a # stage "Name" — clear the screen, then announce a stage and show progress.
# stage count. Clearing keeps only the current step on screen. # Clearing keeps only the current step on screen.
stage() { stage() {
_clear _clear
_STAGE_INDEX=$((_STAGE_INDEX + 1)) _STAGE_INDEX=$((_STAGE_INDEX + 1))
@@ -182,7 +182,6 @@ finish() {
# ────────────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────────────
# STAGES — author this section. One stage() per step the human takes. # STAGES — author this section. One stage() per step the human takes.
# Replace the example below. Set TOTAL_STAGES to match the stages you write. # Replace the example below. Set TOTAL_STAGES to match the stages you write.
# Never tell the human how many minutes anything takes.
# ────────────────────────────────────────────────────────────────────────── # ──────────────────────────────────────────────────────────────────────────
TOTAL_STAGES=1 TOTAL_STAGES=1