Setup Zsl Superpowers¶
Bucket: Engineering ·
Slash command: /zsl:setup-zsl-superpowers ·
Source: skills/engineering/setup-zsl-superpowers/SKILL.md
User-invocable only
This skill is marked disable-model-invocation: true — Claude won't auto-trigger it, so you must invoke it explicitly with the slash command above.
What it does¶
Sets up an ## Agent skills block in AGENTS.md/CLAUDE.md and docs/agents/ so the engineering skills know this repo's issue tracker (GitHub, local markdown, or a hybrid local-markdown-plus-GitHub-mirror), triage label vocabulary, domain doc layout, ship style (PR vs direct push), and — optionally — the remote claude.ai environment the overnight agent loop schedules into. Run before first use of to-issues, to-prd, triage, diagnose, tdd, or improve-codebase-architecture — or if those skills appear to be missing context about the issue tracker, triage labels, domain docs, ship style, or remote agent environment.
Scaffold the per-repo configuration that the engineering skills assume:
- Issue tracker — where issues live (GitHub by default; local markdown is also supported out of the box)
- Triage labels — the strings used for the six canonical triage roles
- Domain docs — where
CONTEXT.mdand ADRs live, and the consumer rules for reading them - Ship style — how changes reach the default branch (pull request or direct push)
- Project board (optional) — a GitHub Projects v2 board whose
Statuscolumn should mirror triage labels and tdd lifecycle - Remote agent environment (optional) — the claude.ai Claude Code environment id the overnight loop (
/afk-fanout,/afk-worker) schedules remote sessions into
This is a prompt-driven skill, not a deterministic script. Explore, present what you found, confirm with the user, then write.
Process¶
1. Explore¶
Look at the current repo to understand its starting state. Read whatever exists; don't assume:
git remote -vand.git/config— is this a GitHub repo? Which one?AGENTS.mdandCLAUDE.mdat the repo root — does either exist? Is there already an## Agent skillssection in either?CONTEXT.mdandCONTEXT-MAP.mdat the repo rootdocs/adr/and anysrc/*/docs/adr/directoriesdocs/agents/— does this skill's prior output already exist?.scratch/— sign that a local-markdown issue tracker convention is already in use
2. Present findings and ask¶
Summarise what's present and what's missing. Then walk the user through the decisions one at a time — present a section, get the user's answer, then move to the next. Don't dump them all at once. Sections A–D are core; E (project board) and F (remote agent environment) are optional.
Assume the user does not know what these terms mean. Each section starts with a short explainer (what it is, why these skills need it, what changes if they pick differently). Then show the choices and the default.
Section A — Issue tracker.
Explainer: The "issue tracker" is where issues live for this repo. Skills like
to-issues,triage,to-prd, andqaread from and write to it — they need to know whether to callgh issue create, write a markdown file under.scratch/, or follow some other workflow you describe. Pick the place you actually track work for this repo.
Default posture: these skills were designed for GitHub. If a git remote points at GitHub, propose that. If a git remote points at GitLab (gitlab.com or a self-hosted host), propose GitLab. Otherwise (or if the user prefers), offer:
- GitHub — issues live in the repo's GitHub Issues (uses the
ghCLI) - GitLab — issues live in the repo's GitLab Issues (uses the
glabCLI) - Local markdown — issues live as files under
.scratch/<NNN>-<feature-slug>/in this repo (<NNN>is an auto-assigned 3-digit feature number; good for solo projects or repos without a remote) - Hybrid (local markdown + GitHub mirror) — issues live in
.scratch/as the source of truth, but each is mirrored to a thin linked GitHub issue so it can appear on a project board (Section E). Pick this when you want.scratch/ergonomics and a board — a board can only track GitHub-native objects, so plain local-markdown issues can't appear on one (see the coupling note below). Uses the issue-tracker-hybrid.md seed. - Other (Jira, Linear, etc.) — ask the user to describe the workflow in one paragraph; the skill will record it as freeform prose
Tracker ↔ board coupling. A GitHub Projects v2 board (Section E) tracks items by their GitHub node ID. GitHub and GitLab() trackers have native issues to put on a board; Local markdown issues are files with no node ID, so they cannot appear on a board directly. If the user wants both local-markdown and a board, that's exactly the Hybrid option — don't quietly skip Section E, offer the hybrid. (GitLab boards are out of scope here; Section E is GitHub Projects v2.)
Section B — Triage label vocabulary.
Explainer: When the
triageskill processes an incoming issue, it moves it through a state machine — needs evaluation, waiting on reporter, ready for an AFK agent to pick up, ready for a human, a tracking container for sub-issues, or won't fix. To do that, it needs to apply labels (or the equivalent in your issue tracker) that match strings you've actually configured. If your repo already uses different label names (e.g.bug:triageinstead ofneeds-triage), map them here so the skill applies the right ones instead of creating duplicates.
The six canonical roles:
needs-triage— maintainer needs to evaluateneeds-info— waiting on reporterready-for-agent— fully specified, AFK-ready (an agent can pick it up with no human context)ready-for-human— needs human implementationtracking— container/parent issue (e.g. PRD) — work lives in sub-issueswontfix— will not be actioned
Default: each role's string equals its name. Ask the user if they want to override any. If their issue tracker has no existing labels, the defaults are fine.
Section C — Domain docs.
Explainer: Some skills (
improve-codebase-architecture,diagnose,tdd) read aCONTEXT.mdfile to learn the project's domain language, anddocs/adr/for past architectural decisions. They need to know whether the repo has one global context or multiple (e.g. a monorepo with separate frontend/backend contexts) so they look in the right place.
Confirm the layout:
- Single-context — one
CONTEXT.md+docs/adr/at the repo root. Most repos are this. - Multi-context —
CONTEXT-MAP.mdat the root pointing to per-contextCONTEXT.mdfiles (typically a monorepo).
Section D — Ship style.
Explainer: When a skill like
tddfinishes a change, it needs to know how to get that change to the default branch. Team projects almost always go through pull requests; solo projects often push direct. This affects whether the skill creates a feature branch, opens a PR with a closing keyword, or commits straight to the default branch and closes the issue explicitly.
- Pull request — every change goes through a PR. Skills create a feature branch, push, and open a PR with
Closes #<issue>in the body. The human merges. - Direct push — changes go straight to the default branch. Skills commit, push, and close the related issue explicitly.
Default: pull request, unless the user specifies otherwise.
Section E — Project board sync (optional, GitHub only).
Explainer: If you're using GitHub Projects v2 to track your issues on a board — or want to start — the
triage,to-issues, andtddskills can update a card'sStatuscolumn whenever they change the issue's lifecycle (e.g. triaged toready-for-agent→ StatusReady;tddstarts work →In progress; PR opened →In review). Without this, the board stays static and you have to drag cards across columns manually. The skill can wire up either an existing board or create a fresh one. Skip this section if you don't want a project board, or if you'd rather wire the sync up via GitHub Actions yourself.Requires a GitHub-native tracker. A board tracks items by GitHub node ID, so this section only applies when Section A chose GitHub or Hybrid (local markdown + GitHub mirror). If Section A chose plain Local markdown, there are no GitHub objects to track — don't silently skip the board the user asked for; go back and offer the Hybrid tracker, which mirrors each
.scratch/issue to a GitHub issue precisely so it can land on a board. In hybrid mode the board tracks the mirror issue, and the skills resolve that issue's number from the.scratch/file'sgithub:frontmatter before each Status update.
If the user opts in, walk them through:
-
Identify or create the project. Ask whether an existing Projects v2 board should be wired up, or whether to create a new one.
-
Existing board. Ask for the project URL (e.g.
https://github.com/users/<owner>/projects/<number>orhttps://github.com/orgs/<org>/projects/<number>) or anowner/numberpair. Parse out the owner and number. -
New board. Ask for a title (default: the repo name). Determine the owner — for org-owned repos default to the org; for user repos default to the user — and confirm before creating. Then:
Capture the returnednumber,url, and node ID. Two follow-ups, both optional but worth offering:- Link the repo so issue/PR pickers know about the board:
gh project link <number> --owner <owner> --repo <owner>/<repo>. - Enable built-in workflows at
<url>/workflows— at minimum Auto-add to project (filterrepo:<owner>/<repo> is:issue,pr is:open) and Auto-close issue (so closing an issue lands its card onDonewithout the skills having to). These workflows can't yet be toggled viagh; point the user at the URL.
- Link the repo so issue/PR pickers know about the board:
-
Fetch the project's structure. Run:
Capture the project's node ID (gh project view <number> --owner <owner> --format json gh project field-list <number> --owner <owner> --format jsonPVT_…), find the single-select field namedStatus(or whatever the user calls their lifecycle column — confirm with them), and capture its field ID (PVTSSF_…) and option IDs. -
Customise Status options if needed. New projects ship with
Todo/In Progress/Done. These skills work best with five canonical options —Backlog,Ready,In progress,In review,Done— because they map cleanly onto the triage and tdd lifecycle. Compare the option list from step 2 against the canonical five. If any are missing, ask the user which approach they'd prefer: -
Replace the Status options with the canonical five (recommended for new boards, or older boards with no cards yet).
Deterministic gate. The
updateProjectV2Fieldmutation has exactly one correct shape and the obvious prose drifts — the current GitHub GraphQL schema rejects aprojectIdargument onUpdateProjectV2FieldInput(InputObject 'UpdateProjectV2FieldInput' doesn't accept argument 'projectId'), so a hand-typed mutation that includes it fails mid-setup. Resolve and run the bundled script, which carries the correct mutation (it printsoptionId optionNameper option so you can capture the new IDs without a secondfield-list):SSO=$({ ls "$PWD"/skills/*/setup-zsl-superpowers/scripts/set-status-options.sh 2>/dev/null ls "$HOME/.claude/skills/setup-zsl-superpowers/scripts/set-status-options.sh" 2>/dev/null ls -d "$HOME"/.claude/plugins/cache/zsl-superpowers/zsl/*/skills/*/setup-zsl-superpowers/scripts/set-status-options.sh 2>/dev/null | sort -Vr; } | head -1) if [ -n "$SSO" ]; then bash "$SSO" <PVTSSF_…> # the Status field ID from step 2 else echo "zsl-gate: set-status-options.sh unresolved — run the mutation by hand per the Fallback below" fiFallback (if
$SSOis empty): run the mutation directly — note noprojectId, onlyfieldId:gh api graphql -f query=' mutation($fieldId: ID!) { updateProjectV2Field(input: { fieldId: $fieldId singleSelectOptions: [ {name: "Backlog", color: GRAY, description: ""} {name: "Ready", color: BLUE, description: ""} {name: "In progress", color: YELLOW, description: ""} {name: "In review", color: PURPLE, description: ""} {name: "Done", color: GREEN, description: ""} ] }) { projectV2Field { ... on ProjectV2SingleSelectField { id options { id name } } } } } ' -F fieldId=<PVTSSF_…>Either way, capture the new option IDs (the script prints them; the fallback returns them in the response, or re-run
gh project field-list). Note:updateProjectV2Fieldreplaces the option set wholesale; any cards assigned to a removed option (e.g.Todo) become unassigned and need manual remapping. Don't run this on a board with live cards without warning the user first. - Map existing options onto the canonical states (recommended when the board already has live cards). Confirm a mapping with the user — e.g.Todo → Backlog,In Progress → In progress— and record it indocs/agents/project-board.mdso the skills emit the right option IDs without mutating the field. -
Map canonical states to Status options. Default mapping (override per user preference, or per the mapping agreed in step 3):
| Skill action | Status option |
|---|---|
/triage → needs-triage / needs-info |
Backlog |
/triage → ready-for-agent / ready-for-human |
Ready |
/triage → tracking / /to-issues parent |
In progress |
/tdd step 1 (work begins) |
In progress |
/tdd ship in PR-style (PR opened) |
In review |
/tdd-parallel step 4 (integration PR opened) — bulk parent + every integrated sub-issue |
In review |
/triage → wontfix |
Done |
/tdd invoked with --no-ship (used by /tdd-parallel sub-agents) skips the per-slice "In review" update; the orchestrator handles the bulk transition when the consolidated integration PR opens.
Issue closure (PR merged, direct-push commit, manual close) lands at Done automatically via the project's built-in Auto-close issue workflow — skills don't write Done themselves.
5. If the user's Status options don't include some of these labels (e.g. their column is named In Review not In review, or they have no In progress), confirm the substitutions before writing.
If the user opts out, do not write docs/agents/project-board.md — the skills detect its absence and silently skip the sync.
Section F — Remote agent environment (optional).
Explainer: The overnight loop runs each PRD in its own remote claude.ai session.
/afk-fanout(you run it in the evening) schedules one one-shot routine per PRD via the claude.ai routines API; each fires/afk-workerin a fresh remote session. To schedule those,/afk-fanoutneeds the environment id of a Claude Code environment on claude.ai for the sessions to run in. Skip this whole section if you don't intend to use the overnight loop —/afk-fanoutjust refuses at pre-flight until it's configured.
This section is more involved than A–E, so walk it one decision at a time — present a step, get the answer, then move on. Don't dump it all at once. If the user opts out at the top, do not write docs/agents/remote-env.md (/afk-fanout detects its absence and refuses; the rest of the loop is unaffected).
Lead with this — the environment is reusable, not per-repo. A Claude Code environment on claude.ai is repo-agnostic: its config screen has only Name / Network access / Environment variables / Setup script — there is no repo field. The repo a routine works on is chosen per-routine (via
sources, which/afk-fanoutsets at schedule time from this repo'sorigin), not by the environment. So one generic environment (e.g. "Full Network + GH + Telegram") is reused across every project. The user very likely already has a usable one and does not need a new per-repo environment.
F1 — Reuse an existing environment if there is one. Before walking the form, try to auto-discover an environment id the user already has and offer to reuse it:
If any routine exists, surface its environment_id (looks like env_016kJTSSQaEEUatC4vq82c1G) and ask: "Reuse this environment for the overnight loop?" If yes, record it and skip F2 (jump to F3 — verify its env vars + setup script match what the loop needs). Only build a new environment if none exists or the user wants a dedicated one.
F2 — Create the environment (only if needed): walk the UI form field-by-field. In claude.ai → Code → Environments → New (or Update an existing one). The form has exactly four fields:
- Name — a generic, reusable name, e.g.
Full Network + GH + Telegram. Not a repo name; this environment serves all repos. - Network access — Full. Needed for
git push, theghCLI, the Telegram Bot API, and package installs in the setup script. Anything less and workers can't push results or notify. - Environment variables (the
.envbox) — paste exactly these (drop the two Telegram lines if Telegram isn't wanted — see F4):
GH_TOKEN=<github PAT>
AFK_TELEGRAM_BOT_TOKEN=<from BotFather> # only if Telegram opted in (F4)
AFK_TELEGRAM_CHAT_ID=<chat id> # only if Telegram opted in (F4)
ZSL_SUPERPOWERS_REF=main
⚠️ This box is NOT a secret vault. The UI itself warns the values are visible to anyone using this environment — don't add secrets. So use a minimally-scoped, ROTATABLE GitHub PAT, never a broad personal token. The scopes the loop actually needs:
- read on zsl-superpowers — the SessionStart hook clones it to provision the skills.
- read + write on the repos workers ship to — contents + pull requests (a fine-grained PAT), or repo (classic). This is what lets /tdd-parallel push feature branches, open PRs, and push the afk-runs ledger branch.
ZSL_SUPERPOWERS_REF=main pins which ref the skills-provisioning hook checks out (override to a tag/branch to freeze a version).
- Setup script — paste verbatim, and know why each line is there:
apt install gh puts the GitHub CLI on the box. gh auth setup-git is the load-bearing line and is the prerequisite that was previously missing from this setup: it configures git's credential helper to use GH_TOKEN, so raw git push authenticates — that's what the worker's afk-runs ledger-branch push and /tdd-parallel's feature-branch push rely on. Installing gh alone is not enough for git push; without gh auth setup-git, pushes fail and results never come home.
F3 — Obtain the environment id. The id is not shown in the env config dialog, so don't make the user hunt. The reliable path (have the skill run it): read it off any routine via RemoteTrigger({ action: "list" }) → job_config.ccr.environment_id. (If the env URL surfaces it, that works too — but the routines list is the dependable source.) Record this id; it's what goes into remote-env.md and what /afk-fanout schedules into.
F4 — Telegram heads-up (optional within optional), fully walked. Each worker can fire a best-effort one-line Telegram message when it finishes a PRD, so the user wakes to a status. If they want it, step them through it — don't just say "set two env vars":
- Create the bot. Message @BotFather, send
/newbot, follow the prompts, and capture the bot token it returns (AFK_TELEGRAM_BOT_TOKEN). - Get the chat id. Have the user message their new bot first (send it any text — the bot can't see a chat until the user opens it), then have the skill run:
Extract
result[].message.chat.id— that'sAFK_TELEGRAM_CHAT_ID(for a self-DM it's the user's own id). Ifresultis empty, the user hasn't messaged the bot yet — prompt them to, then re-run. - (Optional) confirm end-to-end. Send one test message so the user sees it actually arrives:
- Record both as env vars in the environment's
.envbox (F2) —AFK_TELEGRAM_BOT_TOKENandAFK_TELEGRAM_CHAT_ID. The values never go in the repo;remote-env.mdrecords only the var names. If they decline Telegram, workers skip the heads-up silently — it carries no load-bearing data.
F5 — Write the remote-skills hook so the skills resolve in the remote session. A scheduled routine fires in a fresh remote session with no plugins installed, and plugin availability is not configurable per claude.ai environment — so without provisioning, /afk-worker (and the skills it drives) won't resolve. The fix is a repo-level SessionStart hook that clones zsl-superpowers and symlinks its skills into ~/.claude/skills/ only when CLAUDE_CODE_REMOTE=true (a no-op locally, where the user has the plugin):
- Copy remote-skills-hook.sh to
.claude/hooks/zsl-remote-skills.shin the target repo andchmod +xit. - Merge a
SessionStartentry into the repo's.claude/settings.json— append to the existingSessionStartarray if one is present, never overwrite it (the repo may already have its own hooks): There is no "install the plugin into the environment" lever — the repo provisions its own skills via this hook.
F6 — Confirm a writable remote. Workers git push their per-PRD results to a shared afk-runs git branch that /morning-review reconciles back into the tracker (.scratch/ mode). The environment's PAT (F2) must have push access to this repo or results can't come home; /afk-fanout pre-flights this with git push --dry-run.
F7 — Per-repo runtime credentials caveat. Ask: "Does this repo's tests or slices need cloud credentials at run time — e.g. AWS for infra work?" If yes, those must also live in the environment's env vars — static keys or a CI role; interactive SSO won't work in a headless routine session — or workers will stall on integration tests. A generic environment with no cloud creds is fine for pure-code repos but breaks infra repos. (These are runtime creds for this repo's tests, distinct from the GH_TOKEN the loop itself needs.) Record any required cloud-cred var names in remote-env.md so the next operator knows the environment must carry them.
3. Confirm and edit¶
Show the user a draft of:
- The
## Agent skillsblock to add to whichever ofCLAUDE.md/AGENTS.mdis being edited (see step 4 for selection rules) - The contents of
docs/agents/issue-tracker.md,docs/agents/triage-labels.md,docs/agents/domain.md,docs/agents/ship-style.md, (if Section E was answered yes)docs/agents/project-board.md, and (if Section F was answered yes)docs/agents/remote-env.md
Let them edit before writing.
4. Write¶
Pick the file to edit:
- If
CLAUDE.mdexists, edit it. - Else if
AGENTS.mdexists, edit it. - If neither exists, ask the user which one to create — don't pick for them.
Never create AGENTS.md when CLAUDE.md already exists (or vice versa) — always edit the one that's already there.
If an ## Agent skills block already exists in the chosen file, update its contents in-place rather than appending a duplicate. Don't overwrite user edits to the surrounding sections.
The block:
## Agent skills
### Issue tracker
[one-line summary of where issues are tracked]. See `docs/agents/issue-tracker.md`.
### Triage labels
[one-line summary of the label vocabulary]. See `docs/agents/triage-labels.md`.
### Domain docs
[one-line summary of layout — "single-context" or "multi-context"]. See `docs/agents/domain.md`.
### Ship style
[one-line summary — "pull request" or "direct push"]. See `docs/agents/ship-style.md`.
If Section E was answered yes, also append:
If Section F was answered yes, also append:
### Remote agent environment
[one-line summary — the environment id]. See `docs/agents/remote-env.md`.
Then write the docs files using the seed templates in this skill folder as a starting point:
- issue-tracker-github.md — GitHub issue tracker
- issue-tracker-gitlab.md — GitLab issue tracker
- issue-tracker-local.md — local-markdown issue tracker
- issue-tracker-hybrid.md — hybrid local-markdown source-of-truth + GitHub mirror (use when Section A chose Hybrid; fill the repo
<owner>/<repo>and confirm the.scratch/is the source of truth) - triage-labels.md — label mapping
- domain.md — domain doc consumer rules + layout
- ship-style-pr.md — pull-request workflow
- ship-style-direct.md — direct push to default branch
- project-board.md — GitHub Projects v2 sync (only when Section E was answered yes)
- remote-env.md — remote agent environment for the overnight loop (only when Section F was answered yes)
- remote-skills-hook.sh — the
SessionStarthook that provisions the skills in remote sessions (only when Section F was answered yes); copy to the target repo's.claude/hooks/zsl-remote-skills.sh
For "other" issue trackers, write docs/agents/issue-tracker.md from scratch using the user's description. For docs/agents/project-board.md, fill the template placeholders with the project node ID, Status field ID, and option IDs you discovered in Section E. For docs/agents/remote-env.md, fill the seed from Section F: the environment id (replacing the env_xxxxxxxxxxxxxxxxxxxxxx placeholder), the chosen env name, the env-var names the environment must carry (never values — GH_TOKEN, the Telegram pair if opted in, any F7 cloud-cred names), and confirm the verbatim setup script and PAT-scope notes match what you walked. When Section F was answered yes, also install the remote-skills hook (copy remote-skills-hook.sh → .claude/hooks/zsl-remote-skills.sh, chmod +x, and merge the SessionStart entry into .claude/settings.json per Section F step F5 — append, don't overwrite).
5. Migrate local-markdown layout (local-markdown only)¶
Only runs if Section A selected local-markdown. Two one-time migrations, in this order — the folder rename must run before the number/date backfill, because the backfill globs .scratch/_done/ and treats anything else directly under .scratch/ as an active feature, so a stale .scratch/done/ would get mis-numbered.
5a. Rename legacy archive folders done/ → _done/¶
Older repos archived closed work under done/; the convention is now _done/ so the archive sorts to the top of its parent directory. Detect first (read-only):
# Feature archive still using the old name:
[ -d .scratch/done ] && echo ".scratch/done"
# Per-feature issue archives still using the old name (active + archived features):
find .scratch -type d -path '*/issues/done' 2>/dev/null
If both probes print nothing, the repo is already on the new layout — skip to 5b. Otherwise show the maintainer the moves and, on confirmation, apply them with git mv so history follows the rename:
[ -d .scratch/done ] && git mv .scratch/done .scratch/_done
for d in $(find .scratch -type d -path '*/issues/done' 2>/dev/null); do
git mv "$d" "${d%/done}/_done"
done
Move the feature archive first so the loop's find also sweeps the just-renamed .scratch/_done/*/issues/done. Nothing is deleted and no numbers change — only the two folder names. Use plain mv if .scratch/ isn't git-tracked. Commit as its own chore: migrate archive folders done/ → _done/, or fold it into the backfill commit below.
5b. Backfill feature numbers and archive date prefixes¶
Check whether any existing features lack the new prefixes:
# Active features missing the <NNN>- number prefix:
find .scratch -mindepth 1 -maxdepth 1 -type d \
-not -name '_done' \
-not -name '[0-9][0-9][0-9]-*' 2>/dev/null
# Archived features missing either the date or the number (or both):
find .scratch/_done -mindepth 1 -maxdepth 1 -type d \
-not -name '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]-*' 2>/dev/null
If both outputs are empty, skip this step.
Otherwise, offer a single unified backfill that handles both the number prefix (active and archive) and the date prefix (archive only) in one pass.
Algorithm¶
-
Catalog every feature directory across
.scratch/(exclude_done) and.scratch/_done/. -
Classify each by its current prefix state:
-
Active, numbered (
^[0-9]{3}-) — preserve as-is. - Active, unnumbered — assign a number.
- Archived, date+number (
^[0-9]{8}-[0-9]{3}-) — preserve as-is. - Archived, date-only (
^[0-9]{8}-but not the above) — insert a number after the date. -
Archived, unprefixed — assign both a date and a number.
-
Determine the canonical date for every feature that needs one. Use the commit when the directory (or its current name) was added:
Fall back to the most recent touching commit if --diff-filter=A returns nothing. If neither yields a date (no git history for the path), prompt the user — don't silently default to today.
For active features, the date is used only as a sort key for number assignment; it isn't written into the directory name.
-
Sort all features needing a number by canonical date (oldest first, so the lowest numbers go to the earliest features).
-
Assign numbers: existing numbers are preserved. New numbers start from
max(existing) + 1(or001if no features are numbered yet) and are assigned sequentially in date order. -
Compose the full proposed rename list, with a one-line note explaining what changed:
.scratch/auth/ → .scratch/001-auth/ (assigned number 001)
.scratch/billing/ → .scratch/002-billing/ (assigned number 002)
.scratch/_done/oauth/ → .scratch/_done/20251020-003-oauth/ (assigned date 2025-10-20, number 003)
.scratch/_done/20251114-payments/ → .scratch/_done/20251114-004-payments/ (assigned number 004)
-
Ask: "Apply these renames in a single commit?" Wait for confirmation. The maintainer may want to override a date, override a number (e.g. to keep an external reference stable), or skip specific entries entirely — accept edits before applying.
-
Apply each rename via
git mv, then commit as a single migration commit:
Don't run any git mv without explicit confirmation. Backfilled values are best-effort heuristics from git history; the maintainer is the authority on edge cases (e.g. a feature whose archive commit doesn't reflect the real ship date, or a number that should be preserved to match an external system).
6. Done¶
Tell the user the setup is complete and which engineering skills will now read from these files. If Section F was configured, note that /afk-fanout will read docs/agents/remote-env.md to schedule the overnight loop. Mention they can edit docs/agents/*.md directly later — re-running this skill is only necessary if they want to switch issue trackers or restart from scratch.