mcpbeat Sign in

Nocobase App Upgrade Agent Skill

>- Upgrade this application to a newer release of the template it was generated from, which is how this application moves to a newer NocoBase version. Users rarely think in terms of templates, so use it whenever the user asks to upgrade or update NocoBase, the NocoBase core, kernel or framework version, or the @nocobase packages as a whole — for example "upgrade NocoBase", "update the NocoBase core version", "move to the latest NocoBase release", "升级 NocoBase", "升级 NocoBase 内核版本", "更新 NocoBase 到最新版" — as well as when they ask to upgrade the template, pull in template changes, move to a newer template version, or reconcile the application with upstream. Do not use for ordinary feature development, for upgrading a single dependency, or for upgrading an already deployed build on a server, which the app installer handles.

5.8k tokens
context cost
SKILL.md, read when the skill is used
13
files
plus reference files
0
copies elsewhere
how many repositories repackaged it
24 822
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/nocobase/nocobase --skill nocobase-app-upgrade

What comes with it

144 714 bytes besides the instruction
references/application-cookie-isolation.md
references/database-upgrades.md
references/edge-cases.md
references/form-feedback-upgrade.md
references/list-feedback-upgrade.md
references/list-navigation-upgrade.md
references/notification-upgrade.md
references/plugin-development-skill.md
references/realtime-upgrade.md
references/submission-upgrade.md
references/theme-upgrade.md
references/versioned-upgrade-verification.md

The instruction itself

11 sections, as written by the author

Upgrading the application template

pnpm create @nocobase/app copied a template into the user's hands and left no link back to it, so a newer template release arrives only by someone merging it in.

The difficulty is telling the template's changes from the user's. Comparing the application against the latest template cannot: a file that differs may have been changed by either side, or both. So compare the two template _releases_ instead — the baseline already merged and the target — and decide file by file how each of their differences lands here.

BASE     nocobase.defaultTemplateVersion — the release already merged in
TARGET   the release being moved to
PROJECT  the application as the user has it now

BASE → TARGET    what the template changed — the work to bring in
BASE → PROJECT   what the user changed — the work that must survive

defaultTemplateVersion is not the application's version. It records how far template source has been merged, and moves only after a merge actually happens.

The diff is information. Decide each file yourself and write every edit by hand — a text-merge tool applied to the project would reconcile only what its hunks happen to touch, leaving the user's own files unexamined and step 5 undone.

Never: overwrite the application with a fresh template copy; bump defaultTemplateVersion without merging the source; resolve a conflict by discarding the user's side; run git checkout --, git restore, git reset --hard, git stash, git clean, or rm -rf against the working tree; regenerate with create-app and copy the user's code across.

When the App already supplies the project plugin development Skill, check for a missed global plugin Skill migration even if no template version change is needed. This cleanup does not advance defaultTemplateVersion.

1. Secure a way back

Git project: require a clean tree (ask the user to commit anything outstanding — do not stash or commit it for them), record git rev-parse HEAD, then git checkout -b template-upgrade-<target>. Editing the project directly is safe on a branch, and it is what lets typecheck/test/build actually run.

Not a Git project: do not touch it. Offer git init plus a commit, or a full copy in a scratch directory to upgrade and verify before moving back. Never proceed with no way back.

2. Identify the source

node -p "JSON.stringify(require('./package.json').nocobase, null, 2)"

templatePackage names the template; defaultTemplateVersion is BASE. Treat that package name as authoritative even when it names a template this Skill has never seen. If it is missing, the application predates the field: inspect templateKind, dependency history, plugin registrations, database directories, and published template versions, then confirm the source package before fetching. templateKind: "app" alone does not distinguish Default from Examples, while templateKind: "hub" identifies the discontinued Hub template, which has no newer version to upgrade to: tell the user rather than picking another template as BASE. If defaultTemplateVersion itself is missing or was bumped without a merge, the baseline is unknown — work it out with the user from Git history rather than guessing, since too old a baseline replays changes already present and too new a one skips changes never applied.

If nocobase.templatePackage is missing, use the confirmed package name for TEMPLATE instead of the manifest lookup below, then record it in the manifest during the agreed source merge.

3. Select the release channel and fetch both releases

Resolve the user's requested channel before choosing TARGET. An explicit version takes precedence. For a beta upgrade, use the template's beta dist-tag; for an explicit latest upgrade, use its latest dist-tag. If the user only asks to upgrade, retain the baseline's channel: use beta for a beta baseline and latest for a stable baseline; clarify other prerelease channels instead of guessing. State the selected channel and resolved version in the upgrade plan.

