Files
Panama/user/agents/skills/wizard/SKILL.md
T
Gabriel Brown 89761a7da3 Keep the personal half of the desktop in one place, and ask before installing it
Agent instructions, skills, SSH host aliases and expansion triggers are worth
having identical on every machine one person owns, and belong in none of the
shared configuration. They live in user/ now, with a manifest saying where each
piece goes and a link-user stage that puts it there.

That stage does nothing unless the machine said yes. Somebody who clones Panama
to try the desktop keeps their own ~/.claude/CLAUDE.md exactly where it was;
the question names the destinations and defaults to no. Anything displaced goes
to config/old rather than being deleted.

~/.claude/CLAUDE.md and ~/.codex/AGENTS.md were byte-identical copies of one
file, which is the drift this exists to prevent.

Also adds the vitals toggles for the battery and Claude usage readouts, which
had preferences and no way to reach them.
2026-08-22 08:54:43 -04:00

102 lines
5.1 KiB
Markdown

---
name: wizard
description: Use when a procedure needs a human at the keyboard, meaning provisioning infrastructure, setting up credentials or CI secrets, clicking through an unfamiliar third-party dashboard, or running a one-off migration or cutover. Not for steps you can perform yourself.
---
# Wizard
A **wizard** is a bash script that walks a human, step by step, through a manual procedure that is
tedious to do by hand and tedious to re-explain to an agent every time. It opens each URL, says
exactly what to click and copy, captures the values, writes them where they belong, confirms before
anything irreversible, and shows how many stages are left.
The UX is already solved by [template.sh](template.sh): stage-by-stage progress, confirmation gates,
cross-platform URL opening, hidden secret entry, idempotent `.env` upserts, CI secret writes, and a
closing summary of what was set and what still needs doing by hand.
**Your job is only to scope the procedure and author its stages.** The library above the `STAGES`
marker is identical in every wizard, and that sameness is the point. Never hand-edit it.
A wizard is ephemeral by default: built for one run, saved to a scratch path or `scripts/`, deleted
when the job is done. Commit it only where the user wants a repeatable setup path living in the repo.
**Where you could just do it yourself, do it yourself.** This is for the steps where a human is
genuinely in the loop.
## 1. Scope the procedure
Work out every manual step the human must take and every value captured along the way. Read the repo
first rather than asking cold:
- **For setup**: `.env`, `.env.example`, `.env.*`, the README, `docker-compose*` or `Containerfile`,
framework config, and CI workflow files. Every `secrets.*` or `$CI_` reference is a value the wizard
must produce.
- **For a migration or cutover**: the current state, the target state, and every irreversible action
in between.
Then show the ordered list of stages and the values each produces, and confirm. They may add, drop,
or reorder.
**Done when**, for every captured value, you know where the human gets it, where it is written
(`.env`, a CI secret, Infisical, several of those, or nowhere for a pure action stage), and whether it
is secret and so needs hidden entry.
## 2. Map each stage's journey
For each stage, write the precise path a human follows: which URL, what to do there, where the value
is shown, which variable it fills.
> Dashboard → Developers → API keys → Reveal test key → copy
Where you do not actually know the current UI or the exact command, **say so and ask, or check the
docs.** Never invent steps that may not exist: a wizard confidently naming a button that is not there
is worse than no wizard, because the human trusts it.
**Done when** every stage traces to concrete instructions a stranger could follow.
## 3. Author it
Copy `template.sh` to the target path. Replace the example stage with one `stage` per step in
dependency order, and set `TOTAL_STAGES` to match.
Use the library helpers:
| Helper | Does |
|---|---|
| `stage "Name"` | Clears the screen, announces the stage, shows progress |
| `say` / `step` / `note` / `warn` | Instruction lines |
| `open_url URL` | Opens it in the human's browser |
| `ask KEY "Prompt"` / `ask_secret KEY "Prompt"` | Reads a value, hidden for secrets, offering the existing `.env` value on a re-run |
| `write_env KEY VALUE` | Idempotent upsert into `.env` |
| `set_secret` / `set_var` | Writes a CI secret or variable, detecting GitHub or GitLab from the git remote |
| `set_infisical KEY VALUE` | Writes to Infisical, honouring `INFISICAL_ENV` (default `dev`) |
| `pause` / `confirm` | Waits, or gates an irreversible action behind y/N |
Hold the bar the template sets: open the URL **before** asking for its value, `ask_secret` anything
secret, `write_env` every persisted value, `set_secret` only what CI actually needs, and `confirm`
before anything irreversible.
Each `stage` clears the screen, so keep a stage to one focused task and nothing the human still needs
scrolls away.
**Verify the CLI invocations you rely on.** `set_secret` degrades to a warning rather than failing,
so a wrong flag silently becomes a manual to-do. Where a stage depends on a `glab`, `gh`, or
`infisical` command, confirm the syntax against its `--help` before shipping.
## 4. Verify and hand off
- `bash -n <script>`, and `shellcheck` where it is installed
- `chmod +x <script>`
- **Do not run it end to end yourself.** It opens browsers and blocks on human input. Trace it
statically instead: every value from step 1 is captured, lands where step 1 said it would, and
every `set_secret` name exactly matches the reference in CI.
- Tell the user how to run it. Where it is a repeatable setup path, commit it and link it from the
README so the next person runs the script instead of asking an agent.
## Done when
- Every stage is a step only a human can take.
- Every captured value has a known source, a known destination, and correct secrecy.
- No step names a button or command you have not verified exists.
- The script passes `bash -n`, is executable, and was traced statically rather than run.