Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
Use this skill for release and publish-time workflow. Keep ordinary development changes and GHSA-specific advisory work outside this skill.
docs/reference/RELEASING.md for public policy.openclaw publish is manual workflow_dispatch; creating or pushing a tag does not publish by itself.stable: tagged releases only, published to npm beta by default; operators may target npm latest explicitly or promote laterbeta: prerelease tags like vYYYY.M.D-beta.N, with npm dist-tag beta-beta.N; do not mint new -1 or -2 beta suffixesdev: moving head on mainpackage.jsonapps/android/app/build.gradle.ktsapps/ios/Sources/Info.plistapps/ios/Tests/Info.plistapps/macos/Sources/OpenClaw/Resources/Info.plistdocs/install/updating.mdvYYYY.M.D-N, the repo version locations still stay at YYYY.M.D.appcast.xml.https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml, and the canonical published file is appcast.xml on main in the openclaw repo.appcast.xml unless a separate beta feed exists.vYYYY.M.D-N, the repo version still stays
at YYYY.M.D, but the mac release must use a strictly higher numeric
APP_BUILD / Sparkle build than the original release so existing installs
see it as newer.vYYYY.M.D-beta.N from the release commitopenclaw YYYY.M.D-beta.NCHANGELOG.md version sectionCHANGELOG.md sorted by impact:
### Changes first### Fixes deduped with user-facing fixes firstBefore tagging or publishing, run:
pnpm build
pnpm ui:build
pnpm release:check
pnpm test:install:smoke
For a non-root smoke path:
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke
After npm publish, run:
node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
YYYY.M.D-N, it also verifies the
upgrade path from YYYY.M.D to YYYY.M.D-N so a correction publish cannot
silently leave existing global installs on the old base stable payload.pnpm test:install:smoke
now fails the candidate update tarball when npm reports an oversized
unpackedSize, so release-time e2e cannot miss pack bloat that would risk
low-memory install/startup failures.npm install -g <candidate> fresh installs and npm-driven update installs,
because many users install with npm even when docs prefer pnpm.pnpm test:live:media video for bounded video-provider smoke when video
generation is in release scope. The default video smoke skips fal, runs one
text-to-video attempt per provider with a one-second lobster prompt, and caps
each provider operation with OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS
(180000 by default).pnpm test:live:media video --video-providers fal only when FAL-specific
proof is required. Its queue latency can dominate release time.OPENCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1 only when intentionally
validating the slower image-to-video and video-to-video transform lanes.pnpm checkpnpm buildpnpm ui:buildpnpm release:checkOPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoketimeout --foreground/gtimeout --foreground caps such as:
45m for OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke90m for pnpm test:docker:allopenclaw-parallels-smoke skill
If a lane hits its cap, stop and inspect/fix the affected lane before continuing; do not continue to wait on the same process.npm install -g, installer package install, or openclaw update takes longer than 300s in release e2e, stop treating the run as healthy progress and debug the installer/updater or harness.pnpm build, pnpm ui:build, pnpm release:check, install smoke, and any Docker/package-prep lanes before starting Parallels npm pack lanes; otherwise dist can disappear during VM pack prep and produce false failures.openclaw/openclaw and the real mac preflight in
openclaw/releases-private for every release.appcast.xml update on main as part of mac release readiness, not an optional follow-up.appcast.xml before uploading
public release assets so the updater feed cannot lag the published binaries.appcast.xml files from the same stale seed.beta to latest is an explicit mode on
.github/workflows/openclaw-npm-release.yml, but it still needs a valid
NPM_TOKEN because npm dist-tag management is separate from trusted
publishing.sync_stable_dist_tags=true to point both latest and beta at the
already-published stable version. This also needs the npm-release
environment approval and NPM_TOKEN.workflow_dispatch.preflight_only=true to run validation/build/package steps without uploading
public release assets.smoke_test_only=true for branch-safe
workflow smoke tests that use ad-hoc signing, skip notarization, skip shared
appcast generation, and do not prove release readiness.preflight_only=true on the npm workflow is also the right way to validate an
existing tag after publish; it should keep running the build checks even when
the npm version is already published..github/workflows/macos-release.yml in openclaw/openclaw is now a
public validation-only handoff. It validates the tag/release state and points
operators to the private repo. It still rebuilds the JS outputs needed for
release validation, but it does not sign, notarize, or publish macOS
artifacts.openclaw/releases-private/.github/workflows/openclaw-macos-validate.yml
is the required private mac validation lane for swift test; keep it green
before any real mac publish run starts.openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml.appcast.xml generation.main; branch-dispatched publish
attempts should fail before the protected environment is reached.npm-release environment must be approved by @openclaw/openclaw-release-managers before publish continues.openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml for
private mac preflight artifact preparation and real publish artifact
promotion..zip, .dmg, and
.dSYM.zip assets to the existing GitHub release in openclaw/openclaw
automatically when OPENCLAW_PUBLIC_REPO_RELEASE_TOKEN is present in the
private repo mac-release environment.macos-appcast-<tag> artifact from the successful private mac workflow and
then update appcast.xml on main.appcast.xml
unless a separate beta Sparkle feed exists.mac-release environment. If the GitHub
plan does not yet support required reviewers there, do not assume the
environment alone is the approval boundary; rely on private repo access and
CODEOWNERS until those settings can be enabled.NPM_TOKEN or the plugin OTP flow for the OpenClaw package
publish path; package publishing uses trusted publishing.NPM_TOKEN only for explicit npm dist-tag management modes, because npm
does not support trusted publishing for npm dist-tag add.@openclaw/* plugin publishes use a separate maintainer-only flow.scripts/package-mac-dist.sh to build, sign, notarize, and package the app;
manual GitHub release asset upload; then scripts/make_appcast.sh plus the
appcast.xml commit to main.scripts/package-mac-dist.sh now fails closed for release builds if the
bundled app comes out with a debug bundle id, an empty Sparkle feed URL, or a
CFBundleVersion below the canonical Sparkle build floor for that short
version. For correction tags, set a higher explicit APP_BUILD.scripts/make_appcast.sh first uses generate_appcast from PATH, then
falls back to the SwiftPM Sparkle tool output under apps/macos/.build.appcast.xml.appcast.xml unless a separate beta feed exists..zip, .dmg, and .dSYM.zip assetsappcast.xml on main points at the new stable zipCFBundleVersion at or above the canonical Sparkle build floorCHANGELOG.md and assemble the matching GitHub release notes..github/workflows/openclaw-npm-release.yml with preflight_only=true
and choose the intended npm_dist_tag (beta default; latest only for
an intentional direct stable publish). Wait for it to pass. Save that run id
because the real publish requires it to reuse the prepared npm tarball..github/workflows/macos-release.yml in openclaw/openclaw and wait
for the public validation-only run to pass.openclaw/releases-private/.github/workflows/openclaw-macos-validate.yml
with the same tag and wait for the private mac validation lane to pass.openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml
with preflight_only=true and wait for it to pass. Save that run id because
the real publish requires it to reuse the notarized mac artifacts..github/workflows/openclaw-npm-release.yml with the same tag for
the real publish, choose npm_dist_tag (beta default, latest only when
you intentionally want direct stable publish), keep it the same as the
preflight run, and pass the successful npm preflight_run_id.npm-release approval from @openclaw/openclaw-release-managers.beta, start
.github/workflows/openclaw-npm-release.yml again after beta validation
passes with the same stable tag, promote_beta_to_latest=true,
preflight_only=false, empty preflight_run_id, and npm_dist_tag=beta,
then verify latest now points at that version.latest and beta should
follow it, start .github/workflows/openclaw-npm-release.yml again with
the same stable tag, sync_stable_dist_tags=true,
promote_beta_to_latest=false, preflight_only=false, empty
preflight_run_id, and npm_dist_tag=latest, then verify both latest
and beta point at that version.openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml
for the real publish with the successful private mac preflight_run_id and
wait for success..zip, .dmg,
and .dSYM.zip artifacts to the existing GitHub release in
openclaw/openclaw.macos-appcast-<tag> from the successful
private mac run, update appcast.xml on main, and verify the feed.appcast.xml artifact and do not update the shared production feed unless a
separate beta feed exists.openclaw-ghsa-maintainer for GHSA advisory inspection, patch/publish flow, private-fork validation, and GHSA API-specific publish checks.