The tags are independent pointers, not a version ordering: beta tracks beta releases, while latest is npm's default tag and can still point to an older beta before a stable release exists. Do not assume latest is newer or stable, or choose the highest version across all channels. If the user asks for a stable release but latest resolves to a prerelease, explain that the tag does not provide a stable target and clarify before proceeding. A missing requested tag is not permission to fall back to another channel.

REGISTRY=https://registry.npmjs.org
TEMPLATE=$(node -p "require('./package.json').nocobase.templatePackage")
BASE=$(node -p "require('./package.json').nocobase.defaultTemplateVersion")
npm view "$TEMPLATE" dist-tags --json --registry="$REGISTRY"

# Set CHANNEL to beta or latest according to the selection above.
CHANNEL=beta
TARGET=$(npm view "$TEMPLATE@$CHANNEL" version --registry="$REGISTRY")
# For an explicitly requested version, assign that exact version to TARGET instead.

Use semantic version ordering to compare the resolved TARGET with BASE. If equal, there is no template upgrade; if older, report the result rather than performing an implicit downgrade. Resolve a tag once, then use that exact version for fetching, the source diff and defaultTemplateVersion, even if the tag moves during the upgrade. Fetch dependencies from the target template's manifest; do not independently move every @nocobase/* dependency to a dist-tag, since packages have separate versions and release schedules.

WORK=$(mktemp -d)

