eas-build-and-submit
Configures EAS Build and Submit: eas.json profiles, remote build numbers, fingerprints, gated store submits.
Skill by zakariaf
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-eas-build-and-submit
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
Use cases: writing
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 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/eas-build-and-submit
What's inside
- Skill name
eas-build-and-submit- Description
- Configures EAS Build and Submit: eas.json profiles, remote build numbers, fingerprints, gated store submits. Use when editing eas.json, running eas build/submit, or a build fails. Not for local builds (ios-release-testflight) or OTA (ota-updates).
- License
- MIT
- Instructions
- 212 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Agent Skills spec issues
- files: referenced but missing: scripts/eas/release-preflight.ts
Files (51)
- SKILL.md
- eas-facts.json · assets/
- shared.json · assets/
- template-placeholders.json · assets/
- release-report.md · examples/
- build-and-submit-runbook.md · references/
- credentials-and-signing.md · references/
- eas-json.md · references/
- failure-playbook.md · references/
- versions-and-fingerprints.md · references/
- check-eas-build.mjs · scripts/
- check-eas-config.mjs · scripts/
- check-lib.mjs · scripts/
- eas-json.mjs · scripts/lib/
- repo-facts.mjs · scripts/lib/
- ship-placeholders.mjs · scripts/lib/
- selftest.mjs · scripts/
- eas.json · templates/
- eas-commands.test.ts · templates/scripts/eas/
- eas-commands.ts · templates/scripts/eas/
- eas-profile.test.ts · templates/scripts/eas/
- eas-profile.ts · templates/scripts/eas/
- release-plan.test.ts · templates/scripts/eas/
- release-plan.ts · templates/scripts/eas/
- release-preflight.ts · templates/scripts/eas/
- app-variant.test.ts · templates/src/config/
- app-variant.ts · templates/src/config/
- release.yml · tests/bases/app/.github/workflows/
- app.config.ts · tests/bases/app/
- dot-gitignore · tests/bases/app/
- dot-nvmrc · tests/bases/app/
- package.json · tests/bases/app/
- build-ios.json · tests/bases/build/dist/eas/
- builds.json · tests/bases/build/dist/eas/
- fingerprint-android.json · tests/bases/build/dist/eas/
- fingerprint-ios.json · tests/bases/build/dist/eas/
- SKILL.md · tests/bases/decoys/.agents/skills/release-helper/
- ship.sh · tests/bases/decoys/.agents/skills/release-helper/
- release.sh · tests/bases/decoys/skills/old-release/
- SKILL.md · tests/bases/decoys/vendor/kit/
- submit.sh · tests/bases/decoys/vendor/kit/
- CASES.json · tests/fixtures/eas-build-tags/
- SUITE.json · tests/fixtures/eas-build-tags/
- EXPECT.txt · tests/fixtures/eas-build-tags/good/
- TAGS.txt · tests/fixtures/eas-build-tags/good/
- CASES.json · tests/fixtures/eas-build/
- SUITE.json · tests/fixtures/eas-build/
- EXPECT.txt · tests/fixtures/eas-build/good/
- CASES.json · tests/fixtures/eas-config/
- SUITE.json · tests/fixtures/eas-config/
- EXPECT.txt · tests/fixtures/eas-config/good/
SKILL.md (first lines)
# EAS Build and Submit
An Expo app builds every variant on EAS from one checked `eas.json`, and a store build reaches
TestFlight and Google Play internal testing only after the gates passed, from the reviewed commit, with
a build number no store has seen and a fingerprint that matches the reviewed native inputs. Credentials
stay with EAS and the developer; the agent builds, proves and submits with the developer's word.
## Rules that must hold
1. **Nothing leaves the machine without the developer's word in this session.** A store `eas build`,
every `eas submit`, `eas build:version:set` and any `eas credentials` change ask first. *Why:* each
uploads, spends a build number or changes shared signing state, and none can be undone.
2. **eas.json is valid for the CLI it names.** `cli.version` is a floor `>= 24.10.0` (or newer), every key
and value passes EAS CLI's own schema (`image` only inside `ios`/`android`, `node` a full version),
and `extends` chains resolve. *Why:* EAS CLI refuses an invalid file only after a login, often in CI;
the checker and `eas config --eas-json-only` catch it offline in seconds.
3. **Build numbers are remote and only go up.** `cli.appVersionSource` is `remote`, every store profile
has `autoIncrement: true`, and the app config holds a literal `version: 'x.y.z'` (raised per store
release) and no `ios.buildNumber` or `android.versionCode`. *Why:* EAS keeps one counter per app id,
so two machines can never upload the same number (ITMS-90189, a used `versionCode`), and a number in
the file would only mislead.
4. **A build is exactly a commit.** `cli.requireCommit` is `true`, and store builds start from a clean
tree on the release branch. *Why:* without it EAS CLI copies uncommitted and untracked files into the
build, so its `gitCommitHash` lies and the review covered other code.
5. **A profile per variant (and per simulator build), and only `production` is a store build.** `development`,
`development-simulator`, `preview`, `preview-simulator` and `production` (templates/eas.json);
the store profile builds an Android app bundle, signs, and never sets `developmentClient`,
`withoutCredentials` or `ios.simulator`; internal profiles never build an AAB. *Why:* EAS defaults a
profile without `distribution` to `store`, Play takes only app bundles, and testers cannot install an
AAB from a link.
6. **Every build profile pins the project's Node.** `"node": "26.4.0"`, equal to `.nvmrc` (or an
`eas-build-pre-install` script that upgrades npm). *Why:* the SDK 57 images ship npm 10.9.8, which the <!-- stack-pin-ignore -->
`engines` field and the install policy refuse (`EBADENGINE`), and which ignores `min-release-age`.
7. **`submit.production` pins the production ids and reaches testers only.** `ios.ascAppId` (digits) and
`ios.bundleIdentifier`, `android.applicationId`, never a `.dev`/`.preview` id; Android `track` is
`internal` (or `alpha`/`beta`) with `releaseStatus` `completed` or `draft`. *Why:* a standalone
`eas submit` evaluates the app config without the profile's env and would look up the development
id; promotion and rollouts are store-console decisions (android-release-play).
8. **Credentials stay with EAS and the developer.** Managed credentials (`credentialsSource: remote`),
`--freeze-credentials` on every `eas build` (EAS Workflows build jobs have no such flag), no `appleId` login and no literal key path in `eas.json`
(EAS-stored keys or `$VARIABLES` from CI secrets); the agent never opens a `.p8`, `.p12`, keystore or
service-account file. *Why:* a leaked key publishes apps in the developer's name, and a build that
regenerates a certificate breaks every app that shares it.
9. **Gates first, then one named command.** An outward `eas build` runs after `npm run verify` or
`scripts/eas/release-preflight.ts`, and an `eas submit` after `check-eas-build` on its record, in the
same script or job, as a command, never only in a comment (an EAS Workflows `type: build` job
`needs:` the job that ran verify, a `type: submit` job the job that ran the record check); every
`eas build`/`eas submit` names `--profile` (a job: `params.profile`); EAS CLI is the global `eas`,
never `npx eas-cli`; no `eas submit --latest`; `--auto-submit` (`-s`) only from the store profile and
only for iOS; CI commands pass `--platform`, and `eas submit` `--non-interactive`. *Why:* `eas build`
defaults to `production`, `--latest` submits whatever finished last, verify proves the code but not
what EAS built, an auto-submitted Android bundle reaches Play before its gate read it, and
`eas submit` stays interactive even in CI.
10. **Only a build whose record proves it is submitted, and only the file its gate read.**
`check-eas-build` on `eas build:view <id> --json`: finished, store distribution, the production
profile, the reviewed commit, the production id, the app config's version, a build number above
every upload tag, and the fingerprint the preflight wrote. Then the record's artifact is downloaded
to `build/ios-release/export/app.ipa` / `build/release-android/app-release.aab`, the stores' own
gates read it (ios-release-testflight, android-release-play), and `eas submit --path <that file>`
uploads exactly those bytes. *Why:* the record is the only evidence of what EAS built, the artifact
gate the only evidence of what is inside it; a wrong variant or commit looks like success until
testers open it.
11. **The fingerprint decides between a build and an update, and nothing hides native inputs from it.**
Compare fingerprints of the same variant and platform (`eas fingerprint:compare --build-id <id>`);
`.fingerprintignore` never hides `package.json`, the lockfile, the app config, `plugins/`, `patches/`
or `node_modules/`, and `sourceSkips` never `ExpoConfigAll`. *Why:* a hidden native change ships as
an update to binaries that lack the code, and the build-record check loses its proof.
12. **Stops are never retried.** Credentials errors, agreements, HTTP 401/403, missing app records, a
used build number, a draft Play app, an `INVALID` processing state: one message with the step, the
exact error and the one action. *Why:* retries lock accounts, burn numbers and hide the real cause.
13. **Every submitted build is tagged from its record.** `git tag -a v1.4.0+ios.14 -m "App Store build 14"`
(and `+android.<n>`, "Play build N"), with the record's `appBuildVersion`, pushed only with the
developer's word. *Why:* each TestFlight and Play build traces back to its commit, and the next
record check compares against these numbers (git-commits-and-reporting owns the scheme).
## Workflow
1. **Choose the lane and list the human steps.** EAS is the default; a team that cannot use EAS takes the
local lane (ios-release-testflight, android-release-play) and this skill's checker prints NOT
APPLICABLE. Read [references/credentials-and-signing.md](references/credentials-and-signing.md) and
ask the developer, one step per message, for what is missing: accounts, `eas init` (writes
`extra.eas.projectId`), app records, signing and submit keys, `EXPO_TOKEN` for CI.
2. **Install EAS CLI** globally with the policy flags:
`npm install -g --min-release-age=7 --ignore-scripts eas-cli@24.10.0`, never `npx eas-cli` in the app
([references/build-and-submit-runbook.md](references/build-and-submit-runbook.md), "Install the CLI").
3. **Write eas.json** from `templates/eas.json`: fill `__ASC_APP_ID__` (the Apple ID number of the app
record) and `__APP_ID__` (the production id); keep an existing file's extra profiles and merge the
variant wiring app-variants-and-environment owns. Read [references/eas-json.md](references/eas-json.md)
for every key and the ownership table; leave `image` out (expo-sdk-upgrade's `auto` default).
Validate offline: `eas config --eas-json-only --profile production --platform ios --json --non-interactive`.
4. **Fix the version fields** in `app.config.ts`: a literal `version`, no `ios.buildNumber` or
`android.versionCode`. For an app with store history, ask the developer to run
`eas build:version:set` per platform with the last store numbers
([references/versions-and-fingerprints.md](references/versions-and-fingerprints.md)).
5. **Copy the release templates**: `templates/scripts/eas/` (`eas-profile.ts`, `eas-commands.ts`,
`release-plan.ts`, `release-preflight.ts` and the three tests) and, when missing,
`templates/src/config/app-variant.ts` with its test (the canonical resolver). Run
`npx jest scripts/eas --ci --maxWorkers=2`, `npm run typecheck` and `npx eslint scripts/eas --max-warnings 0`.
6. **Check the setup:** `node ${CLAUDE_SKILL_DIR}/scripts/check-eas-config.mjs .`; fix every `FAIL`
line and rerun until `RESULT: PASS`. Then app-variants-and-environment's `check-variants` and
expo-sdk-upgrade's `check-sdk-alignment` for the parts they own.
7. **Internal builds** (dev client, preview, simulator builds for E2E) need no preflight: the runbook's
table has each command.
8. **A store release**, step by step from the runbook: `check-eas-config.mjs . --release`; then
`node scripts/eas/release-preflight.ts --profile production --platform all --what-to-test "<text>"`,
which prints the sequence; then ask (rule 1, shape in [examples/release-report.md](examples/release-report.md));
then its build line, `eas build ... --json > dist/eas/builds.json` (no `--auto-submit`); then
`node ${CLAUDE_SKILL_DIR}/scripts/check-eas-build.mjs . --build dist/eas/builds.json --platform ios`
(and android); then its download and store-artifact gate lines (ios-release-testflight's
`check-store-artifact`, android-release-play's `check-store-aab`); then its submit lines,
`eas submit --profile production --platform <p> --path <gated file> --non-interactive` (What to Test
on iOS); then tag and report. The preflight's `--auto-submit` (iOS only: the build submits itself,
record checked afterwards) only when the developer explicitly agreed to skip the record check.
9. **Before an update instead of a build**, compare fingerprints
([references/versions-and-fingerprints.md](references/versions-and-fingerprints.md), "New build or
update?") and hand the update to ota-updates.
10. **On any failure** find the row in [references/failure-playbook.md](references/failure-playbook.md):
fix and rerun, or send the stop message and wait.From 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 (12 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
Cite this page
eas-build-and-submit skill. Agent Mart. https://agentmart.dev/skills/zakariaf-eas-build-and-submit (last updated 2026-10-24)