Skip to content
Agentmart
Submit a tool

eas-build-and-submit

Configures EAS Build and Submit: eas.json profiles, remote build numbers, fingerprints, gated store submits.

Skill by zakariaf

IndexedMIT★ 11
Write a review

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.

We use your email only for this newsletter. Privacy

About

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).

Use cases: writing

No 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

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
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from zakariaf

Cite this page

eas-build-and-submit skill. Agent Mart. https://agentmart.dev/skills/zakariaf-eas-build-and-submit (last updated 2026-10-24)