Agent skill

Happy Monorepo Release

by slopus in slopus/happy

Walks you through releasing a component of the Happy monorepo (CLI, mobile, web or server) from a clean local main that matches origin/main.

MITAuto-check passedDevOps & Cloud

Install Happy Monorepo Release

skills CLI
$ npx skills add slopus/happy --skill release -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install slopus/happy release --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/slopus/happy.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/release .claude/skills/release && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
release
GitHub stars
24k
Token cost
~6.6k tokens
SKILL.md length
3,233 words
Files
1
Skills in repo
8
Repo updated
First seen
Licence
MIT

At a glance

Walks you through releasing a component of the Happy monorepo (CLI, mobile, web or server) from a clean local main that matches origin/main.

  • Works in 2 steps: Where you release from (never skipped) → Pick a target
  • Shipping a new version of the Happy CLI, mobile app, web client or server
  • SKILL.md covers Step 0: Where you release from…, Step 1: Pick a target, CLI Release and Mobile Release, plus 5 more sections
  • Calls eas, git and npm; reaches github.com; needs POSTHOG_API_KEY

What it does

Written for the Happy monorepo, this skill makes the agent act as the release operator when you type /release or ask to publish, deploy or ship a component. It covers the CLI, mobile app, web and server, and guides version bumping, building, testing, publishing and deploying in one conversation instead of an interactive release-it prompt.

Its first rule is never skipped: every release runs from a local main that equals origin/main after a fresh fetch, with a clean working tree, never from a worktree or feature branch. The skill backs the rule with an incident in which an over-the-air preview update built from a worktree commit left phones on a bundle that lacked fixes main already had, with no error to explain it.

For mobile releases, the repository's releasePreflight.mjs script fetches, compares HEAD with origin/main, checks the tree is clean and confirms changelog.json is regenerated and committed. It runs first in the OTA and App Store build scripts, and you run it by hand if you call eas update or eas build directly. Preview and production OTA updates, native builds, store submissions and CLI dispatch are all named as release targets.

When your agent uses it

  • Shipping a new version of the Happy CLI, mobile app, web client or server
  • Publishing a preview or production over-the-air update for the mobile app
  • Submitting a native build to the app store from the Happy repository
  • Checking that a checkout is releasable before running eas update or eas build by hand

Example prompts

  • “/release the CLI and walk me through each step.”
  • “Publish a preview OTA update of the mobile app from main.”
  • “I want to ship the production mobile build, so run the preflight check first.”
  • “Release the server component and tell me what you verify before each step.”

Requirements

  • A checkout of the Happy monorepo on a clean local main
  • Node.js to run the preflight script
  • Expo EAS tooling for mobile updates and builds

Workflow steps

2 steps, taken from the step headings in SKILL.md.

  1. Where you release from (never skipped)
  2. Pick a target

What it can do on your machine

Read from SKILL.md and the folder at commit 7ea7017. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • eas
    • git
    • npm
    • pnpm
    • node
    • gh
    • expo
    • tsx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • github.com

    Also links to:

    • registry.npmjs.org

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • POSTHOG_API_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Happy Monorepo Release loads about 6.6k tokens when it runs. Until then it costs about 77 tokens; SKILL.md has 3,233 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~77
When it runs · the whole SKILL.md, loaded when a task matches
~6.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from slopus/happy at commit 7ea7017, republished under its MIT licence (© slopus). 3,233 words, ~6,565 tokens.

