# Executables

> Shipping a build as standalone launchers, no store involved.

Canonical: https://docs.extension.dev/publish/executables
This page as Markdown: https://docs.extension.dev/publish/executables.md
Section: Publish to stores
Siblings: [Publishing](https://docs.extension.dev/publish/overview.md) · [Chrome Web Store](https://docs.extension.dev/publish/chrome.md) · [Firefox Add-ons](https://docs.extension.dev/publish/firefox.md) · [Microsoft Edge Add-ons](https://docs.extension.dev/publish/edge.md)
Map of every page: https://docs.extension.dev/llms.txt · Whole corpus: https://docs.extension.dev/llms-full.txt

---

# Executables

An executable is a standalone launcher that starts a browser with the
extension preloaded. Reach for it when a build should reach people without a
store or a review queue: the download is the distribution.

## Quick start

```bash
curl -s https://www.extension.dev/api/projects/$PROJECT_ID/builds/<buildId>/artifacts \
  -H "Authorization: Bearer $EXTENSION_DEV_TOKEN"
```

The artifacts list carries a Windows, macOS and Linux launcher per browser
beside the extension packages. The same list renders on the build's page in
the console.


## How it works

### Which browsers get a launcher

Chrome, Edge and Firefox. Safari does not: a launcher works by starting a
browser with an unpacked extension, and Safari loads no unpacked extension
and speaks no remote protocol.

The build pipeline skips Safari by name, so a build with Safari enabled
produces a Safari artifact and no Safari executable. That is the pipeline
working, not a build that half ran. A Safari build ships through the App
Store instead.

### Formats

One executable per launcher browser and platform. Windows is the only
download that is not wrapped. The macOS bundle is a directory, and the Linux
archive carries the executable bit through a browser download, so both ship
as `tar.gz`. The Linux icon ships beside the binary as a sidecar `png`.

### Extension sources

The launcher carries its extension one of two ways, and which one you get
depends on which download you took.

**Embedded.** The extension bytes live inside the binary. The download is
the whole product, and it carries the build it came from for as long as it
exists. Every Windows `.exe`, every Linux archive and every Firefox launcher
is embedded. A newer build means a newer download.

**Remote.** The launcher fetches the extension over HTTPS into a per-user
cache and checks the bytes against a SHA-256 checksum published beside them.
It refuses to run if the bytes do not match or the checksum cannot be read.
Only the notarized macOS bundle for Chrome and Edge is remote, and only when
the channel zip is publicly readable. A private project gets an embedded
bundle instead.

A remote launcher refreshes its extension on next launch and follows its
channel. It is the one download that does, and it is the extension that
refreshes, never the launcher. To ask your copy whether it performs the
integrity check, run it with `--version` and read the line beginning
`answer:`.

The checksum is served from the same origin as the extension. It detects a
corrupted, stale or partially replaced download. It is not a signature over
the extension, and Apple's notarization says nothing about the extension
either: Apple notarizes the launcher bundle, and the extension arrives
afterward over the network.

### macOS and notarization

Windows and Linux executables download straight from any build. The macOS
app appears only after notarization at promote time, because a bundle that
is not notarized is reported as damaged on the recipient's machine. The
build's artifact list marks the bundle as awaiting notarization until then.

Notarization is part of the paid plan. On a plan that does not include it,
the promote reports the refusal `MACOS_NOTARIZATION_NOT_INCLUDED` inside its
own response. Nothing is signed, nothing is sent to Apple, and the Windows
and Linux downloads are unaffected.

Notarization runs on the platform's side with `rcodesign` on Linux. No Mac
is required. It is two phase: the promote signs and submits, then a sweep
every five minutes completes the notarization when Apple answers.

This is the launcher's signature, not Safari's. Safari's installer package
is signed on its own path at submit time.

### Notarize once, promote forever

Remote mode makes the launcher byte deterministic per workspace, project,
browser and channel. Notarize once, and every later promote refreshes the
extension zip behind the same signed app. On a cache hit the promote
publishes without contacting Apple at all.

## Reference

### Artifacts

| Platform | Artifact | Extension source |
| --- | --- | --- |
| Windows | `<browser>-extension-windows.exe` | Embedded |
| macOS | `<browser>-extension-macos.app`, delivered as a `tar.gz` | Remote for Chrome and Edge on a public channel, embedded otherwise |
| Linux | `<browser>-extension-linux`, delivered as a `tar.gz`, with the icon as a sidecar `png` | Embedded |

### Limits and refusals

| Item | Value |
| --- | --- |
| Launcher browsers | Chrome, Edge, Firefox |
| Remote-capable browsers | Chrome, Edge |
| Notarization sweep | Every five minutes |
| Notarization on a plan without it | `MACOS_NOTARIZATION_NOT_INCLUDED` under `notarization.refused` in the promote response |
| Integrity sidecar | The channel zip URL plus `.sha256`, published by the promote |

## When it fails

- **The macOS download is missing from a build.** That is not an error. It
  appears after promote-time notarization, not at build time, and only on a
  plan that includes notarization.
- **A remote launcher shows an error instead of opening a browser.** That is
  the integrity check: the zip at the channel URL did not match the sha256
  published beside it, or that checksum could not be read. Promote again,
  which republishes both together.
- **A Firefox launcher never updates itself.** Firefox has no remote mode. A
  Firefox launcher is always embedded, so a new build means a new download.
- **There is no Safari launcher in the downloads.** Safari has no launcher on
  any platform. Submit it to the App Store instead.
- **macOS reports the app as damaged.** The bundle was obtained outside the
  notarized download, for example a rebuilt tar. Ship the artifact the
  platform produced.

## Next

- [Publishing](/publish/overview) for store submissions
- [Channels](/builds/channels) for what promote means
- [HTTP API](/automate/api) for the artifacts endpoint
