x86_64 builds of SuperCmd ship arm64 esbuild binaries → all extensions fail to load on Intel/Rosetta Macs
Summary
The published macOS x64 build of SuperCmd contains only the arm64 native binary
of esbuild inside app.asar.unpacked. On Intel Macs (and on Apple Silicon when the
app runs under Rosetta 2) every extension that needs an on-demand build fails with:
Extension load failed: On-demand build failed for <ext>/<command>.
Expected output: <ext>/.sc-build/<command>.js.
Underlying error:
You installed esbuild for another platform than the one you're currently using.
…
Specifically the "@esbuild/darwin-arm64" package is present but this platform
needs the "@esbuild/darwin-x64" package instead.
Reproduction
- Download SuperCmd
1.0.25 for x64 (or any Intel/Rosetta Mac).
- Install any extension whose package contains TypeScript/JSX sources without a
pre-built .sc-build/. (Loading a local dev extension with ray develop
layout also reproduces it.)
- Launch the extension → error above.
Tested on macOS 13.6 (Darwin 22.6.0), SuperCmd.app reports as
Mach-O 64-bit executable x86_64.
Root cause
extension-runner.ts calls requireEsbuild() which loads esbuild from
app.asar.unpacked/node_modules/esbuild (top-level, 0.19.12) and — for the
nested @raycast/api copy — from
app.asar.unpacked/node_modules/@raycast/api/node_modules/esbuild (0.25.12).
Both unpacked directories ship only @esbuild/darwin-arm64:
$ file /Applications/SuperCmd.app/Contents/MacOS/SuperCmd
… Mach-O 64-bit executable x86_64
$ ls /Applications/SuperCmd.app/Contents/Resources/app.asar.unpacked/node_modules/@esbuild
darwin-arm64
$ ls .../@raycast/api/node_modules/@esbuild
darwin-arm64
$ file .../@esbuild/darwin-arm64/bin/esbuild
Mach-O 64-bit executable arm64
Both darwin-arm64 and darwin-x64 are optionalDependencies of esbuild.
When CI/dev packages the app on an Apple Silicon machine, npm installs only
@esbuild/darwin-arm64. electron-builder then bundles the same
node_modules/ into both the x64 and arm64 DMGs (because the JS code, asar
contents, and asarUnpack rules are arch-independent in your config), so the
x64 DMG ends up shipping an arm64 native binary it can never execute.
The misleading "package present but needs other platform" message comes from
esbuild's own platform check at runtime, not from a missing file.
The same bug exists for the nested 0.25.12 copy under @raycast/api.
Fix proposal
The bundled node_modules/ must contain both platform packages, for each
esbuild version that ships in the asar. There are a few clean ways to do it:
Option A — pin both platform packages explicitly (simplest)
Add the platform packages as regular dependencies of SuperCmd so npm always
installs them regardless of the build host. Use the version that matches the
hoisted esbuild you depend on (currently ^0.19.12):
For the @raycast/api nested copy (esbuild 0.25.12) the same can be enforced via
an overrides block so npm installs both platform packages at the nested
location too:
Option B — install missing optional deps in a beforePack hook
Add to package.json build config:
scripts/install-cross-arch-esbuild.mjs:
import { execSync } from 'node:child_process';
// Resolve the exact versions npm has hoisted/nested, then install the *missing*
// platform-specific @esbuild/* packages for the target arch into node_modules
// without disturbing the lockfile (use `npm install --no-save`).
const esbuildVersions = JSON.parse(execSync(
'npm ls esbuild --all --json --depth=10',
).toString()).dependencies; // walk and dedupe
for (const v of new Set(collectVersions(esbuildVersions))) {
for (const pkg of ['@esbuild/darwin-x64', '@esbuild/darwin-arm64']) {
execSync(`npm install --no-save ${pkg}@${v}`, { stdio: 'inherit' });
}
}
This is more robust (no version drift) but adds a script.
Option C — build x64 and arm64 in separate jobs
In GitHub Actions, run the x64 DMG step on a macos-13 (Intel) runner and the
arm64 DMG step on macos-14/macos-latest. Each job's npm install will pull
its own arch's optional dep. Simplest from a code-change perspective but
doubles CI time.
Workaround (for users hitting this today)
# fetch matching versions
mkdir -p /tmp/sc-esbuild-fix && cd /tmp/sc-esbuild-fix
npm pack @esbuild/darwin-x64@0.19.12 @esbuild/darwin-x64@0.25.12
mkdir -p v019 v025
tar -xzf esbuild-darwin-x64-0.19.12.tgz -C v019
tar -xzf esbuild-darwin-x64-0.25.12.tgz -C v025
# splice into the bundled node_modules
SC="/Applications/SuperCmd.app/Contents/Resources/app.asar.unpacked/node_modules"
sudo cp -R v019/package "$SC/@esbuild/darwin-x64"
sudo cp -R v025/package "$SC/@raycast/api/node_modules/@esbuild/darwin-x64"
# clear stale build artefacts
rm -rf <your-extension>/.sc-build
The reverse (darwin-arm64 on an arm64 host) shouldn't happen with current
npm, but the same fix applies — install whichever platform package is missing.
Environment
- SuperCmd: 1.0.25
- macOS: 13.6 (Ventura), Darwin 22.6.0
- Hardware: x86_64 (Intel) / Rosetta 2
file SuperCmd.app/Contents/MacOS/SuperCmd → Mach-O 64-bit executable x86_64
- Bundled esbuild versions: 0.19.12 (top-level), 0.25.12 (nested under @raycast/api)
x86_64 builds of SuperCmd ship arm64 esbuild binaries → all extensions fail to load on Intel/Rosetta Macs
Summary
The published macOS x64 build of SuperCmd contains only the arm64 native binary
of
esbuildinsideapp.asar.unpacked. On Intel Macs (and on Apple Silicon when theapp runs under Rosetta 2) every extension that needs an on-demand build fails with:
Reproduction
1.0.25for x64 (or any Intel/Rosetta Mac).pre-built
.sc-build/. (Loading a local dev extension withray developlayout also reproduces it.)
Tested on macOS 13.6 (Darwin 22.6.0), SuperCmd.app reports as
Mach-O 64-bit executable x86_64.Root cause
extension-runner.tscallsrequireEsbuild()which loads esbuild fromapp.asar.unpacked/node_modules/esbuild(top-level, 0.19.12) and — for thenested @raycast/api copy — from
app.asar.unpacked/node_modules/@raycast/api/node_modules/esbuild(0.25.12).Both unpacked directories ship only
@esbuild/darwin-arm64:Both
darwin-arm64anddarwin-x64areoptionalDependenciesofesbuild.When CI/dev packages the app on an Apple Silicon machine, npm installs only
@esbuild/darwin-arm64.electron-builderthen bundles the samenode_modules/into both the x64 and arm64 DMGs (because the JS code, asarcontents, and
asarUnpackrules are arch-independent in your config), so thex64 DMG ends up shipping an arm64 native binary it can never execute.
The misleading "package present but needs other platform" message comes from
esbuild's own platform check at runtime, not from a missing file.
The same bug exists for the nested 0.25.12 copy under
@raycast/api.Fix proposal
The bundled
node_modules/must contain both platform packages, for eachesbuild version that ships in the asar. There are a few clean ways to do it:
Option A — pin both platform packages explicitly (simplest)
Add the platform packages as regular dependencies of SuperCmd so npm always
installs them regardless of the build host. Use the version that matches the
hoisted
esbuildyou depend on (currently^0.19.12):For the @raycast/api nested copy (esbuild 0.25.12) the same can be enforced via
an
overridesblock so npm installs both platform packages at the nestedlocation too:
Option B — install missing optional deps in a
beforePackhookAdd to
package.jsonbuildconfig:scripts/install-cross-arch-esbuild.mjs:This is more robust (no version drift) but adds a script.
Option C — build x64 and arm64 in separate jobs
In GitHub Actions, run the x64 DMG step on a
macos-13(Intel) runner and thearm64 DMG step on
macos-14/macos-latest. Each job'snpm installwill pullits own arch's optional dep. Simplest from a code-change perspective but
doubles CI time.
Workaround (for users hitting this today)
The reverse (
darwin-arm64on an arm64 host) shouldn't happen with currentnpm, but the same fix applies — install whichever platform package is missing.
Environment
file SuperCmd.app/Contents/MacOS/SuperCmd→Mach-O 64-bit executable x86_64