Guide
Desktop app setup
What the app still needs to own.
Your app repository should stay boring: source code, package metadata, build commands, and runtime update checks.
Your configured runner owns build execution. ReleaseKit owns workflow scheduling, signing secret storage, artifacts, feeds, approvals, and rollback.
App Responsibilities
| Area | What to keep in the app |
|---|---|
| Source | Desktop app code and package metadata |
| Builds | release-kit.yml with ordered build steps, artifacts, targets, and required env names |
| Updates | Use the ReleaseKit app integration to check for promoted releases |
| UI | Show update availability, download, install, and restart states |
| Telemetry | Send product and updater analytics directly to PostHog |
ReleaseKit Responsibilities
| Area | What ReleaseKit owns |
|---|---|
| Workflows | Parse the DAG, queue ready jobs, issue scoped leases, and record results |
| Runners | Sign job submissions to the organization endpoint selected by the project |
| Secrets | Apple signing and app build secrets in the vault |
| Lanes | Production, Nightly, and Preview policy |
| Releases | Artifacts, feeds, approvals, promotion, and rollback |
Production approval only publishes to the Stable channel. Nightly is its own feed; Early Access users move only when you publish and promote a Nightly candidate.
Projects that want continuous Early Access delivery can enable Release every push under Release lanes. The GitHub App then turns pushes to the tracked Nightly branch into idempotent candidates and promotes them only after the candidate DAG succeeds. Candidate builds may overlap; versions remain permanently reserved, and an older candidate that finishes after a newer release is active is marked superseded instead of moving the Nightly channel backward. Version commits made by Release Kit are ignored by the push trigger, preventing release loops.
Do not hand-wire runner endpoints or release-control APIs into the shipped app. Runner selection is dashboard-only; the app should only know how to ask ReleaseKit whether an update is available.
Workflow
Put project jobs in release-kit.yml. Release Kit expands the dependency graph and matrices, snapshots the parsed workflow onto each candidate, and sends ready jobs to the project’s configured runner.
By default, Release Kit selects Production and Nightly versions and commits them to app.versionFiles. Custom vendor-fork sequences can remain cloud-owned with a declarative strategy:
app:
versionFiles:
- npm/package.json
version:
strategy: prerelease-triplet
label: sandbox
This strategy supports Production releases. The upstream triplet comes from the committed version in the first app.versionFiles entry at the resolved release-branch commit. Release Kit takes the fork suffix from its latest assigned or published version, including failed or cancelled candidates whose versions remain reserved. Without cloud history, the committed version initializes the sequence.
For example, if cloud history is 43.0.0-sandbox.1.3.16 and an upstream upgrade commits 44.2.0-sandbox.1.3.16, a patch release becomes 44.2.0-sandbox.1.3.17. A repository edit to the suffix does not reset or advance the cloud sequence. Patch, minor, and major requests apply only to the fork suffix. Release Kit rejects a repository upstream older than its latest reserved upstream, even if the repository suffix is larger. Upstream changes belong in reviewed source changes; there is no suffix-reset option.
The CLI baseline and candidate creation use this same policy. With existing cloud history, if a publish creates a version checkpoint PR, merge it and repeat the same bump request. While cloud history is unchanged, Release Kit recomputes the same version and verifies the merged checkpoint before creating the candidate. Once a candidate has reserved a version, a new publish advances the sequence; use the console retry action to retry that candidate.
Repositories that need executable resolution can instead declare app.version.run. The command must validate repository-specific rules and print exactly one committed semantic version. Release Kit records that version without applying its built-in lane naming rules, but verifies its publication identity before assigning a runner.
app:
root: .
versionFiles:
- npm/package.json
version:
run: node .release-kit/scripts/version.mjs
timeoutMinutes: 5
schemaVersion: 2
app:
root: radius
versionFiles:
- package.json
- radius/package.json
runtime:
node: "22"
pnpm: "10.24.0"
env:
required:
- MAIN_VITE_WORKOS_CLIENT_ID
- MAIN_VITE_INSPECTOR_API_BASE_URL
- MAIN_VITE_TCC_API_KEY
jobs:
build:
trigger: candidate
matrix:
platform: [darwin]
arch: [arm64, x64]
steps:
- name: Install
run: pnpm install --frozen-lockfile
- name: Build macOS artifacts
cwd: radius
timeoutMinutes: 45
run: pnpm run build && pnpm exec electron-builder --mac --${RELEASE_KIT_ARCH} --publish never
artifacts:
- radius/dist/*.dmg
- radius/dist/*.zip
- radius/dist/*.ymlApple Signing Credentials
Apple signing setup has one dashboard-guided path:
- Open the Apple signing setup in the ReleaseKit dashboard.
- Download the one-time setup credentials.
- Run
npx -y @sandbox-technologies/release-kit@latest apple setupon your Mac. - Follow the terminal while it creates the certificate request, opens Apple Developer, validates the returned
.cer, and uploads encrypted credentials.
ReleaseKit keeps the matching private key in the vault and leases signing material only to the scoped workflow job running on your configured runner.
Build Environment Variables
Add project-specific environment variables in the ReleaseKit project Environment variables page. The runner leases only the values required by that workflow job. Keep public build-time configuration in the repository when it is not secret, and declare required secret names under env.required so missing configuration fails before execution.
Start
npm install -g @sandbox-technologies/release-kit
release-kit login
release-kit previewWhen you are ready to ship, run:
release-kit publish productionProduction and Nightly wait for approval before feeds change. Preview is artifact-only.
For incident response details, see Instant rollback.