expo-sdk-upgrade
Moves an Expo app to the next SDK and Xcode/Android toolchain in one proven commit - expo install --fix, overrides, breaking changes.
Skill by zakariaf
Chalk Labs
Need help deploying expo-sdk-upgrade?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/zakariaf-expo-sdk-upgrade
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Node.js package
Network hosts it talks to 3
codeload.github.com· found in install commanddeveloper.android.com· found in codedeveloper.apple.com· found in code
Files it touches
~/.claude/skills/expo-sdk-upgrade/tmp/sdk-trigger-x
What's inside
- Skill name
expo-sdk-upgrade- Description
- Moves an Expo app to the next SDK and Xcode/Android toolchain in one proven commit - expo install --fix, overrides, breaking changes. Use when an SDK, Xcode or targetSdk upgrade is due. Not for one package (dependency-management).
- License
- MIT
- Instructions
- 213 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (70)
- SKILL.md
- expo-sdk-57-module-map.json · assets/
- expo-sdk-58-next-module-map.json · assets/
- sdk-lines.json · assets/
- sdk-lines.schema.json · assets/
- shared.json · assets/
- store-requirements.json · assets/
- expo-sdk-lines.json · examples/
- sdk-move-report.md · examples/
- runbook.md · references/
- sdk-58-changes.md · references/
- sdk-lines.md · references/
- toolchain.md · references/
- upgrade-policy.md · references/
- check-lib.mjs · scripts/
- check-sdk-alignment.mjs · scripts/
- check-sdk-trigger.mjs · scripts/
- sdk.mjs · scripts/lib/
- selftest.mjs · scripts/
- scene-support.test.ts · templates/scripts/config/
- scene-support.ts · templates/scripts/config/
- decoy.test.tsx · tests/bases/app-57/.agents/skills/vendored-skill/src/
- app.config.ts · tests/bases/app-57/
- eas.json · tests/bases/app-57/
- jest.config.js · tests/bases/app-57/
- package-lock.json · tests/bases/app-57/
- package.json · tests/bases/app-57/
- with-variant-marker.ts · tests/bases/app-57/plugins/
- decoy.ts · tests/bases/app-57/skills/demo-skill/plugins/
- _layout.tsx · tests/bases/app-57/src/app/
- complete-task.test.ts · tests/bases/app-57/src/features/tasks/
- complete-task.ts · tests/bases/app-57/src/features/tasks/
- swipe-row.tsx · tests/bases/app-57/src/features/tasks/components/
- tasks-screen.tsx · tests/bases/app-57/src/features/tasks/
- decoy.test.tsx · tests/bases/app-57/src/vendor/third-party-skill/
- app.config.ts · tests/bases/app-57/src/vendor/third-party-skill/plugins/
- decoy.test.tsx · tests/bases/monorepo-57/.agents/skills/vendored-skill/src/
- app.config.ts · tests/bases/monorepo-57/apps/notes/
- package.json · tests/bases/monorepo-57/apps/notes/
- _layout.tsx · tests/bases/monorepo-57/apps/notes/src/app/
- app.config.ts · tests/bases/monorepo-57/apps/tasks/
- package.json · tests/bases/monorepo-57/apps/tasks/
- _layout.tsx · tests/bases/monorepo-57/apps/tasks/src/app/
- jest.config.js · tests/bases/monorepo-57/
- package-lock.json · tests/bases/monorepo-57/
- package.json · tests/bases/monorepo-57/
- package.json · tests/bases/monorepo-57/packages/ui/
- swipe-row.tsx · tests/bases/monorepo-57/packages/ui/src/
- jest.config.js · tests/bases/sdk-58/
- package-lock.json · tests/bases/sdk-58/
- package.json · tests/bases/sdk-58/
- with-variant-marker.ts · tests/bases/sdk-58/plugins/
- swipe-row.tsx · tests/bases/sdk-58/src/features/tasks/components/
- facts.json · tests/bases/trigger-facts/
- CASES.json · tests/fixtures/check-sdk-alignment-58/
- SUITE.json · tests/fixtures/check-sdk-alignment-58/
- EXPECT.txt · tests/fixtures/check-sdk-alignment-58/good/
- CASES.json · tests/fixtures/check-sdk-alignment-monorepo/
- SUITE.json · tests/fixtures/check-sdk-alignment-monorepo/
- EXPECT.txt · tests/fixtures/check-sdk-alignment-monorepo/good/
- …and 10 more
SKILL.md (first lines)
# Expo SDK upgrade
Moves the app (every app and shared package, when multi-package) to the next Expo SDK, or the build
toolchain to another Xcode or Android level, in one proven step: only when the new SDK is stable and
old enough or a store deadline forces it, with every package, tool, override, code migration and
toolchain change in one commit, and two checkers that prove when a move is due and that the repo sits
on one SDK line.
## Rules that must hold
1. **Move only when the trigger holds:** npm `latest` (or the target's `sdk-<n>` tag) is the new SDK
and at least the repo's release age old (`.npmrc` `min-release-age`, 7 days at least, measured to
the minute as npm measures it), and so is every package the repo takes from its module map plus
the `@react-native/*` tools at the new React Native version (`check-sdk-trigger.mjs` reports
`upgrade-due`), and on a branch the whole repo passes the gate, iOS and Android release builds,
E2E and the visual baselines. `RESULT: PASS` from the trigger means no move is due (stay). Never a
preview, beta, release candidate or `next` release, never a release-age exclude for an SDK. *Why:*
previews break things, and the first patch releases fix what `.0` broke; an SDK is never urgent
enough for an exception.
2. **One SDK at a time, unless Expo's notes say to skip one; never an expo release the SDK's advisory
rules out.** Apps on SDK 55 go straight to SDK 57 and no app installs expo 57.0.8 or older (a
Hermes V1 memory regression with Worklets and Reanimated, in SDK 56 too); the SDK lines hold this <!-- stack-pin-ignore -->
as `skipFrom` and `minExpo`, the trigger picks the target from them and `expo-min` fails a release
below the floor. *Why:* skipping changes nothing else in the move, and the regression ships to
every user.
3. **Move the whole repo in one commit, on a branch.** *Why:* Expo supports one React Native version
per repo, and a half-moved tree can be neither tested nor rolled back cleanly.
4. **Expo-managed packages move only with `npx expo install expo@~<version>` then
`npx expo install --fix`** (in every app when multi-package). Never hand-edit an Expo-managed
specifier or install `react-native`, React, Reanimated, Worklets, Skia or Gesture Handler by hand.
*Why:* Expo tests one coherent native set per SDK, and `--fix` writes exactly that set.
5. **Everything that follows the SDK moves in the same commit:** the root tools in one
`npm install -D` (`jest-expo`, `eslint-config-expo`, `@react-native/jest-preset`,
`@react-native/eslint-plugin`, `@types/react`, `test-renderer`, and `jest`, `babel-jest`,
`@types/jest` when the SDK's jest-expo peers on a new Jest line), every root `overrides` key at the
version the app installs, `allowScripts`, the code migrations, eas.json images that name an SDK,
Android SDK pins that fell behind, and the app's `contracts/dependency-policy.json` rows. *Why:*
each one alone breaks the install (`ERESOLVE`), the tree (duplicate native modules) or a gate.
6. **Tools the SDK does not move stay:** TypeScript (6.0 on SDKs 56 to 58), ESLint, Prettier and
everything outside Expo's map keep their own held-back triggers (dependency-management). A tool
ahead of the SDK's line fails `held-back`; one behind a line the SDK needs fails `sdk-tooling`.
*Why:* two moves in one commit cannot be debugged.
7. **Readiness first:** run `check-sdk-alignment.mjs --target-sdk <next>` before the branch and fix
every `FAIL` (React Native or Jest APIs the next SDK removes, app config keys its schema dropped,
an Xcode too old) on the current SDK in its own commit; the `todo` lines (config plugin imports,
Jest config, builder gestures, image aliases, pins) change only in the move commit. *Why:* the
replacements already work on the old SDK, so the move commit stays about the move.
8. **When the SDK moves a library to a new API generation, migrate every user of it as a whole** in
the move commit (Gesture Handler 2 builder to 3 hooks: every component that builds gestures).
*Why:* hook and builder gestures cannot be related to each other, so a component that mixes them
loses the exclusive or simultaneous relations it depends on.
9. **The toolchain follows the SDK and is chosen by version.** Xcode through `DEVELOPER_DIR` on a Mac
(never `sudo xcode-select`) or an EAS image (`auto`, `sdk-<n>` or an exact name, never `latest`),
recorded in one place the checkers read; an Xcode major newer than the SDK supports gets that SDK's
extra step first (SDK 57 with Xcode 27 needs `ios.enableSceneSupport`, removed again on SDK 58;
SDKs 55 and 56 have no such option and stay on Xcode 26); Android compileSdk, targetSdk and minSdk
and the iOS deployment target follow the SDK, and an `expo-build-properties` pin never stays behind
them. *Why:* a floating image or a stale pin changes the binary without a commit, a deployment
target below the SDK's pods fails `pod install`, and an iOS 27 SDK build on the application life
cycle does not launch correctly on iOS 27.
10. **Store deadlines are triggers too:** an App Store minimum Xcode or a Google Play minimum
targetSdk in effect that the app does not meet fails `store-deadline` and is fixed by a toolchain
or SDK move. *Why:* the store rejects the next upload regardless of how stable the app is.
11. **Never loosen a gate or re-accept a golden or screenshot to get green.** Every diff is explained
by the change list and committed with a `Gate-Change:` trailer. *Why:* a silent visual or
behavioural regression ships to every user at once.
12. **Read the new versions' release notes, versioned docs and published packages, never memory.**
Put every new finding in the move report; when this skill's entry for the new SDK is missing or
pre-release, write the app's own `contracts/expo-sdk-lines.json` entry from the stable release.
*Why:* SDK facts change between previews (SDK 58's jest-expo switched to Jest 30 while SDK 58 was
still a pre-release).
13. **Stop and ask before the branch (one message with a default: start on the branch) and wait for
an explicit go before merging, pushing, EAS builds or uploads** (silence is never a go: the
branch waits unmerged). Installing Xcode, licences, simulator runtimes, JDKs and `sudo` are human
steps.
## Workflow
1. Read [references/upgrade-policy.md](references/upgrade-policy.md): the current and next line,
the trigger, store deadlines, what moves together, what never does.
2. Check the trigger: `node ${CLAUDE_SKILL_DIR}/scripts/check-sdk-trigger.mjs . --online
--save-facts reports/sdk-trigger.json` (offline: `--facts <saved file>`; with neither it exits 2).
Its `sdk` line names the target (the next SDK, or the one Expo says to move to: a `note` line
says so). `RESULT: PASS` means no move is due: its `wait` lines (`target-stable`, `target-age`,
`package-age`, `package-missing`) say why and from which moment it can change; stop and, if asked,
report "not yet" with that moment (message 1 of [examples/sdk-move-report.md](examples/sdk-move-report.md)).
`FAIL [upgrade-due]`: the move is due; keep its `plan` lines and continue. `FAIL [store-deadline]`:
a toolchain move is due; go to step 6.
3. Start green (the project gate, clean `git status`, and the plain
`node ${CLAUDE_SKILL_DIR}/scripts/check-sdk-alignment.mjs .` passing: the readiness scan checks
imports only against the target SDK's line), then scan readiness:
`node ${CLAUDE_SKILL_DIR}/scripts/check-sdk-alignment.mjs . --target-sdk <target>` (58 from SDK
57). Fix every `FAIL` on the current SDK in its own commit; the `todo` lines are the move commit's
work list.
4. Tell the developer (message 2 of the example) and continue unless told to wait.
5. Read [references/sdk-58-changes.md](references/sdk-58-changes.md) in full (or the release notes
of the target SDK, for 57 and later ones), then follow [references/runbook.md](references/runbook.md) steps 5 to 18: branch,
`npx expo install`, root tools in one command, overrides, approvals, code migrations (config plugin
imports, Jest resolver and Jest 30, Gesture Handler 3, scene-support removal), EAS images, Android
and iOS pins, the dependency policy rows and, when needed, the app's SDK line entry
([references/sdk-lines.md](references/sdk-lines.md)).
6. For a toolchain-only change (a new Xcode, an EAS image, an Android target, a store deadline) read
[references/toolchain.md](references/toolchain.md). SDK 57 with Xcode 27: copy
`templates/scripts/config/scene-support.ts` and its test to `scripts/config/`, import it in
`app.config.ts` with the extension, `import { addSceneSupport } from './scripts/config/scene-support.ts';`
(Expo loads `app.config.ts` through Node, which needs the `.ts`; without it `npx expo config`
fails with "Cannot find module"), wrap the plugin list with `addSceneSupport([...])`, then record
the new Xcode.
7. Verification loop (runbook "Verification loop"): `node ${CLAUDE_SKILL_DIR}/scripts/check-sdk-alignment.mjs .`
until `RESULT: PASS` (each `FAIL` names the file, the rule and the fix), `npx expo install --check`,
`npx expo-doctor` (an `install.exclude` entry only for a stale Expo suggestion, with its reason:
runbook failure table), `npm ls react react-native react-native-reanimated react-native-worklets`, the
gate, then a clean prebuild with Release builds on a named iOS simulator and a named Android
emulator (or EAS preview builds), E2E and the visual baselines (hand-offs below); open every diff.
8. Commit the move as one commit with its `Gate-Change:` trailer (runbook "Commit, report, merge"),
report with message 3 of the example, and merge or push only on the developer's go.
## Definition of doneFrom zakariaf/ReactNative-Skills, MIT.
More from zakariaf/ReactNative-Skills
- 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
android-release-play
zakariaf
Ships Android App Bundles to Google Play: upload key, Play App Signing, AAB gate, versionCode, tracks, rollout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
architecture-and-boundaries
zakariaf
Places app code in the src/ layout and checks import boundaries: one-way zones, pure core, ports with fakes, one composition root.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
async-safety
zakariaf
Prevents silent async bugs: effect races, stale results, lost promises, leaked listeners and timers, AbortSignal gaps.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
audio-and-haptics-feedback
zakariaf
Builds SFX and haptics behind ports.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
auth-and-secure-storage
zakariaf
Builds sign-in - tokens in expo-secure-store, shared refresh, protected routes, OAuth PKCE, Apple sign-in.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
background-tasks
zakariaf
Builds expo-background-task jobs: idempotent, budgeted runs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9
Signals
- Stars
- 11
- Forks
- 2
- Open issues
- 0
- Last commit (this folder)
- Oct 17, 2026 (14 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/zakariaf/ReactNative-Skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from zakariaf
- 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get expo-sdk-upgrade running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
expo-sdk-upgrade skill. Agent Mart. https://agentmart.dev/skills/zakariaf-expo-sdk-upgrade (last updated 2026-10-24)