Download SKILL.mdSave it as .claude/skills/release/SKILL.md (or your agent's skills folder).
name
release
description
Release pipeline for CLI, mobile, web, and server. Guides through version bumping, building, testing, publishing, and deploying. Replaces the old interactive release-it flow with a Claude Code-native experience. Use when user types /release or asks to release, publish, deploy, or ship any component.

Release

You are the release operator for the Happy monorepo. When invoked, walk the user through releasing the component they choose.

Step 0: Where you release from (never skipped)

Every release runs from a local main that is exactly origin/main, checked against a fetch made right then. Not from a worktree. Not from a branch. Not from a main that is ahead by an unpushed commit or behind by anyone else's. Not with uncommitted changes. This applies to every target below: preview OTA, production OTA, native builds, store submissions, CLI dispatch.

Why this is rule zero. On 2026-09-20 a preview OTA was published from a worktree commit (fe7de0a1) that had branched off main hours earlier. The commit was fine on its own, and it was later rebased and pushed, so git looked right afterwards. But expo-updates serves whatever was published last on a branch, not whatever is on main. For the next several hours every phone on the preview channel ran a bundle missing four fixes that main already had: bot faces, the truncated "Auto" chip, paste-from-clipboard, and the send button being pushed out of the composer. Nothing errored. The user saw "the same old issue" and could not tell why. A release from a stale checkout is not a release, it is a rollback that nobody asked for.

Run this and read the output before any release command:

bash
git checkout main
git fetch origin main
git rev-parse --abbrev-ref HEAD            # must print exactly: main
git rev-parse HEAD origin/main             # the two hashes must be identical
git status --porcelain                     # must print nothing

If HEAD is behind, git merge --ff-only origin/main. If it is ahead, the commits are not on main yet — push first (see AGENTS.md "Sync To Main"), then release. If the tree is dirty, commit or stash; a release must be reproducible from the commit EAS records.

The mobile release scripts enforce this mechanically: packages/happy-app/sources/scripts/releasePreflight.mjs runs first in ota, ota:production, release:build:appstore, and the other release:build:* scripts. It fetches, compares HEAD to origin/main, checks the tree is clean, regenerates changelog.json and insists it is committed, and refuses with the list of main commits the release would have dropped. If you run eas update or eas build by hand instead of through those scripts, run the preflight by hand first:

bash
cd packages/happy-app && node sources/scripts/releasePreflight.mjs

The only exception is one the user asks for by name, in the current conversation — for example "publish this branch to preview so I can test it on my phone". A standing instruction from an earlier session does not count, and neither does your own judgement that it is probably fine. When the user does ask: fetch and rebase anyway, show them git log --oneline HEAD..origin/main (what the release will not contain), get a yes, run with HAPPY_RELEASE_ALLOW_OFF_MAIN=1, and say in the final report that the release was off-main and from which commit. Afterwards, once the work lands on main, republish from main so the channel is back on the mainline.

After publishing an OTA, verify the channel now serves what you meant:

bash
cd packages/happy-app && eas update:list --branch <branch> --limit 1 --non-interactive

The newest group's commit must be your HEAD. If it is not, someone published after you; find out from what.

Step 1: Pick a target

Ask which component to release:

  • CLI — npm package happy
  • Mobile — Expo/EAS builds for iOS + Android
  • Web — Docker image + K8s deploy via TeamCity
  • Server — Docker image + K8s deploy via TeamCity
  • Docs — GitHub Pages (separate repo)

Present these as options. Wait for the user to pick.


CLI Release

Package:     packages/happy-cli
npm name:    happy
Registry:    https://registry.npmjs.org
Git tags:    cli-{version}

CLI releases use .github/workflows/release-happy-cli.yml, following the happy-agent manual-dispatch convention: one run builds/tests/packs, then publishes that exact artifact through npm trusted publishing. Never publish from local npm credentials or create a release tag by hand. The workflow creates the tag and GitHub Release only after npm publication and a fresh-install smoke check succeed. Steps 4–6 below describe the workflow's build gates, not a second local release procedure.

Tag namespace note:

  • CLI releases use cli-X.Y.Z
  • Native releases use native-<runtime-version>
  • OTA releases use ota-<ota-version>
  • Do not use a bare vX.Y.Z tag for Happy releases because multiple release streams coexist in this repo
Step 2: Gather state

Run these in parallel:

  1. npm view happy dist-tags — see current latest + beta
  2. cat packages/happy-cli/package.json | grep version — local version
  3. git status --short — check for dirty state
  4. git branch --show-current — confirm branch
  5. git log --oneline -10 — recent commits for release notes context

Present a summary:

Local version:  X.Y.Z
npm latest:     X.Y.Z
npm beta:       X.Y.Z-N
Branch:         main
Working tree:   clean / dirty
Step 3: Pick channel and version

Ask the user:

  • Channel: latest or beta
  • Bump type: For latest: patch, minor, major. For beta: prerelease (appends -N), or explicit version.

Suggest a sensible default based on the current state. For beta, the next prerelease of the current version. For latest, a patch bump.

Present as options. Wait for confirmation.

Step 4: Version bump

The workflow stamps its requested version into packages/happy-cli/package.json before building. Do NOT use npm version (it chokes on pnpm workspace protocol). Beta identities stay in the artifact; stable releases persist the version on main.

IMPORTANT: do this before build/test for the CLI. The build imports package.json and bakes the version into the generated bundle. If you build first and bump later, happy --version can still report the old prerelease version even though npm metadata shows the new one.

Step 4b: @slopus/happy-wire must stay bundled — do NOT move it back

packages/happy-cli/package.json keeps "@slopus/happy-wire": "workspace:*" in devDependencies, deliberately. That is not a mistake to tidy up.

pkgroll has no --external flag — its entire externals policy is derived from dependencies/peerDependencies. So the dependency section IS the bundling switch:

  • in dependencies → pkgroll emits a bare import ... from '@slopus/happy-wire' and Node resolves it from the registry at runtime
  • in devDependencies → pkgroll inlines the code into dist/. The dev dependency may remain in the published manifest, but is not installed as a runtime dependency.

It must stay in devDependencies. After any build change, verify:

bash
# must return nothing — no runtime import may survive
grep -rnE "(import|require).*@slopus/happy-wire" packages/happy-cli/dist/
# must return the definitions, not just import mentions
grep -rhoE "(function|const) (createEnvelope|stripLeadingTaskNotificationWrappers)" packages/happy-cli/dist/

(A bare "@slopus/happy-wire": "workspace:*" string does still appear in dist — that is the CLI's own package.json inlined as a JSON literal for the version string. Inert. Only an actual import/require matters.)

Why this exists. 1.2.1-beta.0 shipped declaring "@slopus/happy-wire": "0.1.0" — the only version on npm, published 2026-02-13. Local happy-wire was also labeled 0.1.0 but had 18 commits of drift, including f85b20c3 which added stripLeadingTaskNotificationWrappers and imported it from happy-cli/src/codex/utils/sessionProtocolMapper.ts. February's tarball had no such export, ESM failed at module load, and happy crashed on every invocation — dead on arrival, not degraded. 1.2.0 had survived the identical latent bug purely because none of its 15 import sites needed a post-February symbol. workspace:* publishes the local version NUMBER, never the local CODE.

No in-repo test can catch that class of bug. Inside the monorepo workspace:* resolves to local source, so prepublishOnly — build, typecheck, all 792 unit tests — always sees the correct code. It only fails against the registry. The isolated install smoke check is what catches that class of bug.

Still exposed — happy-agent and happy-server-self-host both keep happy-wire in dependencies, so they carry the original trap. Before publishing either, bundle it the same way or get happy-wire republished first.

Publish rights: @slopus/happy-wire is owned solely by steve.kite <steve@korshakov.com>. bra1ndump is an owner of happy but NOT of the @slopus scope, so publishing happy-wire 404s for them. Bundling exists partly to route around that.

Note: happy --version prints BOTH happy's own version and the Claude Code version it found:

happy version: 1.2.1-beta.1
Using Claude Code v2.1.224 from native installer
2.1.224 (Claude Code)

Do NOT pipe it through tail -2 — that cuts the happy line off and makes it look like the command only reports Claude Code's version. Read the first line.

Step 5: Build
bash
cd packages/happy-cli
pnpm --filter happy run build

Report success/failure. Stop on failure.

Step 5b: Self-host server split

The happy npm package no longer bundles the self-host server binary or webapp. Packaged installs resolve those from the separately installed happy-server-self-host package. Do not rebuild or ship tools/server or tools/webapp as part of a CLI release.

If the CLI release depends on self-host server changes, release happy-server-self-host separately. It lives in packages/happy-server-self-host and is the publishing shell around the private packages/happy-server: pnpm --filter happy-server-self-host build bundles that package's standalone entrypoint into dist/ and copies prisma/ in (this needs bun), then pnpm --filter happy-server-self-host run bundle:webapp builds the bundled webapp. Publish from packages/happy-server-self-host — packages/happy-server is private and is never published. The server package is a JS/TS npm package; npm handles platform specific dependencies such as Prisma and sharp normally. Do not pass --ignore-scripts when publishing it; its prepublishOnly script rebuilds the runtime, rebuilds the webapp, and runs tests before npm receives the tarball.

Before handing a server publish to the user, pre-run the full prepublishOnly chain yourself to catch failures early — the bundle:webapp step runs a multi-minute expo export, and build needs bun:

bash
pnpm --filter happy-server-self-host --fail-if-no-match run prepublishOnly

The server typecheck, unit suite, and both Docker images are gated by .github/workflows/server.yml.

(Observed: 1332 merged a standalone.spec.ts test that only passes on Windows because the impl used POSIX path.basename; it was red on main and would have aborted the publish at the prepublishOnly test step.)

Step 6: Test (unit only)
bash
cd packages/happy-cli
pnpm --filter happy exec vitest run --project unit

Integration tests are slow and flaky — skip them for releases. Unit tests are the gate. Expect the unit suite to take around a minute; src/utils/serverConnectionErrors.test.ts is particularly slow, so don't mistake a long run for a hang.

Report results. If failures, ask the user whether to proceed or abort.

Step 7: Publish

Fetch/rebase onto current main before dispatching. Build user-facing release notes from the actual changes since the previous CLI release of that channel (for a first beta of a new stable target, start from the latest stable). Keep notes under .context/. Show the chosen version, channel, and notes and get confirmation.

bash
gh workflow run release-happy-cli.yml --repo slopus/happy --ref main \
  -f version=X.Y.Z-beta.N -F prerelease=true \
  -F release_notes=@.context/release-notes.md

Stable releases use version=X.Y.Z and prerelease=false. The workflow derives the npm dist-tag (beta or latest) and rejects mismatched versions. Do not introduce a separate prepare/publish dispatch. -F release_notes=@... reads file contents; -f release_notes=... sends a literal path, which is wrong.

The workflow runs prepublishOnly explicitly after version stamping and before pnpm pack. Packing or publishing an existing tarball does not invoke the source workspace's prepublishOnly. Never omit this build/typecheck/unit-test gate. 1.1.10-beta.9 previously shipped a stale beta.8 bundle when scripts were skipped.

Use pnpm for workspace packaging. Uploading the already-tested pnpm tarball with a pinned npm CLI is supported and matches Happy Terminal's CI. Do not run raw npm publish against the source workspace. npm 11.5.1+ supports OIDC; the workflow pins and directly invokes npm 11.18.0 so Node's bundled npm cannot shadow it.

One-time trust configuration on npm: GitHub owner slopus, repository happy, workflow release-happy-cli.yml, environment npm, direct publishing allowed. The GitHub environment permits only main. Never request npm passwords, tokens, browser authentication links, or OTPs in chat, and never fall back to local npm credentials if OIDC fails.

Step 8: Verify
bash
npm view happy@{version} version   # did the version actually publish?
npm view happy dist-tags           # did the channel tag move?

Watch the dispatched run to completion using the product's durable wait/monitor mechanism and GitHub CLI status/logs. Check npm view happy@X.Y.Z version before retrying any failed publication: npm versions are immutable. A failed publish must leave the release tag and GitHub Release absent. If publication succeeded but a later gate failed, investigate before retrying; do not overwrite the version or move an existing tag.

⚠️ This metadata check is necessary but NOT sufficient. npm view ... version only confirms the tarball was accepted — it says nothing about what's inside it. A bundle stamped with the wrong version (the --ignore-scripts footgun above) passes this check cleanly. The authoritative check is the workflow's fresh-install smoke test (happy --version). Never report a release as done on the metadata check alone.

Then confirm the new version appears under the correct dist-tag. The tag often lags the publish by 10–40s — poll a few times before concluding it failed; npm tag propagation is not instant.

Show full SKILL.md (1,309 more words)Show less
Step 9: Read back the release and installed-package verification
bash
gh release view cli-X.Y.Z --repo slopus/happy --json body,tagName,isDraft,isPrerelease,url

The body must contain the actual notes, not a filename. Betas must be prereleases, must update only npm's beta tag, and must leave GitHub's latest release unchanged. The CLI shares its repository with native/OTA releases, so even stable CLI releases do not automatically replace GitHub's latest release.

The workflow checks the tarball SHA-256 after artifact download, compares the npm integrity and provenance metadata, then installs the published version in a fresh directory and checks happy --version, happy --help, and happy daemon status. Verify that these gates passed. Do not replace the maintainer's global CLI or restart their daemon as an implicit release step. After stable releases, fetch and fast-forward/rebase the workflow's version commit while preserving local work.


Mobile Release

Package:     packages/happy-app
Variants:    development, preview, production
Platform:    Expo SDK 55 / React Native 0.83.1

Step 0 first, always. Every command in this section is wrapped by sources/scripts/releasePreflight.mjs; if you bypass a pnpm script and call eas directly, run the preflight yourself.

Build types

Always ask the user explicitly what they want to release. Present these options in order of popularity:

  1. OTA update (preview) — push JS bundle to preview channel. Most common release type.
  2. OTA update (production) — push JS bundle to production channel. Do this after preview OTA is validated.
  3. Native dev build — when native code changes. Points to dev server with bundled app.
  4. Full native release — build all profiles (dev + preview + production) to prep for a new native release.
OTA Updates
bash
# Preview (most common). pnpm forwards the trailing flags to `eas update`.
cd packages/happy-app && pnpm ota --message "<what changed> (<short sha>)" --non-interactive

# Production
cd packages/happy-app && pnpm ota:production

eas update prompts for a message when none is given, and stdin is not readable from an agent, so always pass --message and --non-interactive. Put the short commit hash in the message: it is what lets the next person answer "what is actually on this channel" from eas update:list alone.

The ota script is releasePreflight.mjs && pnpm typecheck && eas update --branch preview. The preflight regenerates changelog.json from CHANGELOG.md and refuses if the result is not committed, so edit the changelog, regenerate, commit, push, then release. Do not reach around the script to eas update directly just to skip a step it is failing on; the failure is the point.

Production OTA (ota:production) dispatches the EAS workflow in .eas/workflows/ota.yaml, which publishes the current commit to the production channel. Same rule: main, matching origin/main, pushed. Never run it without the user asking for a production OTA in the current conversation.

Native Builds
  • Dev build — development profile, used when native code changes (points to dev server)

    bash
    cd packages/happy-app && eas build --profile development --platform all --non-interactive
  • TestFlight / Play Store builds — use -store profiles for distribution via TestFlight and Play Store. Always pass --auto-submit so the build goes straight to TestFlight after completion.

    bash
    # Production, both platforms, auto-submitted to App Store Connect and Play Console.
    # This is `release-production.sh`, and it runs the preflight first.
    cd packages/happy-app && pnpm release:build:appstore
    
    # Preview (TestFlight/internal testing) — run the preflight yourself, then:
    cd packages/happy-app && node sources/scripts/releasePreflight.mjs && eas build --profile preview-store --platform ios --non-interactive --auto-submit
    
    # Dev (TestFlight, points to dev server)
    cd packages/happy-app && node sources/scripts/releasePreflight.mjs && eas build --profile development-store --platform ios --non-interactive --auto-submit

    Afterwards, eas build:list --limit 4 --non-interactive --json and check that each build's gitCommitHash is your HEAD and its runtimeVersion is the one in app.config.js. A build from the wrong commit is the native version of the stale-OTA mistake, and it is far harder to undo.

IMPORTANT: Always pass --non-interactive to eas build commands. Without it, EAS prompts for Apple account login interactively which breaks in non-TTY contexts (Claude Code, CI). Remote credentials are already configured on EAS servers.

IMPORTANT: Always pass --auto-submit to -store builds. Without it, the build finishes but never reaches TestFlight — you have to manually submit with eas submit.

EAS Build Profiles
Profile              Distribution   Channel       Notes
development-store    store          development   Dev build via TestFlight
preview-store        store          preview       TestFlight / Play Store internal testing
production           store          production    App Store / Play Store submission

Internal / ad-hoc profiles (rarely used)

These install via direct link, NOT TestFlight. Almost never needed — prefer the -store profiles above.

Profile              Distribution   Channel
development          internal       development
preview              internal       preview

Version source is remote (EAS manages build numbers, auto-incremented). Runtime version is runtimeVersion in app.config.js (currently "21") — bump it when native code changes, so an OTA built against the new native layer can never land on an old binary.

App Store Connect
Apple ID:    steve@bulkovo.com
Team ID:     466DQWDR8C

App Store Connect App IDs:
Production:   6748571505  (com.ex3ndr.happy)
Preview:      6749025570  (com.slopus.happy.preview)
Development:  6748984254  (com.slopus.happy.dev)

Web Release

Package:     packages/happy-app (same Expo app, web export)
Dockerfile:  Dockerfile.webapp
Image:       docker.korshakov.com/happy-app:{version}
K8s:         packages/happy-app/deploy/happy-app.yaml (3 replicas)

Web releases go through TeamCity (Lab_HappyWeb). The config is in the TeamCity UI, not in the repo.

Flow: expo export --platform web -> nginx:alpine static serve -> Docker build -> push -> K8s deploy.

Build args: POSTHOG_API_KEY, REVENUE_CAT_STRIPE.

Guide the user to trigger the TeamCity build, or help with manual Docker builds if needed.


Server Release

Package:     packages/happy-server
Dockerfile:  Dockerfile.server (production), Dockerfile (standalone w/ PGlite)
Image:       docker.korshakov.com/handy-server:{version}
K8s:         packages/happy-server/deploy/handy.yaml (1 replica, port 3005)

Server releases go through TeamCity (Lab_HappyServer). The config is in the TeamCity UI, not in the repo.

Build: node:20 + python3 + ffmpeg, builds happy-wire + happy-server. Secrets from Vault: handy-db, handy-master, handy-github, handy-files, handy-e2b, handy-revenuecat, handy-elevenlabs. Redis: happy-redis StatefulSet (redis:7-alpine, 1Gi persistent volume).

Guide the user to trigger the TeamCity build.


Docs Release

Site:    happy.engineering (GitHub Pages)
Repo:    github.com/slopus/slopus.github.io

Separate repo, not part of this monorepo. Guide the user to push to that repo.


Writing release notes (the in-app changelog)

CHANGELOG.md is regenerated into changelog.json and shown inside the mobile app, on a phone, right after an OTA update. Write for that reader.

  1. Investigate before writing — use subagents (Opus). Don't infer from commit titles. Spawn parallel subagents to read the actual code + git history of each candidate change and classify it: user-visible UX vs impl detail, default-on vs gated, new vs polish/fix.
  2. Default-off ⇒ exclude. A change behind a setting/experimental flag that defaults to OFF (or whose UI entry point is hidden) is a silent ship — omit it until it's on by default. Same for impl / perf-internal / refactor / type-only changes.
  3. Audience is phone users. Most never touch the CLI or desktop. Be skeptical of CLI-only / desktop-only / web-only / beta-only items — a genuinely strong feature can still be wrong for this venue; announce those in CLI release notes / docs / GitHub instead.
  4. Ask, don't assume. When announce-vs-silent-ship, default state, or scope is unclear, ask the owner and confirm the final include/exclude list before writing. Never headline-announce on your own judgment.
  5. Voice: benefit-first, terse, em-dash, one line per item, grouped as a dated themed entry like existing ones. Edit CHANGELOG.md only, then regenerate via tsx packages/happy-app/sources/scripts/parseChangelog.ts.
  6. Community Credits bullet. End each entry with a single bullet crediting community contributors whose commits ship in it: - Community Credits: [@user1](https://github.com/user1), [@user2](https://github.com/user2). Core team never appears there — Kirill (bra1ndump / kirill2003de@gmail.com), Scoteezy, and Steve (ex3ndr). To find contributors: get the previous OTA's commit via eas update:list --branch preview + eas update:view <group-id> --json (gitCommitHash), then git log <hash>..HEAD and keep non-core authors. GitHub handles come from the PR (gh pr view <n> --json author), not from the commit email. If an OTA shipped without a changelog entry, its uncredited community commits roll into the next entry's credits.

Rules

  • Release only from local main that is origin/main, fetched right then, tree clean — see Step 0. Not a worktree, not a branch, not ahead, not behind. The mobile scripts refuse otherwise. The only exception is one the user asks for by name in the current conversation; then run with HAPPY_RELEASE_ALLOW_OFF_MAIN=1, show what main commits the release lacks, and say it was off-main in the report.
  • Release notes: investigate with subagents, exclude default-off, ask when unsure — see "Writing release notes" above.
  • Always present options — never assume which component, channel, or version.
  • Always verify before publishing — show the user what will be published and get confirmation.
  • CLI releases use the approved GitHub workflow — dispatch from main with the confirmed version and notes; never publish from local credentials or handle npm credentials/OTP.
  • Do not bundle self-host server/webapp into happy — self-host runtime and the bundled webapp ship through happy-server-self-host, not the main CLI package.
  • Unit tests are the gate, not integration tests — integration tests are slow and have flaky abort/interrupt tests.
  • Use pnpm to pack the workspace — CI uploads that exact tested tarball with its pinned npm CLI; never use raw npm publishing on the source workspace.
  • Run prepublishOnly after stamping and before packing — tarball upload does not run the workspace's lifecycle scripts. Never skip this gate.
  • Never force-push tags — if a tag exists, stop and ask.

© slopus, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/release of slopus/happy.

Open the folder on GitHubat commit 7ea7017

Compare with similar skills

Happy Monorepo Release next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Happy Monorepo Release compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Happy Monorepo Release this skillslopus/happy24k—~6.6kAutomated safety check: PassMIT
Releaselinagora/twake-on-matrix168—~1kAutomated safety check: PassAGPL-3.0
Releasebmeares/Meerschaum154—~1.1kAutomated safety check: NotesApache-2.0
Agr Releasecomputerlovetech/agr451—~1.6kAutomated safety check: PassMIT
Deploy Androidtimusus/Shuttle2229—~1.2kAutomated safety check: PassApache-2.0
ClickUp CLI Release Processkrodak/clickup-cli120—~906Automated safety check: WarnMIT

Similar skills

  • Release

    linagora/twake-on-matrix

    Twake-on-Matrix release process skill. An agent skill from linagora/twake-on-matrix.

    168 GitHub stars~1k tokensUpdated today
    MobileAuto-check passed
  • Release

    bmeares/Meerschaum

    Meerschaum release process — bump version, update changelog, stage dev→main PR, run CI, publish to PyPI, tag, GitHub release, build/push Docker images, rebuild docs on prod VPS.

    154 GitHub stars~1.1k tokensUpdated 29 days ago
    DevOps & CloudAuto-check: notes
  • Agr Release

    computerlovetech/agr

    Release process for the agr package. An agent skill from computerlovetech/agr.

    451 GitHub stars~1.6k tokensUpdated 1 mo ago
    DevOps & CloudAuto-check passed
  • Deploy Android

    timusus/Shuttle2

    Deploy the Android app to the Play Store via GitHub Actions.

    229 GitHub stars~1.2k tokensUpdated today
    MobileAuto-check passed
  • ClickUp CLI Release Process

    krodak/clickup-cli

    Walks through releasing a new version of clickup-cli: pre-release checks, version bump, tagging, CI watch, release notes and the Homebrew update.

    120 GitHub stars~906 tokensUpdated yesterday
    DevOps & CloudAuto-check: warnings
  • OpenWork Release Process

    different-ai/openwork

    Cuts an OpenWork desktop release through a tag-driven GitHub Actions workflow that makes no commits, with pre-tag checks on open fix PRs and verification afterward.

    24k GitHub stars~2.3k tokensUpdated today
    DevOps & CloudAuto-check passed

More from slopus/happy

All 8 skills in this repo
  • Searches past Claude Code, Codex and Cursor sessions and summarizes what was worked on, tried or decided, using extraction scripts instead of reading raw logs.

    24k GitHub stars~3.1k tokensUpdated today
    Auto-check passed
  • Agent Browser CLI

    slopus/happy

    Drives a real browser from the shell with the agent-browser CLI: open pages, snapshot elements by ref, click, fill and extract, for testing web flows.

    24k GitHub stars~1.7k tokensUpdated today
    Auto-check passed
  • Traces how an action moves through your code and draws it as a compact ASCII tree: functions called, payload types, state changes and components that re-render.

    24k GitHub stars~654 tokensUpdated today
    Auto-check passed
  • Local development guide for the Happy pnpm monorepo: install, build, test and run the CLI, server, Expo app and Tauri desktop packages.

    24k GitHub stars~1.8k tokensUpdated today
    Auto-check passed
  • Queries live Prometheus metrics and manages Grafana dashboards as code for Happy's infrastructure, using the grafanactl CLI and the Grafana datasource proxy API.

    24k GitHub stars~2k tokensUpdated today
    Auto-check: notes
  • Tests interactive CLI and TUI programs with Microsoft's tui-test, driving prompts, arrow keys and screen output in a real pseudo-terminal.

    24k GitHub stars~603 tokensUpdated today
    Auto-check passed

Works with

Questions about Happy Monorepo Release

What does Happy Monorepo Release do?

Walks you through releasing a component of the Happy monorepo (CLI, mobile, web or server) from a clean local main that matches origin/main. Written for the Happy monorepo, this skill makes the agent act as the release operator when you type /release or ask to publish, deploy or ship a component. It covers the CLI, mobile app, web and server, and guides version bumping, building, testing, publishing and deploying in one conversation instead of an interactive release-it prompt.

When should I use Happy Monorepo Release?

Happy Monorepo Release fits situations like: shipping a new version of the Happy CLI, mobile app, web client or server; publishing a preview or production over-the-air update for the mobile app; submitting a native build to the app store from the Happy repository; checking that a checkout is releasable before running eas update or eas build by hand.

How do I install Happy Monorepo Release in Claude Code?

Run `npx skills add slopus/happy --skill release -a claude-code`. Or copy the skill folder (.agents/skills/release in slopus/happy) into .claude/skills/release in your project. Claude Code loads it when a task matches its description.

How do I install Happy Monorepo Release in Codex?

Run `npx skills add slopus/happy --skill release -a codex`. Or copy the skill folder (.agents/skills/release in slopus/happy) into .agents/skills/release in your project. Codex loads it when a task matches its description.

Can I use Happy Monorepo Release in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add slopus/happy --skill release -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/release, .gemini/skills/release, .github/skills/release and .opencode/skills/release in your project.

What does Happy Monorepo Release need to run?

Going by SKILL.md and its folder, Happy Monorepo Release needs the command-line tools its instructions call (eas, git, npm, pnpm, node and gh) and credentials named POSTHOG_API_KEY. Our summary lists: A checkout of the Happy monorepo on a clean local main; Node.js to run the preflight script; Expo EAS tooling for mobile updates and builds.

Does Happy Monorepo Release access the network?

SKILL.md names 2 domains. In commands or code: github.com; the agent is likely to contact it when it follows the instructions. As links in the text: registry.npmjs.org. This is read from the text; nothing was executed.

Is Happy Monorepo Release safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Happy Monorepo Release use?

Happy Monorepo Release is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Happy Monorepo Release use?

About 6.6k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Happy Monorepo Release?

Skills that share tags, products or a category with Happy Monorepo Release: Release (linagora/twake-on-matrix, 168 stars), Release (bmeares/Meerschaum, 154 stars), Agr Release (computerlovetech/agr, 451 stars) and Deploy Android (timusus/Shuttle2, 229 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Happy Monorepo Release?

slopus (a GitHub organization) maintains it in slopus/happy, which has 24,039 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on October 7, 2026.

Source: slopus/happy on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.