Desktop application shell for Agent Zero. This Electron app automatically downloads and displays the latest content from GitHub releases.
The app consists of two parts:
-
Shell (
shell/) - The Electron executable that handles:- Window management
- Checking for updates via GitHub Releases API
- Downloading and caching content
- Loading the downloaded content
-
Content (
app/) - The actual application UI:- HTML, CSS, and JavaScript files
- Bundled into
content.jsonon each release - Downloaded at runtime by the shell
Note: The
app/folder exists in this repo as source content for the GitHub Action to bundle. The built executable does NOT include these files - it downloads them from GitHub Releases at runtime. This enables "build once, update forever" - content updates are deployed by creating new releases, not rebuilding the app.
Project non-negotiables live in .specify/memory/constitution.md (Electron security model, shell/content contract, and release semantics). When making changes to shell/, forge.config.js, or release workflows, ensure the release tag reflects the change scope (MAJOR for shell/workflow behavior changes).
This project can be tested end-to-end in your fork (including GitHub Releases + Actions) without rewriting code.
- The packaged shell (
shell/) downloadscontent.jsonfrom GitHub Releases at runtime. - In your fork, you want the shell you built to download content from your fork's releases.
When you build/run from your fork, the app will default to using your fork as the content source because build scripts generate shell/build-info.json from your git origin remote.
You can force the content source repo explicitly:
A0_LAUNCHER_GITHUB_REPO="your-user/a0-launcher" npm startThis is also useful when running a vendor-built executable but testing content from your fork.
- Enable Actions in your fork (GitHub UI: "Actions" tab).
- To test building executables without creating a release:
- Run the
Build Executablesworkflow withworkflow_dispatch. - Provide an input version like
v99.0.0. - Download artifacts from the workflow run (macOS, Windows, Linux).
- macOS signing/notarization secrets are optional for fork testing - the workflow builds unsigned mac artifacts when secrets are absent.
- Run the
- To test the full release pipeline:
- Create a GitHub Release in your fork with a tag like
v99.0.0. Bundle Contentuploadscontent.jsonto the release.Build Executablesuploads executables to the release (major changes build fresh; minor/patch reuse previous major's assets).
- Create a GitHub Release in your fork with a tag like
This repo includes a "Service Versions" screen (Docker-backed) that can install, update, switch, and roll back the backend service.
Notes:
- Requires Docker Desktop/Engine installed and running.
- Optional dev overrides:
A0_BACKEND_GITHUB_REPO="owner/repo"(override the GitHub Releases catalog source)A0_BACKEND_IMAGE_REPO="namespace/name"(override the image repo to pull/run)
- The UI in
app/is bundled intocontent.jsonby CI and downloaded at runtime. For end-to-end UI testing, publish a release with yourcontent.jsonand run withA0_LAUNCHER_GITHUB_REPO="your-user/a0-launcher"(see "Fork Testing (End-to-End)").
- Node.js 20+
- npm 9+
npm installnpm startBy default, npm start loads UI content by downloading content.json from GitHub Releases (or from cache in offline mode).
For fast UI iteration, you can force the shell to load the local app/ directory directly.
A0_LAUNCHER_USE_LOCAL_CONTENT=1: Use the current working directory (CWD) as the repo root if it looks like an A0 Launcher checkout (must containapp/index.htmlandpackage.json).A0_LAUNCHER_LOCAL_REPO=<path>: Use a specific local repo path (absolute path, or relative to CWD). Same repo-root validation applies.
Precedence:
- If
A0_LAUNCHER_LOCAL_REPOis set and valid, it wins. - Otherwise if
A0_LAUNCHER_USE_LOCAL_CONTENT=1and CWD is valid, CWD is used. - Otherwise the shell falls back to downloading
content.jsonfrom GitHub Releases.
Examples:
# Use the current repo checkout as UI content source
A0_LAUNCHER_USE_LOCAL_CONTENT=1 npm start
# Use a specific local checkout (absolute or relative path)
A0_LAUNCHER_LOCAL_REPO=. npm start
A0_LAUNCHER_LOCAL_REPO=/home/rafael/Workspace/Repos/rafael/a0-launcher npm start# All platforms (on respective OS)
npm run make
# Platform specific
npm run make:mac
npm run make:win
npm run make:linuxFor day-to-day development and fork testing, you typically want an unsigned build:
SKIP_SIGNING=1 npm run make:macRelease-grade macOS builds (signed + notarized) require CI secrets:
MACOS_CERT_P12(base64-encoded .p12)MACOS_CERT_PASSPHRASEAPPLE_IDAPPLE_PASSWORD(app-specific password)APPLE_TEAM_ID
Notes:
- If the signing secrets are not present (common in forks), GitHub Actions will still build mac artifacts unsigned.
- Notarization is enabled automatically when Apple credentials are present (or explicitly with
NOTARIZE=1).
If you are using short-lived macOS machines and want a repeatable setup:
- Fastest path (recommended): build in GitHub Actions and download the mac artifact to your VM (see "Fork Testing (End-to-End)").
- Local build path: run the bootstrap script from repo root:
./scripts/bootstrap-macos.sh buildThis installs prerequisites (Homebrew + Node 20) and produces unsigned mac artifacts using SKIP_SIGNING=1.
- Update the content in
app/directory - Create a new GitHub Release with a version tag (e.g.,
v1.0.0) - The
bundle-content.ymlworkflow automatically:- Bundles all files in
app/intocontent.json - Uploads
content.jsonto the release
- Bundles all files in
When users launch the app, it will:
- Check the latest release via GitHub API
- Compare timestamps with locally cached content
- Download new content if available
- Display the content
a0-launcher/
├── .github/workflows/ # GitHub Actions
│ ├── bundle-content.yml # Bundles app/ on release
│ └── build.yml # Builds executables
├── app/ # Source content (bundled on release, NOT in executable)
│ └── index.html
├── shell/ # Electron shell (packaged)
│ ├── assets/ # Icons and entitlements
│ ├── main.js # Main process
│ ├── preload.js # Context bridge
│ └── loading.html # Loading screen
├── forge.config.js # Electron Forge config
└── package.json
MIT