From freenet-freenet-agent-skills
Orchestrate a new Freenet release. Determines next version, shows changelog, confirms with user, and runs the release pipeline. Use when the user says "do a release", "new release", "release", or "/release".
npx claudepluginhub freenet/freenet-agent-skills --plugin freenetThis skill uses the workspace's default tool permissions.
This skill orchestrates a complete Freenet release. It determines the next version, shows what's changed since the last release, confirms with the user, and runs the automated release pipeline.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
This skill orchestrates a complete Freenet release. It determines the next version, shows what's changed since the last release, confirms with the user, and runs the automated release pipeline.
/release 0.1.133), use that as the target versionCapture the current tmux window ID and rename it. The window ID is stable even if the user switches tabs during the long-running release, so always use -t with the saved ID for subsequent renames.
RELEASE_WINDOW=$(tmux display-message -p '#{window_id}')
tmux rename-window -t "$RELEASE_WINDOW" "release X.Y.Z"
Replace X.Y.Z with the target version (determine it first if auto-detecting). Keep $RELEASE_WINDOW available for Step 8 (success criteria).
First, pull the latest changes from origin. Without this, you may see zero commits since the last tag and incorrectly conclude there's nothing to release.
# Pull latest — MUST do this before anything else
git pull origin main
# Get current version from Cargo.toml
grep "^version" crates/core/Cargo.toml | cut -d'"' -f2
# Get the last release tag
git describe --tags --abbrev=0
# Get commits since last release
git log --oneline $(git describe --tags --abbrev=0)..HEAD
Auto-version logic: If no version argument was provided, increment the patch version of the current version (e.g., 0.1.132 -> 0.1.133).
Present the user with:
Then ask the user to confirm before proceeding.
Before running the release script, verify:
# Must be on main branch (or a release worktree)
git branch --show-current
# Must have clean working directory
git status --porcelain # Should be empty
# Must be up to date with origin
git fetch origin main
git rev-parse HEAD # Compare with:
git rev-parse origin/main
If any check fails, inform the user and stop.
To avoid disrupting the main worktree:
cd ~/code/freenet/freenet-core/main # or wherever main worktree is
git worktree add -b release-work ../release-X.Y.Z
cd ../release-X.Y.Z
Clean up after release:
git worktree remove ../release-X.Y.Z
git branch -d release-work
CRITICAL: You MUST run release.sh as a single command. Do NOT manually execute individual release steps (gh release create, cargo publish, etc.). The script handles draft releases, binary waits, and publish ordering that prevent users from seeing a version before its binaries exist. Doing steps manually caused a user-facing 404 during v0.1.177.
Execute the release script:
./scripts/release.sh --version <VERSION> [--skip-tests]
The script handles the entire pipeline:
crates/core/Cargo.toml and crates/fdev/Cargo.tomlfreenet then fdev to crates.io--skip-tests - Skip local pre-release tests (CI still runs on the PR)--dry-run - Show what would be done without executingThe release script is resumable. If it fails partway through, re-running with the same --version will auto-detect completed steps and skip them. State is saved to /tmp/release-<VERSION>.state.
You can also resume explicitly: ./scripts/release.sh --resume /tmp/release-<VERSION>.state
The script automatically restores the original git branch on exit (success or failure). If the script is interrupted, your working directory won't be left on the release/v* branch.
PR title / Conventional Commits check fails: Release PRs must use "build:" prefix (not "chore:"). The commit-msg hook only allows: feat, fix, docs, style, refactor, perf, test, build, ci.
gh api repos/freenet/freenet-core/pulls/XXXX --method PATCH -f title="build: release X.Y.Z"
Auto-merge not triggering:
Test failures: Check CI logs. Either fix the issue or inform the user and ask how to proceed.
CRITICAL: Do NOT announce until cross-compile binaries are available. The Build and Cross-Compile workflow triggers on tag push and takes ~15-20 min to build binaries for all platforms. Gateway auto-update depends on these binaries.
# Check crates.io publication
cargo search freenet --limit 1
# Check GitHub release exists
gh release view v<VERSION>
# Verify ALL required platform binaries are attached
gh release view v<VERSION> --json assets --jq '.assets[].name'
Required platform binaries (all must be present):
freenet-x86_64-unknown-linux-musl.tar.gzfreenet-aarch64-unknown-linux-musl.tar.gzfreenet-aarch64-apple-darwin.tar.gzfreenet-x86_64-apple-darwin.tar.gzfreenet-x86_64-pc-windows-msvc.zipfdev-x86_64-unknown-linux-musl.tar.gzfdev-aarch64-unknown-linux-musl.tar.gzfdev-aarch64-apple-darwin.tar.gzfdev-x86_64-apple-darwin.tar.gzfdev-x86_64-pc-windows-msvc.zipfreenet.exeSHA256SUMS.txtIf any binary is missing, do not proceed to announcements. Investigate the cross-compile workflow failure first.
# Monitor cross-compile workflow if binaries not yet available
gh run list --workflow=cross-compile.yml --limit 3
Before announcing, verify that River clients can still talk to the gateway. Protocol changes (new message variants, streaming defaults, serialization changes) can silently break River even when all freenet-core tests pass.
cd /home/ian/code/freenet/river/main
cargo run -p riverctl -- member list 4uNUKFzZQCnzo4K2ecZ16cMsYEEfoaRS35z6exEsbvm4
This GETs the official room state from the gateway and deserializes it. If it fails:
Why this matters: During v0.2.11, enabling WebSocket streaming by default broke riverctl because it was pinned to an older stdlib that couldn't deserialize the new StreamHeader/StreamChunk variants. This smoke test would have caught that before users were affected.
Only after binaries are confirmed available. Use the matrix-comms and river-official-room skills for detailed instructions on each platform.
Announcement content: Write a 1-3 sentence Markdown summary of the key changes in this release, followed by a link to the GitHub release for full details. Both Matrix and River support Markdown formatting.
Example format:
**Freenet v0.1.177 released.** Transient WebSocket errors no longer kill the client slot permanently. See [release notes](https://github.com/freenet/freenet-core/releases/tag/v0.1.177) for details.
Matrix (#freenet-locutus channel) — use the matrix-comms skill:
# -z flag is REQUIRED for Markdown rendering (bold, links, etc.)
timeout 30 matrix-commander -z -r "!ygHfYcXtXmivTbOwjX:matrix.org" -m "announcement text"
River (Freenet Official room) — use the river-official-room skill:
IMPORTANT: You MUST invoke the river-official-room skill first to get the correct Room Owner VK and identity restoration instructions. The Room Owner identity must be restored before sending messages. Do NOT hardcode the VK here — it changes when the room is recreated.
# 1. Restore Room Owner identity (see river-official-room skill for current VK and key location)
# 2. Send message using the VK from the skill
cd /home/ian/code/freenet/river/main
cargo run -p riverctl -- message send <ROOM_OWNER_VK> "announcement text"
A release is NOT complete until the network is verified healthy.
Wait 10-15 minutes for gateways to auto-update, then verify:
If you have access to gateway machines, check logs directly. If you have access to telemetry, monitor network-wide health. The specific verification steps depend on your access level — see your local environment's release skill for machine-specific commands.
What to look for:
If critical issues found: Roll back immediately, create GitHub issue, announce rollback.
If a release needs to be rolled back:
# Rollback (keeps crates.io versions)
./scripts/release-rollback.sh --version <VERSION>
# Rollback and yank from crates.io (irreversible!)
./scripts/release-rollback.sh --version <VERSION> --yank-crates
# Dry run
./scripts/release-rollback.sh --version <VERSION> --dry-run
0.1.X - patch incremented each release0.3.X - patch auto-incremented by release script (independent versioning)These are real issues from past releases that the release process has been hardened against:
cargo install freenet may leave stale binary at ~/.cargo/bin/freenet shadowing /usr/local/bin/freenet; always use absolute paths when verifying versionssystemctl show -p MainPID + /proc/PID/exe, not just binary on diskgithub.head_ref is a queue branch in merge_group events, not the PR branch. Fixed by detecting release PRs via commit message (build: release*) and skipping expensive test stepsStreamHeader/StreamChunk variants. Always smoke-test River CLI against the gateway before announcing.The release script automatically SSHes into all known gateways and triggers gateway-auto-update.sh --force immediately after cross-compile binaries are available. This eliminates the 10-minute polling delay that previously caused version mismatch issues (users installing the new version before gateways updated).
Gateways also have a 10-minute polling timer as a fallback. Peers self-update when they detect a version mismatch with the gateway (exit code 42), which triggers freenet update automatically.
Release is complete when:
Once ALL criteria are met (including post-release monitoring), mark the release as complete using the window ID captured in Step 0:
tmux rename-window -t "$RELEASE_WINDOW" "✓ release X.Y.Z"