Installation
Usage
overlayed bundles, overlayed jobs and overlayed releases each take a
subcommand, e.g. overlayed releases create. Run a group on its own, or add --help, to list its subcommands.
Authentication
You can authenticate in two ways:- Interactive login - Run
overlayed loginto authenticate via browser - Environment variable - Set
OVERLAYED_API_KEYfor CI/CD or programmatic use
Multiple Accounts
Eachoverlayed login adds an account instead of replacing the previous one, so you can stay logged in to several
applications at once, including ones owned by different emails. Run overlayed accounts to see
them.
Commands pick the account by application: the one whose API key is scoped to the applicationId in the nearest
overlayed.config.ts, or to OVERLAYED_APPLICATION_ID if that is set. When that is not the
account you last logged in to:
- In a terminal, the CLI asks before switching to it, and remembers the switch as the new default.
- Without a terminal (CI, scripts, coding agents), the CLI uses it for that run and leaves the default alone. Runs in different applications can therefore happen in parallel without affecting each other.
Choosing the Application
overlayed bundle uploads to the applicationId in your overlayed.config.ts. Every other
command works on the first of these that is set:
OVERLAYED_APPLICATION_ID- The
applicationIdin the nearest overlayed.config.ts - The application the API key is scoped to, when it is scoped to exactly one
OVERLAYED_API_KEY and OVERLAYED_APPLICATION_ID are enough. If
the application named by (1) or (2) isn’t one the API key can reach, the command fails and says so, rather than sending
requests that would be refused. A key scoped to several applications needs OVERLAYED_APPLICATION_ID (or a config file)
to pick one.
Running in CI
The CLI behaves the same in a terminal and in CI, with these differences when there is no terminal to ask in (CI runs, scripts, coding agents):- Nothing prompts. A command that would ask for something fails instead, naming the flag or environment variable
that answers it:
overlayed bundleneeds--app/--siteand a bundle name, andoverlayed loginasks you to setOVERLAYED_API_KEY. - Public channels don’t ask for confirmation. In a terminal, releasing, promoting, publishing, raising a rollout or
cancelling on a public channel asks first.
--yesskips the question; without a terminal the command goes ahead, since whoever wrote the pipeline has already decided. Private channels never ask.
Exit Codes
--help, --version and a command group run without a subcommand exit 0.
Waiting
overlayed bundle, releases create, releases promote, jobs wait and releases wait wait for the build to finish
and fail if it doesn’t succeed. They give up after 15 minutes. Change that with --wait-timeout <seconds> or the
OVERLAYED_WAIT_TIMEOUT environment variable (the flag wins). A wait that times out exits 1, and the build carries on
on the server: wait on it again with overlayed jobs wait or overlayed releases wait.
JSON Output
Add the global--json flag to any command to print only its result, as one JSON document on stdout. Progress,
warnings and prompts go to stderr. The result includes ids, statuses and dashboard links, so a later step can pick them
up:
outcome is how a wait ended (succeeded, failed, cancelled, revoked or timed_out, or null when nothing was
waited on), and error says why the command fails, or is null. A release has its id, version, status, draft flag, channel,
bundle, rollout, minimum app version and dashboard link; releases list, show, latest and wait add commit_hash,
has_modern_installer and created_at. A failed job carries its latest run’s message as build_error.
A command that fails prints { "error": { "message": … } }, with status, kind, required_permissions, issues or
missing_urls when the API gave them. A command that fails after doing some of its work (a build that failed, a release that didn’t
build) prints its usual result instead, so the ids it produced aren’t lost, with the failure in it: error for the
release commands, each bundle’s error for bundle, and release_error for bundle --release. Either way it exits
1; check the exit code rather than a field.
When releases promote or bundle --release stopped because the API returned an error creating a release, error_kind
(release_error_kind for bundle --release) is that error’s kind, the same as kind above; otherwise it’s null.
A release to a public channel is refused while the application has no privacy policy URL or terms of service URL, drafts
included. The release commands then say which is missing and where to add it (Settings › Application in the dashboard),
and --json gives kind public_release_missing_legal_urls with missing_urls: privacy_url, terms_url or both.
releases promote puts missing_urls beside error_kind, and bundle --release puts release_missing_urls beside
release_error_kind.
Update Checks
Every command checks npm for a newer@overlayed/cli, and overlayed bundle also checks the @overlayed/app and
@overlayed/electron versions installed in your project. If any are out of date, a warning is printed to stderr before
the command runs. The check never fails a command: if the registry can’t be reached or doesn’t answer within 1.5
seconds, it is skipped silently. Snapshot installs (e.g. @canary) are not checked, and neither are --help and
--version, which print without touching the network.
Config File Lookup
Commands that need your overlayed.config.ts look for it (.ts, .mts or .js) in this
order:
- The current directory, then each parent directory. The nearest one is used.
- If none is found, up to 3 directories below the current directory (so running from a monorepo root finds
packages/app/overlayed.config.ts).node_modulesand.gitare skipped.
Commands
overlayed login
Authenticate with the Overlayed platform. This is required for local development.
Opens the dashboard’s API key creation page with the key name prefilled as cli and these permissions preselected, so
the resulting key can bundle and release without further setup:
The permissions are only a starting point — add or remove any of them before creating the key. Your role must hold a
permission for the key to have it: Developers can’t create or update releases, so they untick those two and get a key
that bundles and reads but doesn’t release.
Without a terminal
overlayed login fails: set OVERLAYED_API_KEY instead (see Running in CI).
overlayed logout
Log out of the account that commands in the current directory use. Only that one stored account is removed; other
accounts stay logged in, including others with the same email. No request is made, so an expired or revoked key can
still be removed.
Options:
--email and --application can be combined to match accounts that have both.
overlayed accounts
List the accounts you are logged in to, with the application each API key is scoped to and the last four characters of
the key.
* marks the account that commands run from the current directory use. (default) marks the account you last logged in
or switched to, which is used when no application can be determined. See Multiple Accounts.
overlayed whoami
Display information about the currently authenticated user.
overlayed init
Initialize your local development environment. This command:
- Fetches your application metadata from the Overlayed API
- Creates a
.overlayed/meta.jsonfile with cached application data - Must be run after
overlayed loginand from your project (see how the config file is found)
overlayed bundle
Bundles the app and site for deployment. This command looks for an overlayed.config.ts
file (see how the config file is found), uploads a bundle of each, and waits for them to be
processed. With --release it then releases them to a channel.
Options:
With no
--app or --site, a terminal asks which to bundle. Without a terminal (or with --json), pass --app and/or
--site, each with a name unless --no-wait is set.
Each uploaded bundle prints its bundle id and build job id, with links to them in the dashboard. A build that fails, is
cancelled or is still running when the wait times out makes the command exit 1.
Examples:
Bundle and release
--release <channel> releases what was just bundled, once its build succeeds:
It also takes the release options (
--draft, --rollout, --rollout-start, --rollout-end,
--public-notes, --internal-notes, --min-app-version, --yes), which apply only with --release.
- The channel and versions are worked out, and a public channel is confirmed, before anything is uploaded.
- With both
--appand--site, the app is released first and waited on, then the site, with its minimum app version set to the new app version.--min-app-versionis for a site bundled on its own. - If a build fails, nothing is released and the command exits
1. - If the app release goes out but the site’s doesn’t, the command exits
1and names the app release. If the site’s release was refused, failed or was cancelled, it also prints theoverlayed releases createcommand that releases the site on its own. If the wait gave up while the site was still building, follow it withoverlayed releases wait. --releaseneeds--app/--sitegiven explicitly, waits for the builds (so not with--no-wait), and can’t be used with--debugor--debug-files.- A channel with auto-release on bundle turned on is refused before uploading: the platform already releases every
bundle built to it, so
--releasewould release it twice. Leave that channel to auto-release, or turn the setting off.
--json the result has bundles, each with its own error, plus releases and release_error (why the
releases stopped, or null; a failed build releases nothing and leaves it null, with the build’s error set
instead), and release_error_kind (the API error’s kind, see JSON output).
overlayed bundles
overlayed jobs
Every uploaded bundle is processed by a build job.
overlayed releases
A release puts a bundle on a channel. Releasing an app builds its installer;
releasing a site deploys it. Each release builds on the server after it’s created.
overlayed releases create
Release a bundle to a channel.
Plus the release options. It prints the release’s id, version, channel, status, rollout and a link
to it in the dashboard (with
--json: { "release": …, "outcome": …, "error": … }), and exits 1 unless the release
built (or, with --no-wait, was created).
overlayed releases promote
Release a release’s bundle on another channel, e.g. from beta to stable, so what was tested is exactly what ships.
Like the dashboard’s Promote, it creates a new release of the same bundle on the target channel, which builds there.
Plus the release options. The new release keeps the source’s public and internal notes unless
--public-notes/--internal-notes give new ones, and a site promoted on its own keeps its minimum app version.
With --type both the app is promoted first and waited on, then the site, with its minimum app version set to the
promoted app’s version. If the app doesn’t build, the site isn’t promoted. With --no-wait both are created at once, as
the dashboard does. With --json the result is { "releases": [ … ], "error": …, "error_kind": … }.
overlayed releases publish
overlayed releases rollout
overlayed releases cancel
publish or rollout either.
overlayed releases list, latest, show, wait
overlayed releases download
classic (the default), or modern for the branded installer when the
release has one. It is saved under the installer’s own file name in the current directory, or at --output. --url
prints a download link instead, which expires after 5 minutes, plus any headers it needs.
Release Versions
Every release needs a version, given in one of two ways:- A version, like
1.4.0or2.0.0-beta.1: SemVer, with no leading zeros. - A bump:
patch,minorormajorbumps the channel’s latest release of the same bundle type (drafts included; cancelled and failed releases don’t count). A channel with no release of that type bumps from0.0.0, sopatchgives0.0.1.
Release Options
releases create, releases promote and bundle --release take these:
Rollout
--rollout <percent>sends the release to that share of users. It can’t be combined with a window.--rollout-startand--rollout-endmake a window: 0% of users at the start, rising evenly to 100% at the end.--rollout-startalone releases to everyone at that time.--rollout-endalone starts the window when the release is created.- With no rollout option, a release uses its channel’s default rollout duration, if the channel has one, as a window
starting when it’s created; otherwise it goes to everyone at once. A draft gets no window until it’s published:
overlayed releases publishthen opens the channel’s default window from that moment, as the platform’s automatic releases do.
Migrating to 2.0
CLI 2.0 changes what CI pipelines see:overlayed bundleexits1when a build fails, is cancelled or times out. It used to exit0in all three cases.- Waiting gives up after 15 minutes by default instead of about 5 (see Waiting).
- Without a terminal, commands fail instead of prompting (see Running in CI).

