capacitor-app-upgrade-v5-to-v6 — Claude Code skill: Capacitor 5 to 6
Walks a Capacitor app from v5 to v6: runs npx cap migrate, then finishes the manual Android and iOS checklist.
npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a claude-codeWhat capacitor-app-upgrade-v5-to-v6 does
The skill kicks in when @capacitor/core sits at 5.x and you want 6.x. It reads a snapshot of package.json and lists the @capacitor/* versions it finds, so you know which branch you are starting from.
From there it runs the procedure: settle androidScheme before migrating, install @capacitor/cli@latest-6, run npx cap migrate, then work through every step the migration reports as failed. Platform fixes follow. On Android that means AGP 8.2.1, Gradle 8.2.1, compileSdk instead of compileSdkVersion, SDK 34. On iOS, local plugins need a CAPBridgeViewController subclass that registers them, and pinch zoom comes back only if you set zoomEnabled: true.
The scheme is where people get burned. Capacitor 6 defaults existing apps to https, and a new scheme means a new WebView origin, so localStorage, IndexedDB, cookies and service workers from the installed build stop being readable. If no androidScheme is set today, the skill advises adding server: { androidScheme: "http" } to keep user data. Also addListener now returns only Promise<PluginListenerHandle>, so h.remove() no longer compiles without an await. Have Node.js 18+, Xcode 15.0+, Android Studio Hedgehog 2023.1.1+ and JDK 17 ready.
What it helps with
- move an app from Capacitor 5 to 6 without hunting breaking changes by hand
- keep Android users logged in after the upgrade
- fix a local iOS plugin that reports "not implemented" post-upgrade
- repair TypeScript errors around
addListener(...).remove - bump Gradle, AGP and
compileSdkto what Capacitor 6 expects
Example prompts for the agent
- My
@capacitor/coreis 5.x — walk me through the upgrade to 6 - Android users got logged out after the upgrade, what do I fix?
- My local iOS plugin says plugin is not implemented on ios, register it properly
How to install capacitor-app-upgrade-v5-to-v6
1Skills CLI (Vercel)
npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a claude-code2Manually: put the files in place
~/.claude/skills/capacitor-app-upgrade-v5-to-v6/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/capacitor-app-upgrade-v5-to-v6/
1Skills CLI (Vercel)
npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a codex2Manually: put the files in place
.agents/skills/capacitor-app-upgrade-v5-to-v6/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a cursor2Manually: put the files in place
.cursor/skills/capacitor-app-upgrade-v5-to-v6/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install Cap-go/capgo-skills capacitor-app-upgrade-v5-to-v62Manually: put the files in place
.github/skills/capacitor-app-upgrade-v5-to-v6/SKILL.md1Skills CLI (Vercel)
npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a gemini-cli2Platform CLI
gemini skills install https://github.com/Cap-go/capgo-skills --path skills/capacitor-app-upgrade-v5-to-v6Manually: put the files in place
.devin/skills/capacitor-app-upgrade-v5-to-v6/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about capacitor-app-upgrade-v5-to-v6
How do I install capacitor-app-upgrade-v5-to-v6 in Claude?
Run npx skills add Cap-go/capgo-skills --skill capacitor-app-upgrade-v5-to-v6 -a claude-code. The skill lands in ~/.claude/skills/capacitor-app-upgrade-v5-to-v6/SKILL.md.
What does capacitor-app-upgrade-v5-to-v6 do?
It drives the Capacitor 5 to 6 migration: runs npx cap migrate, then closes the manual Android and iOS items and verifies with a build.
Why did Android user data disappear after the upgrade?
Capacitor 6 defaults existing apps to the https scheme, and a scheme change swaps the WebView origin. Restore the previous androidScheme value and localStorage plus cookies become readable again.
Source text
SKILL.md · MIT
---
name: capacitor-app-upgrade-v5-to-v6
description: Upgrades a Capacitor app from v5 to v6 using `npx cap migrate` from `@capacitor/cli@latest-6`, then the manual checklist - Node 18+, Xcode 15+, Android Studio Hedgehog, AGP 8.2.1, Gradle 8.2.1, compile/target SDK 34, `compileSdkVersion` to `compileSdk`, the `androidScheme` default flipping to `https` (data loss risk), iOS local plugins no longer auto-registered, iOS zoom disabled by default, and official plugin breaking changes (`addListener` returns only a Promise, Camera Photo Picker, Filesystem ctime/mtime numbers). Use when `@capacitor/core` is 5.x and the target is 6.x, or after the upgrade users are logged out on Android, a custom iOS plugin is "not implemented", or `addListener(...).remove` no longer compiles. Do not use for other major versions, plugin library upgrades, or non-Capacitor apps.
allowed-tools:
- Bash(node -e *)
---
# Capacitor App Upgrade v5 to v6
Move a Capacitor 5 app to Capacitor 6. Source of truth: https://capacitorjs.com/docs/updating/6-0
## When to Use
- `@capacitor/core` in the snapshot below is `5.x` and the user wants `6.x`.
- After upgrading: Android users lose localStorage/cookies, a local (non-npm) iOS plugin reports `"<Name>" plugin is not implemented on ios`, pinch-zoom stopped working on iOS, or TypeScript errors around `addListener`.
- The user asks for the exact 5 -> 6 checklist.
Do not use:
- App on 4.x -> `capacitor-app-upgrade-v4-to-v5` first. On 6.x -> `capacitor-app-upgrade-v6-to-v7`. Multi-hop planning -> `capacitor-app-upgrades`.
- Plugin library upgrade -> `capacitor-plugin-upgrade-v5-to-v6`.
- Moving iOS from CocoaPods to SPM (experimental in 6) -> `cocoapods-to-spm`.
## Live Project Snapshot
Current Capacitor packages from `package.json`:
!`node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@capacitor/'))out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"`
## References
Only load a reference when its topic is in play.
| File | Load when |
| --- | --- |
| `references/android.md` | Editing `variables.gradle`, `build.gradle`, wrapper, or Kotlin by hand |
| `references/plugins.md` | The app uses official `@capacitor/*` plugins or stores `addListener` results |
## Preflight
| Tool | Minimum for Capacitor 6 |
| --- | --- |
| Node.js | 18+ (latest LTS recommended) |
| Xcode | 15.0+ |
| Android Studio | Hedgehog 2023.1.1+ |
| Java (Gradle JDK) | 17 |
| AGP / Gradle | 8.2.1 / 8.2.1 |
| Android SDK | minSdk 22, compileSdk 34, targetSdk 34 |
| iOS deployment target | 13.0 (unchanged) |
```bash
node -v && xcodebuild -version && java -version
git status --short
grep -rn "androidScheme" capacitor.config.* # decide the scheme BEFORE migrating
```
## Procedure
1. Confirm 5.x from the snapshot.
2. **Decide `androidScheme` first** (judgement call, ask the user if unclear). Capacitor 6 defaults existing apps to `https`. Changing scheme changes the WebView origin, so localStorage, IndexedDB, cookies and service workers from the installed app are no longer readable.
- No `androidScheme` set today -> add `server: { androidScheme: "http" }` to keep user data.
- Already `"https"` -> the entry can be removed.
3. Run the automated migration:
```bash
npm i -D @capacitor/cli@latest-6
npx cap migrate
```
Read the output and finish every step it reports as failed.
4. **iOS**:
- Plugin classes are no longer auto-registered. npm plugins are handled by the CLI-generated list. Local plugins written in the app target (custom code guide) need a `CAPBridgeViewController` subclass that overrides `capacitorDidLoad()` and calls `bridge?.registerPluginInstance(MyPlugin())`, and `Main.storyboard` must use that subclass as the view controller's custom class.
- Zoom is disabled by default. If the app relied on pinch zoom, set `zoomEnabled: true` in the Capacitor config.
5. **Android**: apply `references/android.md` (AGP 8.2.1, Gradle 8.2.1, google-services 4.4.0, `compileSdk`, Kotlin 1.9.10).
6. Update all `@capacitor/*` plugins to `^6.0.0` and community plugins to their Capacitor 6 releases. Fix code per `references/plugins.md`.
7. Run verification.
## Traps
- `addListener` now returns only `Promise<PluginListenerHandle>`. `const h = Plugin.addListener(...); h.remove()` no longer compiles; use `const h = await Plugin.addListener(...)`.
- Camera now uses the Android Photo Picker. Gallery cancel rejects with `"User cancelled photos app"` on Android, like other platforms; update error matching.
- Filesystem `stat()` on iOS returns `ctime` / `mtime` as numbers, not strings.
- Do not remove `READ_MEDIA_IMAGES` / storage permissions if `saveToGallery: true` or another plugin needs them.
## Verification
```bash
grep -rn "androidScheme" capacitor.config.* # explicit decision recorded
grep -n "compileSdkVersion rootProject" android/app/build.gradle # expect none (now compileSdk)
grep -n "gradle:8.2.1\|google-services:4.4.0" android/build.gradle
grep -n "distributionUrl" android/gradle/wrapper/gradle-wrapper.properties # gradle-8.2.1
grep -n "SdkVersion" android/variables.gradle # 22 / 34 / 34
grep -rnE "= *[A-Za-z]+\.addListener\(" src/ # each must be awaited
grep -rn "registerPluginInstance" ios/App/App/ # present if the app has local plugins
npx cap sync
cd android && ./gradlew assembleDebug
```
Build and launch iOS in Xcode 15+. On a device that had the v5 build installed, upgrade in place and confirm login/localStorage survived.
## Error Handling
| Error | Fix |
| --- | --- |
| `Migrate can only be used on capacitor 5 and above, please use the CLI in Capacitor 5 to upgrade to 5 first` | Run `capacitor-app-upgrade-v4-to-v5` first. |
| `Capacitor 6 requires JDK 17 or higher. Some steps may fail.` | Set Gradle JDK to 17+. |
| `Unable to find "<text>" in <file>. Try updating it manually` | Apply the diff from `references/android.md`. |
| `"<Plugin>" plugin is not implemented on ios` (local plugin) | Register it in a `CAPBridgeViewController` subclass (step 4). |
| `Property 'remove' does not exist on type 'Promise<PluginListenerHandle>'` | `await` the `addListener` call. |
| Users logged out / data gone on Android | Scheme changed. Restore the previous `androidScheme` value. |
© Cap-go · MIT · Cap-go/capgo-skills