Cofounder CLI

Mobile Apps

Develop, test, build, and ship Expo mobile apps with EAS: previews, Maestro tests, store submissions, and over-the-air updates.

cofounder mobile runs an Expo (React Native) app's lifecycle on Expo Application Services (EAS): installable previews, Android and iOS builds, Maestro tests on emulators and simulators, TestFlight and Google Play submissions, and over-the-air (OTA) updates. The commands run the pinned eas CLI in a local app checkout, so EAS builds exactly the source you have. Every command takes --dir <app directory> (default: the current directory) and --json for structured results.

MCPCLIAPI
—cofounder mobile initPOST /cofounder-cli/v1/company/mobile/projects, POST /cofounder-cli/v1/company/mobile/projects/provision
—cofounder mobile statusGET /cofounder-cli/v1/company/mobile/jobs, GET /cofounder-cli/v1/company/mobile/jobs/{job_id}
——GET /cofounder-cli/v1/company/mobile/project, POST /cofounder-cli/v1/company/mobile/credentials, POST /cofounder-cli/v1/company/mobile/jobs, POST /cofounder-cli/v1/company/mobile/jobs/{job_id}/provider, POST /cofounder-cli/v1/company/mobile/jobs/{job_id}/outcome

The job and credential routes support the commands: each build, submission, update, rollback, and test is recorded as a Cofounder job keyed by its intent, so rerunning an interrupted command reuses the operation it already started.

Set up the app

init scaffolds or connects an Expo app and configures EAS for it. A new app's EAS project is created in the company's Cofounder-managed Expo organization, so no Expo account or login is needed; pass --account, or an Expo access token with --expo-token-stdin, to use your own Expo account instead. It writes eas.json profiles (development, development-simulator, simulator, preview, production; submit: beta, production), update channels, and Maestro wiring, and records the app on the company.

cofounder mobile init --create --dir apps/mobile \
  --bundle-id com.example.app --api-url https://api.example.com --json
cofounder mobile init --dir apps/mobile --account my-expo-org --json

Develop

The inner loop runs JavaScript in a development build. Build one once per native change, then let Metro serve JavaScript changes without another build:

cofounder mobile dev start --dir apps/mobile --api-url https://api.example.com --tunnel --json
cofounder mobile dev status --dir apps/mobile --json
cofounder mobile dev logs --dir apps/mobile --lines 100
cofounder mobile dev stop --dir apps/mobile

dev start runs Metro in the background and returns its URL, process id, and log path; it reports the running server instead of starting a second one. With --tunnel, Metro is also served at a public HTTPS URL for hosted simulators and phones on other networks.

Remote simulator

cofounder mobile simulator start --dir apps/mobile --dev --max-minutes 30 --json
cofounder mobile simulator exec --dir apps/mobile -- npx agent-device@latest open com.example.app --platform ios
cofounder mobile simulator exec --dir apps/mobile -- npx agent-device@latest screenshot shot.png
cofounder mobile simulator status --dir apps/mobile --json
cofounder mobile simulator stop --dir apps/mobile

simulator start runs the app on a remote iOS simulator or Android emulator on EAS (EAS Simulator, an Expo preview that the app's Expo account needs access to). It installs the newest simulator build matching the source's native fingerprint; --dev installs the development build and opens Metro's tunnel from dev start --tunnel, so edits reach the device live. It returns the session page and, on iOS, a live browser view. exec runs a controller command, such as agent-device's snapshot, press, or screenshot, against the session; agent-device acts on the app it opened, so open the app's bundle id first. A session bills until it stops or reaches --max-minutes.

Preview and test

cofounder mobile preview --dir apps/mobile --simulator --wait 1800 --json
cofounder mobile preview --dir apps/mobile --platform android --json
cofounder mobile test --dir apps/mobile --flow .maestro --wait 1800 --json

preview builds the preview profile (device installs) or, with --simulator, the simulator profile for automated tests. test runs Maestro flows on EAS emulators and simulators and needs an EAS paid plan; without --build, it picks the newest finished emulator or simulator build matching the source's native fingerprint.

Build and submit

cofounder mobile build --dir apps/mobile --platform all --wait 3600 --json
cofounder mobile submit --dir apps/mobile --track beta --wait 1800 --json
cofounder mobile submit --dir apps/mobile --track production --platform ios --build <build-id> --json

build uses the production profile unless you pass --profile. submit sends the newest finished store build (or --build): --track beta uploads to App Store Connect for TestFlight and to the Play internal testing track; --track production uploads to App Store Connect and creates a draft Play production release, so nothing goes live by itself.

Over-the-air updates

cofounder mobile update --dir apps/mobile --channel production --dry-run --json
cofounder mobile update --dir apps/mobile --channel production --message "Fix checkout copy" --json
cofounder mobile rollback --dir apps/mobile --channel production --json

Updates change JavaScript and assets only. update checks each platform's native runtime fingerprint against finished builds on the channel and refuses with ota_incompatible when a platform needs a new binary. rollback republishes the channel's previous update, or returns devices to the embedded bundle with --to-embedded.

Status and logs

cofounder mobile status --dir apps/mobile --json
cofounder mobile status --dir apps/mobile --job <job-id> --release --wait 600 --json
cofounder mobile logs --dir apps/mobile --job <job-id> --lines 200

status reads unfinished jobs from EAS and records their outcome; --release adds App Store Connect state for iOS submissions. Results carry stable error codes such as expo_auth_required, eas_plan_required, store_credentials_required, mobile_project_mismatch, and ota_incompatible.