Without the flag the app builds exactly as before: React Native's stock Hermes,
React Native's own JSI and the pkg-built CLI binaries (Release builds only),
so main's Podfile.lock, pkg config, entitlements, EAS and e2e workflows are
unchanged.
pod install with ORBIT_HERMES_CLI=1 (or "hermesCli": "true" in
Podfile.properties.json) opts into Hermes V1 from hermes-node's pin, its JSI,
and the orbit-cli launcher + orbit-cli.hbc in every configuration (yarn
archive:hermes / codesign:hermes). pod install records the choice in
Pods/.orbit-hermes-cli for the build phases, and without the flag puts React
Native's JSI back.
The app bundles the CLI as Contents/Resources/cli/ either way and runs
cli/orbit-cli when present, otherwise the pkg binary for the architecture.
hermes-node now provides fetch/Headers/Request/Response and AbortSignal
globals like Node, so the CLI runs the same code on both. The
macos-export-certificate-and-key addon ships in its normal layout with
bindings and file-uri-to-path instead of a patched loader. Bump hermes-node
to 5c1c723.
ipa-resign is obfuscated with a self-defending check that regex-tests
Function.prototype.toString() and spins forever on Hermes, which returns
"[bytecode]", and it builds a dynamic-import helper with
new Function('u', 'return import(u)'), which Hermes can't compile. A bundler
plugin prepends Hermes's 'show source' directive and a module-local Function
that turns that one shape into a require()-based import.
Also resolve ipa-resign's directory from its main entry (its exports hide
package.json) and pin esbuild as a devDependency.
- macos/scripts/hermes-node.sh fetches and builds a pinned hermes-node; the
Podfile builds Hermes from the facebook/hermes commit it pins
(RCT_HERMES_V1_ENABLED, REACT_NATIVE_OVERRIDE_HERMES_DIR) and checks that the
JSI vendored into react-native-macos matches
- Regenerate the react-native-macos patch without rename detection: the
hermes.h -> hermes-interfaces.h rename made patch-package fail on a clean
install
- apps/cli yarn archive builds dist/: universal orbit-cli launcher,
orbit-cli.hbc, the macos-export-certificate-and-key addon built for ARCHS
without bindings, and ipa-resign's helpers; codesign signs every Mach-O
with a timestamp. Drop pkg and the V8-only JIT entitlements
- Xcode's Build CLI phase (all configurations) builds it against the app's
hermesvm.framework; the app bundles it as Contents/Resources/cli and runs
cli/orbit-cli
- orbit shell-command recognizes the launcher (was process.pkg)
- Install node-fetch as global fetch when the runtime has none
- EAS: the CLI is built by the Xcode archive; install cmake/ninja. E2E: cache
hermes-node, run on CLI changes
- Remove the in-process spike
* [cli] Start remote sessions without a maximum duration
Orbit set a maximum duration of 30 minutes on each Expo Simulators session.
With no value, the session gets the maximum duration of the account's plan,
as it does from EAS CLI and expo.dev. --max-run-time still sets a shorter one.
* [cli] Add changelog entry for the session duration
Adds Expo Simulators sessions to Orbit as remote devices, and reworks the popover around accounts, projects and device actions.
- CLI: boot-device and install-and-launch accept an eas: device ID. New commands list-remote-simulators, list-remote-simulator-options, stop-remote-simulator and stop-device.
- Popover: an account row, a row of project tiles that can launch the latest app, a default device for each platform, buttons on device rows, and a Remote devices section with running and ended sessions and a default controller.
- Windows: New simulator session starts a session. The Settings pane Menu sets the sections, the order of devices and the hidden devices.
- Quit and log out ask first when sessions still run.
- Includes the fixes from the Windows and Linux tests (#391).
* [cli][menu-bar] Add option to install the orbit command in PATH
* Apply batched suggestions from code review
Co-authored-by: Tomasz Sapeta <[email protected]>
* [cli][menu-bar] Address review feedback on the orbit shell command
* Bump ipa-resign to 0.0.20
---------
Co-authored-by: Tomasz Sapeta <[email protected]>
* [cli][menu-bar] Auto-renew resigned apps every 7 days
Free Apple ID provisioning profiles expire after 7 days, so a resigned build
stops opening weekly. Track each resigned app and re-sign it automatically
before it expires; also add the App ID quota tooling repeated signing needs.
- Record store (ResignedApps): every resign is saved with its device, Apple
ID, managed original/resigned ipa copies, and profile expiry. The CLI gains
--managed-dir (keep a durable copy of the original ipa) and a
cleanup-resigned-apps command.
- Renewal engine (useResignedAppRenewals, mounted in Core): re-signs records
due within 48h on app start, a 6-hour tick, popover focus, and after
sign-in; installs the renewed build when the device is connected, else on
reconnect. A popover attention row prompts re-auth when the session expired.
- Settings "Resigned apps" section: expiry countdowns, per-app and global
auto-renew toggles, Renew now / Remove; DebugMenu dev actions.
- App ID management: list-app-ids / delete-app-id CLI, the "Manage Apple App
IDs" window, and the resign quota-recovery flow that opens it when the
10-App-IDs-per-7-days limit is hit.
Stacked on the base re-signing PR.
* [cli][menu-bar][eas-shared] Add 'Keep me signed 'in and app icons for resigned apps
* [cli][menu-bar][eas-shared] Handle the free Apple ID three-app limit and show a placeholder icon
* Bump ipa-resign to 0.0.18
* [cli][menu-bar][eas-shared] Check the free Apple ID app limit before installing and show app names
* [cli][menu-bar] Address review feedback on resigned app renewals
* [cli][menu-bar] Add iOS re-signing with a free Apple ID
Re-sign an installed build that fails code-signing so it runs on a personal
device, using a free Apple ID. When an install fails with
APPLE_APP_VERIFICATION_FAILED, Orbit offers to re-sign and install.
- CLI: `resign-ipa` and `apple-id-auth` (sign-in / verify-2fa with SMS
fallback / sign-out) commands, driven by ipa-resign.
- Menu-bar: the resign offer + determinate progress in the popover, an Apple
ID sign-in window (6-digit 2FA input, resend, SMS fallback), error-copy
mapping, first-install "Untrusted Developer" trust instructions, and an
Apple ID section in Settings (signed-in state + sign out).
- Session expiry is treated as an automatic logout: the stored Apple ID is
forgotten and every "signed in as" surface updates, with one-tap re-auth.
- Electron/macOS wiring for the ipa-resign native anisette + zsign helpers,
transient-env-var plumbing to pass the password to the CLI, and the
APPLE_APP_VERIFICATION_FAILED mapping that triggers the offer.
[email protected].
* [menu-bar] Fix Electron CI: ensure extraResource dirs exist; drop useless return
- forge.config: create ./bin and ./anisette in the generateAssets hook so
packaging (and Electron E2E, which runs 'yarn package' without
'build:helpers') does not fail with ENOENT on the missing extraResource
dirs. build:helpers still populates them for real builds.
- build-helpers: remove a no-useless-return that failed eslint --max-warnings 0.
* Bump ipa-resign to 0.0.13
* Fix CLI error handling
* Update AppleID auth UI
* Fix Apple ID persistance
* Fix Apple connection lost
* Fix opening settings menu
* Support paid developer accounts in resign copy and show the install step
* Detect builds that need resigning before attempting the install
* Add changelog entry
* [orbit] Add Wi-Fi pairing support for Android devices
Add the ability to pair and connect a physical Android device over Wi-Fi
using ADB wireless debugging pairing codes.
- eas-shared: add pairAndroidDeviceAsync / connectAndroidDeviceAsync ADB helpers
- common-types: add PairAndroidDeviceResult command type
- cli: add `pair-android-device` command (pairing address, code, optional connect address)
- menu-bar: add command wrapper and a "Pair Android Device" section in Settings
https://claude.ai/code/session_01QFVnqBsSN9GoNBed9rAzMV
* [orbit] Add QR code pairing for Android devices over Wi-Fi
Support Android's "Pair device with QR code" wireless debugging flow:
the app generates a QR code, the device scans it and advertises an mDNS
pairing service, which is discovered via `adb mdns services` to pair and
connect automatically.
- eas-shared: add getAdbMdnsServicesAsync / waitForAdbMdnsServiceAsync helpers
- cli: add `pair-android-device-qr` command that waits for the scan, pairs, and connects
- menu-bar: add QRCode component (qrcode-generator + react-native-svg) and a
QR code mode in the Settings pairing form
https://claude.ai/code/session_01QFVnqBsSN9GoNBed9rAzMV
* [cli] improve paring with code
* [menu-bar] Move PairAndroidDevice to a sepate window
* Polish UI
* Add changelog entry
* Unify pair-android-device commands
---------
Co-authored-by: Claude <[email protected]>
* [cli] Lazy-load command modules to speed up CLI startup
Each menu-bar action spawns a fresh CLI process, and index.ts eagerly
imported every command module up front. Because eas-shared is a barrel
that pulls in the whole device/build toolchain, even a trivial command
like list-devices paid the cost of loading download/launch/GraphQL code.
Defer the eas-shared/GraphQL-heavy command modules behind dynamic
import() inside their actions (matching the existing launch-update
pattern) so an invocation only loads the command actually being run.
Also drop the eager `Env` import from utils.ts in favor of a local
EXPO_MENU_BAR check; utils.ts is loaded on every invocation, and
importing Env from the eas-shared barrel alone dragged in the entire
package, defeating the lazy-loading above.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WzvKru3pz1AwhEFBXSnMgo
* [cli] Parallelize list-devices command
* Add changelog entry
---------
Co-authored-by: Claude <[email protected]>
The error thrown in launchUpdateOnIOSAsync was missing the word "devices", so it read "Launching updates on iOS physical is not supported yet". The matching guard in launchUpdateOnExpoGoIosAsync already reads "...iOS physical devices is not supported yet". Align the two messages.
Co-authored-by: Patrick Wehbe <[email protected]>
* [orbit] Install apps on physical iPhones from macOS, Windows & Linux
Enable installing already-signed builds onto a USB-connected iPhone from
all three desktop platforms, without requiring a paid Apple account or Xcode.
The usbmux-based install transport already existed and is cross-platform; this
un-gates it from macOS/Xcode and surfaces it everywhere:
- eas-shared: make the developer disk image mount and app launch best-effort in
runOnDevice (installation works without Xcode; launch is skipped on
Windows/Linux). Discover devices via Promise.allSettled so a missing usbmux
service surfaces a friendly, actionable error instead of crashing. Add a
cross-platform usbmuxd availability check and per-OS helper-software guidance.
- cli: guard simulator-only paths behind process.platform === 'darwin' so
list-devices and install-and-launch work for physical iPhones off macOS; add
an install-apple-device-support command (winget on Windows, pkexec usbmuxd on
Linux).
- menu-bar: add a "Show iOS devices" preference (on by default everywhere),
list physical devices independently of simulators, and show an
install-helper-software prompt when the Apple device service isn't reachable.
- common-types: add APPLE_DEVICE_USBMUXD_NOT_RUNNING / APPLE_DEVICE_NOT_PAIRED
error codes and helper guidance on the device-list error.
https://claude.ai/code/session_01TeUZg8NkPKBJN2RRQfAh3o
* Adjust comments
* [menu-bar] Consolidate iOS gating under a single showIosSimulators preference
Drop the separate showIosDevices preference. The single showIosSimulators
toggle now controls the whole iOS section (simulators on macOS, physical
iPhones everywhere) and defaults ON / is enabled on all platforms so connected
iPhones are discoverable on Windows and Linux.
https://claude.ai/code/session_01TeUZg8NkPKBJN2RRQfAh3o
* [eas-shared] Surface APPLE_DEVICE_USBMUXD_NOT_RUNNING when devicectl returns no devices
getConnectedDevicesAsync swallowed the usbmux "service not running" error on
Linux/Windows: the custom path already wraps the socket error as an
InternalError, but the guard only matched raw socket codes, and the native
devicectl path fulfils with [] off macOS, so the error was logged and dropped.
Re-throw user-facing InternalErrors from the custom path before the other
guards, and add a regression test.
https://claude.ai/code/session_01TeUZg8NkPKBJN2RRQfAh3o
* [eas-shared] Distinguish usbmuxd not-installed vs not-running on Linux
On Linux usbmuxd is socket/udev-activated and only runs while an Apple device is
attached, so an installed-but-stopped daemon previously produced the misleading
"install the usbmuxd daemon" guidance. Detect the installed binary and, when
present, tell the user to connect/trust the device or run
`sudo systemctl start usbmuxd` instead. Adds a `startCommand` to the helper
guidance, hides the menu-bar "Install" button when there's nothing to install,
updates the README, and covers both states with unit tests.
https://claude.ai/code/session_01TeUZg8NkPKBJN2RRQfAh3o
* [eas-shared] Fix extracting tar on Windows
* [orbit] Auto-install lighter Apple Mobile Device Support on Windows
Instead of opening a download page and asking the user to manually install
Apple's software, install the official, lightweight Apple Mobile Device Support
package (USB driver + device service only, no full iTunes/Apple Devices app) via
winget directly from the in-app prompt. Vendoring Apple's binaries isn't viable
(proprietary, signed kernel driver), so this uses Apple's official distribution.
- CLI install-apple-device-support: use winget id Apple.AppleMobileDeviceSupport
with --silent; surface a clear error when winget is missing so the UI can fall
back to the manual download page.
- Menu-bar prompt: run the install first (winget/pkexec) and only open the
download page as a fallback; refresh the device list after a successful install.
- Update guidance text, README, and unit tests.
https://claude.ai/code/session_01TeUZg8NkPKBJN2RRQfAh3o
* adjust manual launch message
* [orbit] Prompt to set up iOS device support during onboarding
On Windows/Linux first run, offer an opt-in to install the helper software
needed to install apps on a physical iPhone over USB, instead of leaving users
to discover it later.
- check-tools CLI reports a cross-platform `appleDevice` entry (usbmux
availability via validateAppleDeviceRequirementsAsync) carrying the same
install guidance the popover prompt uses.
- Onboarding shows an "Install apps on a physical iPhone?" section (Windows/Linux
only, when the tooling is missing) reusing AppleDeviceHelperPrompt; after a
successful install it re-runs the checks so the prompt clears.
https://claude.ai/code/session_01TeUZg8NkPKBJN2RRQfAh3o
* Fix opening IPAs on linux
* Adjust onboarding
* Install Apple Mobile Device Support during onboarding
* [menu-bar][electron] Fix Alert custom onPress
* adjust usbmux message
* Make iOS install less noisy on Windows
* Add changelog entry
---------
Co-authored-by: Claude <[email protected]>
* [menu-bar]: invert noAudio flag to audio for boot device configuration
* [cli]: rename noAudio parameter to audio to align with intended boolean logic
* [eas-shared]: rename noAudio option to audio to align with emulator flag logic
* [eas-shared] Improve resilience against weird simulator states
The simulator can be in a Shutdown or transitional state when Orbit
tries to install an app, causing "Unable to lookup in current state:
Shutdown" errors (CoreSimulator.SimError code 405).
Changes:
- ensureSimulatorBootedAsync now polls until simulator reports Booted
after issuing `simctl boot`, with a 60s timeout
- Handle race condition where simulator gets booted by another process
("Unable to boot device in current state: Booted")
- installAppAsync retries up to 3 times on transient simulator state
errors with 2s delay between attempts
- CLI's installAndLaunchIOSAppAsync now boots the simulator before
attempting install (was previously missing)
- Add SIMULATOR_NOT_READY error code for clearer error identification
https://claude.ai/code/session_016zo1GKjHDxWfKCmJ7uoB1X
* simplify logic
* Add changelog entry
---------
Co-authored-by: Claude <[email protected]>
* [cli] Warn user when trying to an iOS app in a incompatible device
* Prevent detectIOSAppType from erroring out
* Apply suggestions from code review
Co-authored-by: Brent Vatne <[email protected]>
* Add changelog entry
---------
Co-authored-by: Brent Vatne <[email protected]>