agent-upgrade
Upgrades an existing Claude Agent project to the current config schema — migrates information from old locations to new ones, confirms every move with the user, and leaves a backup. Use when a project
SKILL.md.claude/skills/agent-upgrade/SKILL.md
GitHubAgent Upgrade Skill
You migrate an existing Claude Agent project from an older config schema to the current one. You are interactive and non-destructive by default: you show the user every change you are about to make before writing a byte, back up the old files, and stop at the first ambiguity.
This skill is versioned. Each schema bump adds a new migration block below; older blocks continue to work so chained upgrades (v1 → v2 → v3) stay in this one skill.
Base Rules
Environment. You are running in Claude Code directly in the project root. Your working directory is the root of the project being upgraded.
Terminal commands: Single uninterrupted line, no backslash continuations.
Hard rules (no exceptions):
- Do not delete or overwrite any file before:
- Showing the user the full migration ledger, and
- Copying the file into
.workflow/upgrade-backup-<timestamp>/with its original relative path preserved.
- Do not guess config values the user cared about. If a conflict surfaces
(e.g. root
agent.yamlsaysdotnet testbut the per-repoagent.yamlsaysdotnet test --no-build), pause and ask the user to pick. - Idempotent. If the project is already on the current schema, print the detected version and exit without writing anything.
- If the user stops mid-upgrade, the backup is enough to restore state — never delete the backup yourself.
Step 1: Detect Schema Version
Read the root agent.yaml. Classify into one of:
- v3 (current) — schema is on v2 OR newer (multi-repo or single-repo)
AND
workflow.backendkey is present (set to eithermarkdownorgithub_project). - v2 —
repos:entries each have abuild:pointer (build: <path>/agent-build.yaml) and no inlinetesting:orbuild:blocks nested under the repo entry. A root-levelmac_build:block is absent or commented.workflow.backendkey is absent. - v1 (pre-refactor) —
repos:entries inlinetesting:andbuild:blocks, and/or a root-levelmac_build:block is present. Each sub-repo directory likely contains a fullagent.yaml. (workflow.backendkey absent.) - single-repo (no version detection needed) — missing
repos:andproject.type: multi-repo. Single-repo projects only need v3 detection (presence ofworkflow.backend). If absent, jump to Step 9 (v2 → v3).
Migration order:
- v1 → first run Steps 2–8 to get to v2, then continue to Step 9 to land at v3.
- v2 → skip Steps 2–8, run Step 9 only.
- v3 → state
Project is already on schema v3 — no upgrade needed.and stop.
If v3: stop. If v2: jump directly to Step 9. If v1: proceed to Step 2.
Step 2: Scan and Build the Migration Ledger
Walk every repo entry in the root agent.yaml. For each:
- Record the inline
testing.*andbuild.*values from the root. - If
<repo.path>/agent.yamlexists, read it. Extract:testing.*/build.*— compare against the root's inline values. Equal values are unambiguous. Divergent values are a conflict.code_standards— this is unique to the per-repo file; it has no root counterpart.design— if non-empty, record it; it will move to the leafagent-build.yamlif the stack is a UI stack.
- If the root
agent.yamlhas amac_build:block and this repo'sstackisswiftorios, mark it as an iOS mac_build candidate — the block will move to this repo's leaf file. - Fastlane check (stack
iosorandroid). Look for<repo.path>/fastlane/Fastfileor<repo.path>/Fastfile. If found, grep forlane :<name>to list lanes. If the existing v1testing.command/build.commandfor this repo is empty or looks like a generic stack default (xcodebuild ...,./gradlew test,./gradlew assembleDebug) and fastlane offers a better-fitting lane (fastlane test,fastlane build,fastlane beta, etc.), record this as a fastlane suggestion row in the ledger — do NOT auto-apply; the user confirms in Step 3.
Also detect mono-repo candidates: any repo whose <repo.path>
directory contains at least two recognizable sub-project layouts (e.g.
ios/ + android/ + a Rust-toolchain directory). Prompt:
`<repo.path>/` contains what look like multiple independently-built
sub-projects: <list>. Expand this into a mono-repo parent with each
as a separate sub-project? [Y/n]
If yes, for each sub-project ask its stack (run stack detection from the
agent-init skill's detection table on that subdir) and — for iOS — the
Mac SSH host/workspace, defaulting to the root mac_build: block if one
was present.
Build a single Migration Ledger in memory:
Repo: <id> (<path>)
Stack: <stack>
Shape: leaf | mono-repo
Destination: <path>/agent-build.yaml
Source → Destination:
root agent.yaml repos[<id>].testing.command → <dest>.testing.command ("<value>")
root agent.yaml repos[<id>].build.command → <dest>.build.command ("<value>")
<path>/agent.yaml code_standards → <dest>.code_standards (N lines)
root agent.yaml mac_build.host → <dest>.mac_build.host ("<value>") [iOS only]
root agent.yaml mac_build.workspace → <dest>.mac_build.workspace ("<value>") [iOS only]
Conflicts:
<field> — root says "<a>", per-repo agent.yaml says "<b>" — <unresolved>
Fastlane suggestions: [iOS/Android only, if Fastfile found]
testing.command: current "<value>" → suggest "fastlane test" [lane :test found]
build.command: current "<value>" → suggest "fastlane build" [lane :build found]
Sub-projects: [only if mono-repo]
<id> (<path>) → <path>/agent-build.yaml (stack: <stack>, mac_build: <host|—>)
Step 3: Confirm with the User
Print the full ledger. For every Conflict row, ask which value to keep, offering both plus "Other" (free-form input). Do not proceed until every conflict is resolved.
For every Fastlane suggestion row, ask "Adopt fastlane <name> for
<field>? [Y/n]". On yes, the new value goes into the leaf
agent-build.yaml; on no, keep the current value.
Then show the summary:
About to:
- Back up N files to .workflow/upgrade-backup-<timestamp>/
- Write M new files (agent-build.yaml per repo/sub-project)
- Rewrite the root agent.yaml (repos: block + remove root mac_build:)
- Delete K per-repo agent.yaml files after backup
Proceed? [Y/n]
Only continue on an explicit yes.
Step 4: Write the Backup
Create .workflow/upgrade-backup-<YYYY-MM-DDTHH-MM-SS>/. For every file
the upgrade will modify or delete:
- Copy it into the backup under its original relative path (preserve
directory structure — e.g.
.workflow/upgrade-backup-.../Backend/middleware/agent.yaml). - Also copy the root
agent.yamlin full.
Write a manifest backup/MANIFEST.md listing every backed-up file with
its size and sha256.
Step 5: Write New Files
- Per-repo leaf
agent-build.yaml— for each leaf repo, render usingtemplates/<stack>/agent-build.yaml.tmplwhere available, filling instack,testing,build,code_standards, and (iOS only)mac_build. If the stack has no matching template (e.g. stack wasbase), emit the minimal leaf shape fromtemplates/ios/agent-build.yaml.tmpladapted to that stack. - Mono-repo parent
agent-build.yaml— for each repo the user elected to expand, render usingtemplates/mono-repo/agent-build.yaml.tmpl. Populateprojects:with each sub-project'sid,stack,path, andbuildpointer. - Sub-project leaf
agent-build.yaml— one per sub-project inside a mono-repo, same rules as (1). - New root
agent.yaml— replace therepos:block with the pointer shape (id,path,stack,build). Remove the root-levelmac_build:block entirely (those values now live per iOS leaf). Preserve everything else verbatim (project,git,workflow,agents,github, etc.).
Write to disk in this order: sub-project leaves → mono-repo parents →
top-level leaves → new root agent.yaml. If any write fails, stop and
surface the partial state; do not delete anything in Step 6.
Step 6: Remove Old Files
Only after Step 5 succeeds end-to-end:
- Delete each per-repo
<repo.path>/agent.yaml(they are in the backup). - Leave
.workflow/untouched except for the new backup directory.
Print each deletion as it happens.
Step 7: Validate Task Files
Scan .workflow/tasks/ for every task file. For each, read its Repo:
field and attempt to resolve it against the new root agent.yaml:
- Leaf repo id → must exist in
repos:. - Dotted
<parent>.<sub>→<parent>must exist as a mono-repo, and<sub>must appear in the parent'sagent-build.yamlprojects:list. - Legacy relative-path values (e.g.
Repo: Backend/mobile_api) — flag these. Suggest the correct id based on path match; do not rewrite the task file automatically.
Write any unresolved tasks to .workflow/upgrade-backup-<timestamp>/TASKS-TO-FIX.md
with one line per task and a suggested rewrite.
Step 8: Report
Print:
- Backup location (
.workflow/upgrade-backup-<timestamp>/) - Files created (
+), rewritten (~), deleted (-) — one per line - Conflicts resolved (field, chosen value)
- Any unresolved task
Repo:fields - Recommended next commands:
git status— review the changesgit diff <backup>/agent.yaml agent.yaml— compare root before/aftergit add -A && git commit -m "chore: upgrade agent config to schema v2"
Do not run git add or git commit yourself. Leave that to the user.
Step 9: v2 → v3 (workflow backend choice)
A v3 project has workflow.backend set in agent.yaml. v2 projects don't
have the key — they implicitly used markdown. The v3 migration makes the
choice explicit and optionally moves the project to a GitHub Project board.
Backup
agent.yamlto.workflow/upgrade-backup-<timestamp>/agent.yaml.v2(re-use the timestamp from Step 4 if v1 → v2 ran in the same session, else create a fresh backup dir).Ask the user:
Which workflow backend? (a) markdown — keep using `.workflow/*.md` files (no behavioral change). (b) github_project — migrate to a GitHub Project board now via /agent-migrate. Choice [a/b]?On (a) — markdown: Insert a single line under the
workflow:block:backend: "markdown"That's the entire migration. Print:
Project is now on schema v3 (backend: markdown). No behavioral change.Done.On (b) — github_project: Do NOT modify
agent.yamlhere — theagent-migrateskill handles the agent.yaml update as part of its own Step 7. Hand off:Delegating to /agent-migrate. That skill will: - Provision the GitHub Project board (labels, columns, fields) - Migrate every BACKLOG/TODO/DONE item, plan, and task to the board - Update agent.yaml with workflow.backend: github_project - Run install-skills-local.sh to pin .claude/ to the current framework commit - Copy issue templates into .github/ISSUE_TEMPLATE/ Press Enter to continue or Ctrl+C to abort.On Enter, invoke
/agent-migrate. The migration is non-destructive — if the user aborts inside agent-migrate, the project stays on v2 (backend key still absent) and they can re-run later.Either way, also append
.workflow/temp/to.gitignoreif not already present (cheap, harmless on markdown backend, required for github_project). Show the diff and ask the user to commit.
Future schema bumps
When a new schema version ships, add a new top-level section below ("## Step 10: v3 → v4") describing the detection criteria, ledger rows, and write steps for that migration. Re-use Steps 3 (confirm), 4 (backup), 6 (delete), 7 (validate tasks), and 8 (report) with version-specific overrides. Keep the v1 → v2 and v2 → v3 blocks working indefinitely — projects upgrade on their own cadence.