for VERSION in "$BASE" "$TARGET"; do
  npm pack "$TEMPLATE@$VERSION" --registry="$REGISTRY" --pack-destination "$WORK" >/dev/null
  mkdir -p "$WORK/$VERSION"
  tar -xzf "$WORK"/*"-$VERSION.tgz" -C "$WORK/$VERSION" --strip-components=1
done

Record the registry, selected channel or explicit version, exact BASE/TARGET versions, tarball integrity and source checkpoints. A missing target, missing required guidance package, invalid integrity or target not newer than BASE stops the upgrade before editing dependencies, source or the completion marker. Do not substitute a Git checkout, same-version snapshot or another channel.

These are published tarballs, not Git checkouts — they carry only what files publishes, and npm never publishes .gitignore. That is fine: both sides are missing the same things.

3a. Discover the target release’s requirements before editing

Read TARGET’s AGENTS.md and README.MD from the extracted package, even when the installed upgrade Skill is older. Those files can introduce new mandatory upgrade requirements. Resolve the @nocobase/app-skills range in TARGET’s manifest against the selected registry, fetch that exact package, record its version/integrity, and read its skills/nocobase-app-upgrade/SKILL.md and applicable references before planning the source merge. Fetching and reading a package does not require installing or synchronizing it into the application first. Keep the application’s installed old Skill and dependencies until the plan is agreed.

SKILLS_RANGE=$(node -p "const p=require('$WORK/$TARGET/package.json'); p.devDependencies?.['@nocobase/app-skills'] ?? p.dependencies?.['@nocobase/app-skills'] ?? ''")
# Stop if the target declares no guidance package; do not guess a replacement.
npm pack "@nocobase/app-skills@$SKILLS_RANGE" --registry="$REGISTRY" --ignore-scripts --json --pack-destination "$WORK"
# Extract the returned filename into a separate target-guidance directory; record version and integrity.
# Read target-guidance/skills/nocobase-app-upgrade/SKILL.md and its applicable references.

When target guidance changes an older workflow, include the target requirements in this same upgrade. In particular, list feedback requires reconciling copied components, every template and application-owned table/card request owner, translations and installed Registry copies; dependency installation or Skill synchronization alone does not implement it. Do not finish the upgrade and leave this as a separate page-patching task. Preserve application identity, grants, custom behavior and retained data.

Use versioned upgrade verification to distinguish candidate-package evidence from verification of a publicly released target.

4. Read what changed, and who else changed it

diff -rq "$WORK/$BASE" "$WORK/$TARGET"

Files ... differ is modified, Only in TARGET added, Only in BASE removed. Read the substantive ones with diff -u. Use the actual BASE → TARGET changes and the project's current state to decide what applies. The target template's @nocobase/app-skills dependency identifies the shared guidance shipped for that release; inspect that package's relevant references when a changed framework contract needs explanation. Check edge cases for generated configuration, synchronized Skills, and migration history that the template diff cannot describe. When the target package introduces the project plugin development Skill, read its migration procedure, inspect same-named global installations, and include their exact cleanup and recovery in the upgrade plan.

When the upgrade changes application migrations or registered plugins that supply migrations, read database upgrades during planning, before starting the target application. Review the affected packages' upgrade notes as well as the template diff: a dependency update can change database behavior without adding a migration file to the application. Include any documented checksum correction, data prerequisite, and irreversible migration in the upgrade and recovery plan. A Git branch protects source, not the database.

When BASE → TARGET changes Realtime contracts, read Realtime upgrades during planning and include application-owned consumers, custom plugins, workers and transport/test adapters in step 5. Topic authorization, ignored publication promises and recovery gaps can survive type checking; use the actual package contracts and project usage to decide which migration steps apply.

When BASE → TARGET changes notification contracts, read Notification upgrades during planning. Include application-owned test-send forms, API clients, permissions, log pages, E2E fixtures and custom channel extensions in step 5; distinguish removed TestAdapter APIs from deprecated registration and configuration APIs that remain compatible.

When the target adds standard form feedback, follow form feedback source upgrades. Reconcile copied components and application-owned form consumers as well as dependencies, and verify new and retained applications with the same scenarios.

When the template changes the permission workspace, follow Permission editor source upgrades. Merge copied permission models and translations while preserving application-specific descriptions, grants and role behavior; a dependency update alone does not update them.

When the template changes list-return behavior, read list navigation upgrades. Merge the routing context, breadcrumb and back-link sources together, and examine application-owned detail links and forms; updating dependencies alone does not update these copied sources.

When the template changes loading, empty, filtered or failed list feedback, follow list feedback source upgrades. Reconcile copied components, request owners, translations and business empty content together, and verify both new and upgraded applications with retained permissions and records.

Then ask the project which of those files it has also touched:

diff -rq "$WORK/$BASE" "$WORK/$TARGET" \
  | sed -n "s|^Files $WORK/$BASE/\(.*\) and .* differ$|\1|p" \
  | while read -r file; do
      if [ ! -f "$file" ]; then echo "gone:      $file"
      elif diff -q "$WORK/$BASE/$file" "$file" >/dev/null; then echo "untouched: $file"
      else echo "modified:  $file"; fi
    done

Show the user this listing, the version range, any manual actions identified from the changed contracts and project state, the removals from step 5, and the rollback. Include every removed @nocobase/* package, the application references and capabilities it supplies, and the proposed retention, migration, or removal. Get agreement on that plan before editing.

5. Check what the diff cannot show

Do this before editing, so its findings are in the plan. The template's files are consistent with each other after a change; the user's are not, and no diff points at them.

Check every direct @nocobase/* package dropped from the manifest, and check plugins dropped from any composition root even when the application never changed those files. Search application code, configuration, tests, and build scripts for the package name, imports, exports, services, routes, configuration keys, and other public contracts. For plugins, also complete the plugin usage review. When no usage is found, propose removal and obtain the user's confirmation before invoking the removal command; the command does not rewrite business code or configuration.

# For each `Only in BASE` file, and each export that vanished from a surviving file:
grep -hE '^export ' "$WORK/$BASE/<removed-file>"
diff -u "$WORK/$BASE/<file>" "$WORK/$TARGET/<file>" | grep -E '^-\s*export '

# Then search the user's own code for every name found:
grep -rn "<name>" client server cli database tests --include='*.ts' --include='*.tsx'

A hit outside the template's own files is a decision: migrate to the replacement the target added, agree with the user on what replaces a capability deliberately removed, or keep the package and affected file as application-owned code and say the template no longer maintains them. Changed signatures are the same class of problem — pnpm typecheck in step 8 is what catches those.

6. Work through the files

For each file read three versions — $WORK/$BASE/<file>, $WORK/$TARGET/<file>, and the project's — then write the result with Edit.

  • Untouched by the user — take the template's version for ordinary source. Manifests and plugin composition roots follow the edge-case rules, including the usage review from step 5, even when unchanged. Most ordinary files, including client/components/ui/ shadcn primitives, belong here.
  • Both changed it — express what the template was trying to achieve inside the user's version. Their code exists for a reason, so this is a merge of two intents, not a choice between them. If the template's change makes their customization unnecessary, say so rather than deleting it.
  • Template added a file — copy it in; if something already exists at that path, reconcile rather than overwrite.
  • Template removed a file — only after step 5.

The generator rewrites template identity into some files, so those files legitimately differ from both releases. Current candidates include client/runtime.ts, client/service-provider.ts, and the Examples template's server/providers/app-example.ts; inspect the project and generator behavior instead of treating this as an exhaustive list for future templates. Keep the application's name when taking a template change there — copying verbatim splits the i18n namespace. When a target removes one of these files, preserve any application-owned customization until step 5 establishes that it is unused or migrated.

A template upgrade is not a theme reset. Preserve application-owned visual customizations by default; apply non-conflicting presentation changes and obtain a decision before replacing a customized visual result. For theme or shell deltas, inspect the theme upgrade checks during planning and merging, not only at final verification. An explicit request to adopt the new default theme authorizes replacement only within the agreed visual scope.

When the right answer is unclear, stop and ask about the concrete conflict and options. Keep the unresolved files and recovery checkpoint, leave defaultTemplateVersion at BASE, and do not report a completed upgrade. The user is the only one who knows why their code is the way it is. Resume the same upgrade after the decision; never silently discard a business customization.

7. Reconcile what is not ordinary source

package.json, generated configuration, synchronized Skills, and the plugin composition roots have their own rules — see edge cases. For each user-confirmed @nocobase/* removal, run pnpm nocobase package remove @nocobase/example while the dependency is still declared, so the package manager updates the manifest and lockfile and the CLI cleans its Skills and plugin registrations. Do not delete only its manifest key; the edge-case reference covers older CLI versions and already-removed dependencies.

8. Finish

Keep defaultTemplateVersion at BASE while validating the merged source. It is a completion record, not a feature switch. Unresolved conflicts, missing target requirements, failed installation or failed acceptance must not advance it or produce a completion report.

pnpm install && pnpm dedupe && pnpm nocobase skills sync
pnpm typecheck && pnpm test && pnpm lint && pnpm build

pnpm install can retain older transitive dependencies in pnpm-lock.yaml even after the template raises a direct dependency. Run pnpm dedupe to refresh compatible resolutions before synchronizing Skills from the final node_modules. Review and include the resulting lockfile changes in the upgrade. If type checking still reports incompatible types from two versions of the same package, follow dependency resolution conflicts before changing application code.

After synchronization, complete the applicable global plugin Skill migration: verify the project replacement before removing the old global installation, then report cleanup and session reload requirements.

typecheck is doing real work here — it catches the broken import a removal left behind. Before starting the application against retained data, complete the applicable database upgrade checks; startup may apply migrations automatically. Then run the application and check what the delta touched: sign-in, the user's pages, navigation, locale switching, any new migration. Passing commands are not evidence the application still behaves. For a theme or shell change, also complete the theme upgrade checks; token changes alone do not verify the application-owned consumers.

For a Realtime contract change, complete the applicable Realtime acceptance checks, including access denial, reconnect catch-up and publication failure; a connected socket alone is insufficient evidence.

For a notification contract change, complete the applicable notification acceptance checks through business notifications, including delivery results, log permissions and inbox ownership. Preserve historical records and report which configured transports were exercised.

Before declaring completion, verify that the resolved runtime exports the target contracts, installed component copies and all request owners are connected, and applicable target acceptance checks pass with preserved customizations and data. Include both template-provided and application-owned lists and installed Registry copies. Compare retained business records, approval history, permissions and executed migration sources against the recovery checkpoint. If any required check fails, retain BASE and report the failure with recovery instructions.

Only after those checks pass, set defaultTemplateVersion to the exact TARGET selected in step 3, verify the final manifest and lockfile, and commit the reconciled source, dependencies and marker together. Report the registry/channel, exact source and guidance package versions and integrity, range merged, how each contested file was decided, manual actions and their validation, and how to roll back. State whether the target is a local candidate or a publicly released package.

Crossing several releases

Compare BASE directly with TARGET and merge the resulting changes once. Check the user's code against changed or removed contracts and preserve existing configuration, data, and migration history. If a compatibility step cannot be determined from the endpoints, inspect the relevant intermediate release or ask for the missing project context; do not assume every historical instruction applies.

When the target adds or changes the standard process UI sources, also follow standard process management source upgrades: confirm existing process pages actually consume the merged components, while preserving explicit user customizations, parameters, grants and history.

When the target introduces standard submission protection, follow submission source upgrades during planning and reconciliation. Dependency or version-marker changes alone do not update copied forms, custom actions or the application's receipt migrations. Verify both a fresh application and retained customized data.

How to use it

Copy the folder

Take nocobase/nocobase-app-upgrade from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.

Install what it needs

The instructions reference npm. Without those the skill loads but fails at the first command.