| name | hoist-upgrade |
| description | Upgrade a Hoist app's `@xh/hoist` dependency across one or more major versions. Reads per-version upgrade guides, auto-applies mechanical code migrations, flags judgment calls, bumps `hoistCoreVersion` (and refreshes the hoist-core MCP+CLI launchers if previously installed), and produces a comprehensive upgrade report. |
| allowed-tools | Read, Write, Edit, Glob, Grep, Bash, mcp__hoist-react__hoist-search-docs, mcp__hoist-react__hoist-get-symbol, mcp__hoist-react__hoist-search-symbols |
Hoist Version Upgrade
Upgrade this Hoist project's @xh/hoist dependency between versions. Follow each phase in order.
Phase 1: Detect
Gather project information needed to plan and execute the upgrade.
1. Parse arguments
Check $ARGUMENTS for an optional target version (e.g. 81.0.0 or v81). If present, normalize
it: strip any leading v, store as the target version for Phase 2. If no argument is provided,
the skill will prompt the developer to choose a target in Phase 2.
2. Detect package manager
Check which lockfile exists in client-app/:
yarn.lock -- use yarn (e.g. yarn install, yarn why, yarn lint)
package-lock.json -- use npm (e.g. npm install, npm ls, npm run lint)
Store the detected package manager. All frontend commands in subsequent phases should be run
from client-app/ using this package manager.
3. Detect current @xh/hoist version
Read client-app/package.json. Find @xh/hoist in dependencies and extract the current
version. Handle version strings like ^82.0.0-SNAPSHOT -- extract the numeric portion
(e.g. 82.0.0).
If @xh/hoist is not a direct dependency, it may be pulled in transitively via a client plugin.
Run from client-app/:
- Yarn:
yarn why @xh/hoist
- npm:
npm ls @xh/hoist
If neither approach finds @xh/hoist, inform the user:
"This does not appear to be a Hoist project -- @xh/hoist was not found as a direct or
transitive dependency."
Then stop.
4. Check for dirty working tree
Run:
git status --porcelain
If output is non-empty, warn the developer:
"Your working tree has uncommitted changes. Please commit or stash them before running the
upgrade to ensure a clean rollback point if needed."
Do NOT proceed with any modifications until the working tree is clean.
5. Read hoist-core version
Read gradle.properties at the project root. Extract the hoistCoreVersion value.
If the version is not set directly (e.g. it is inherited from a client-specific Grails plugin
dependency), check build.gradle for the plugin dependency and note the transitive hoist-core
version if determinable.
Assess server-side significance: Check CLAUDE.md for notes about server-side complexity.
Also scan the Grails app package (e.g. grails-app/controllers/, grails-app/services/) for
custom controllers and services. If extensive custom server code is present, note this -- it
means hoist-core version bumps warrant extra attention in the upgrade report.
6. Detect client plugins
Scan client-app/package.json dependencies for packages that are NOT @xh/hoist but appear to
be Hoist-related client plugins (e.g. @client/hoist-plugin, @client/hoist-*).
Also read CLAUDE.md for any documented plugin-to-Hoist version mapping or plugin notes.
When a client plugin is detected, note the package name, current version, and any version
mapping information for use in Phase 2 planning.
Phase 2: Plan
Present the upgrade plan for developer confirmation. Do NOT make any changes until the developer
confirms.
1. Determine target version
If a target version was provided via arguments in Phase 1, use it.
If no target version was specified, query npm for available versions:
npm view @xh/hoist versions --json
npm view is a registry-query command -- it works in any Node.js environment regardless of
which package manager the project uses, since npm ships with Node itself. No need to route
through the project's detected manager here.
Filter the results to stable releases only -- versions matching x.y.z with no prerelease
suffix. Exclude versions with -SNAPSHOT, -alpha, -beta, -rc, or any other prerelease tag.
XH publishes many SNAPSHOT versions to npm during development -- these should never be suggested
as upgrade targets.
Filter to versions newer than the currently installed version and present a structured list:
Available @xh/hoist versions (you have v{current}):
v79.0.0
v80.0.0
v80.1.0
v81.0.0 <- latest
What version would you like to upgrade to?
Wait for the developer to choose before continuing.
2. Determine version hop sequence
Each major version between current and target is a separate hop. Example: v77 -> v81 produces
the sequence [v77->v78, v78->v79, v79->v80, v80->v81].
For minor version jumps within the same major version (e.g. v80.0.0 -> v80.1.0), treat that as
a single hop.
3. Check guide availability
For each hop in the sequence, check if a dedicated upgrade guide exists. Use Glob to look for:
client-app/node_modules/@xh/hoist/docs/upgrade-notes/v*-upgrade-notes.md
Match each hop's target version against the available files. If a guide does NOT exist for a
particular hop's target version (versions before v73 will not have one), note that hop as
"CHANGELOG-only" and alert the developer:
"Note: No dedicated upgrade guide exists for v{target}. This hop will use CHANGELOG entries
only, and guidance may be less thorough."
4. Client plugin confirmation
If client plugins were detected in Phase 1, present the detection:
### Client Plugins Detected
| Plugin | Current Version | Hoist Version Mapping |
|--------|----------------|----------------------|
| {plugin name} | {version} | {mapping from CLAUDE.md, or "No mapping found"} |
How should I handle the plugin version during this upgrade?
- Bump to a specific version?
- Leave unchanged?
- Other guidance?
Do not proceed until the developer confirms the plugin approach.
5. Display the upgrade plan
## Upgrade Plan: @xh/hoist v{current} -> v{target}
| Hop | Guide Available | Difficulty |
|-----|-----------------|------------|
| v77 -> v78 | Yes (upgrade notes) | TBD (read during execution) |
| v78 -> v79 | Yes (upgrade notes) | TBD |
| ...
- **Branch:** upgrade/hoist-v{current}-to-v{target} (or existing branch if found)
- **Commits:** One per version hop
- **hoist-core:** {current version from gradle.properties}
- **Server complexity:** {Minimal (stock) | Significant (custom controllers/services)}
- **Client plugins:** {Detected plugins, or "None detected"}
- **Package manager:** {detected package manager}
6. Confirm with developer
Ask: "Proceed with this upgrade plan? (yes/no)"
Wait for confirmation before making any changes.
Phase 3: Execute
For each version hop in the sequence, apply the upgrade. Never commit directly to main or
develop.
3a. Branch setup (first hop only)
Check for existing branches matching upgrade/hoist-* or hoist-upgrade-* patterns:
git branch --list "upgrade/hoist-*" "hoist-upgrade-*"
If a matching branch exists, ask the developer if they want to reuse it.
If no match (or developer declines reuse), create a new branch:
git checkout -b upgrade/hoist-v{current}-to-v{target}
Verify the current branch is NOT main or develop before any commits.
3b. Bump version and install
Update the @xh/hoist version in client-app/package.json dependencies to the hop's target
version (e.g. "@xh/hoist": "^{target}").
Run the detected package manager's install command from client-app/ to update the lockfile
and install the new version.
Important: The upgrade notes for version N ship with version N. They are only available on
the filesystem after installing the target version.
3c. Read upgrade guide for this hop
Use the Read tool to read upgrade notes directly from the filesystem:
client-app/node_modules/@xh/hoist/docs/upgrade-notes/v{TARGET}-upgrade-notes.md
Do NOT use MCP hoist-search-docs for upgrade notes. The MCP server may still be serving
the previous version's content after install. The Read tool always reflects the installed
version.
For versions WITHOUT upgrade notes (pre-v78): Read client-app/node_modules/@xh/hoist/CHANGELOG.md and
parse the Breaking Changes section for the target version. Alert the developer:
"No dedicated upgrade guide exists for this version. Using CHANGELOG breaking changes section.
Guidance may be less thorough for this hop."
3d. Apply migrations
Read the upgrade guide carefully. For each migration step:
Mechanical changes (renames, import updates, CSS class changes):
- Use the grep commands from the upgrade guide to find affected files in the project
- Apply changes using the Edit tool
- Verify with a second grep that the old patterns are gone
Judgment calls (behavior changes, multiple replacement options, architectural decisions):
- Do NOT apply automatically
- Use grep to find affected files
- Record the item with: description, affected files, and the guide's recommendation
- These will be included in the upgrade report for developer review
When migration involves API changes and you need to verify new API shapes, prefer the
before/after code examples in the upgrade guide. MCP API lookups (hoist-get-symbol,
hoist-search-symbols) may reflect the previous version until the MCP server is reconnected.
3e. Check and bump hoist-core version
Parse the upgrade guide's "Prerequisites" section for hoist-core version requirements (e.g.
"hoist-core >= v36.1").
If a requirement is found, compare against the current hoistCoreVersion from
gradle.properties (read in Phase 1).
If the current version is below the requirement:
- Bump
hoistCoreVersion in gradle.properties to the required version.
- Prominently note this change for the upgrade report.
- If the project has significant server-side code (detected in Phase 1), add a prominent
warning that the hoist-core upgrade may require additional server-side review.
- Refresh the hoist-core MCP+CLI launchers if they were previously installed. Check
whether
bin/hoist-core-mcp exists at the project root. If it does, the launchers embed an
absolute path to a version-suffixed JAR (e.g. hoist-core-mcp-{old}-all.jar) and are now
stale. Re-run:
./gradlew installHoistCoreTools
This refreshes the launchers to point at the new version's JAR. Verify with
./bin/hoist-core-docs ping (returns hoist-core CLI is running.). Note the refresh in
the upgrade report.
- Surface the install-eligibility transition if relevant. If the bumped
hoistCoreVersion
is >= 39.0 AND bin/hoist-core-mcp does NOT exist (i.e., the install task was never run
here), the user is now eligible for the hoist-core MCP server + hoist-core-docs /
hoist-core-symbols CLI tools (introduced in v39.0). Add a "Next Steps" item to the upgrade
report: "Install the hoist-core MCP+CLI tools by running /xh:onboard-app -- onboarding
will detect the new eligibility and offer to install."
3f. Handle client plugin version (if applicable)
If a client plugin was detected and the developer confirmed a version strategy in Phase 2:
- Bump the client plugin version in
client-app/package.json according to the confirmed strategy
- Run the install command again from
client-app/ after the plugin version bump
3g. Commit this hop
git add -A
git commit -m "Upgrade @xh/hoist v{FROM} -> v{TO}"
3h. Progress reporting
After each hop, display a brief status showing progress through the sequence:
## Upgrade Progress: v{start} -> v{end}
[completed] v77 -> v78 (TRIVIAL) -- N changes applied, M judgment calls
[in progress] v78 -> v79 -- in progress...
[pending] v79 -> v80 -- pending
Phase 4: Verify
After ALL hops are complete, run verification. The CLI surface is the always-on baseline (it
reads from node_modules and always reflects the upgraded version); MCP reconnect is
opportunistic and safe to skip in environments that block MCP.
1. Verify the upgraded developer-tools surfaces
hoist-react CLI (universal, always run). From client-app/, run:
npx hoist-docs index
This reads from client-app/node_modules/@xh/hoist/... and always reflects the just-installed
version. A clean docs index print confirms the upgraded surface is reachable. Surface any
errors before continuing.
hoist-react MCP reconnect (only if MCP is part of your workflow). The MCP server is still
serving the pre-upgrade version's types and docs. Prompt the developer:
"If you use MCP in this environment, please run /mcp in Claude Code to reconnect the
hoist-react server, then say 'continue'. If you don't use MCP (for example, in MCP-blocked
enterprise environments), say 'skip' -- the CLI surface above is the working path and
already reflects the upgrade."
After 'continue': call mcp__hoist-react__hoist-ping to confirm. After 'skip', or if the ping
fails or the tool isn't in your context, proceed without error -- the CLI verification above is
sufficient.
hoist-core CLI (only if launchers were refreshed in Phase 3e). If Phase 3e re-ran
installHoistCoreTools, run:
./bin/hoist-core-docs ping
Expect hoist-core CLI is running. This confirms the refresh produced working launchers
pointing at the new JAR. Surface any errors before continuing.
2. TypeScript compilation
Run from client-app/:
npx tsc --noEmit
Report pass/fail.
3. Lint
Run the project's lint command from client-app/ using the detected package manager.
Report pass/fail.
4. Guided verification
If the final version's upgrade guide includes a verification checklist, present it to the
developer and work through each item.
If verification fails, present the errors and work with the developer to resolve them before
proceeding to the report phase.
Verification cadence
For multi-hop upgrades where all hops are LOW or TRIVIAL difficulty, batch all verification at
the end. For hops rated MEDIUM or higher, consider running intermediate TypeScript compilation
checks after those hops to catch issues before they compound. Use your judgment based on the
difficulty ratings read from the upgrade guides.
Phase 5: Report
Render a structured upgrade summary directly in the chat. Do NOT write a report file --
the conversation is the artifact. If the developer wants it persisted, they can copy it
or ask you to save it somewhere specific.
1. Render the summary
Print the following as a single Markdown response. Use short prose and lists; lean on
tables only where they genuinely help (e.g. the hop overview). Skip optional sections
when they don't apply.
## Hoist Upgrade Complete: @xh/hoist v{FROM} -> v{TO}
- **Hops:** {N} ({comma-separated hop list, e.g. v77 -> v78, v78 -> v79})
- **Branch:** {branch name}
- **Package manager:** {yarn | npm}
### Hop Overview
| Hop | Difficulty | Changes | Judgment Calls | Status |
|-----|------------|---------|----------------|--------|
| v{a} -> v{b} | {TRIVIAL/LOW/MEDIUM/HIGH} | {n} | {n} | {ok / failed} |
| ...
### Per-Hop Detail
#### v{a} -> v{b} ({difficulty}, guide: {upgrade-notes | CHANGELOG})
**Mechanical changes applied:**
- `{file}` -- {what changed}
- ...
**Judgment calls (require your review):**
- **{item}** -- {one-line description}
- Files: {comma-separated}
- Guide recommendation: {recommendation}
{Repeat per hop. Omit empty subsections.}
### Verification
- TypeScript (`tsc --noEmit`): {pass | fail with brief detail}
- Lint: {pass | fail with brief detail}
- hoist-react CLI (`npx hoist-docs index`): {ok | error}
- hoist-react MCP reconnect: {reconnected | skipped | failed}
- hoist-core CLI (if launchers refreshed): {ok | error | N/A}
### hoist-core Changes
{Include only if hoistCoreVersion was bumped.}
- {old} -> {new} (required by {hop or guide reference})
- Launchers: {refreshed via installHoistCoreTools, ping verified | not previously installed -- skipped}
- {If significant server-side code was detected in Phase 1, add a one-line note that
server-side review is recommended.}
### Client Plugin Notes
{Include only if client plugins were detected.}
- `{plugin}`: {old} -> {new or unchanged} -- {notes}
### Next Steps
- [ ] Review the judgment calls above and apply as appropriate
- [ ] Test affected features (especially anything in judgment calls)
- [ ] Run the app and verify core functionality
{Include if hoist-core was bumped:}
- [ ] Review hoist-core release notes if this project has significant server-side code
{Include if hoistCoreVersion >= 39.0 AND bin/hoist-core-mcp does NOT exist:}
- [ ] Install the hoist-core MCP+CLI tools now that you're eligible (>= v39.0):
run `/xh:onboard-app` -- it will detect the new eligibility and offer to install
{Include if client plugins were detected:}
- [ ] Verify client plugin compatibility with the upgraded Hoist version
- [ ] Open / merge the pull request for this upgrade branch
Be honest in the verification section -- if tsc or lint failed and you and the developer
worked through the failures, summarize what was resolved. If something is still broken at
report time, say so plainly so the developer doesn't merge a half-green branch.