Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Release a package to NPM. Validates version bump, changelog, creates release branch, monitors CI, verifies publish.
.claude/skills/tetherto-release/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 20% | 0% |
| case-07 | ✗→✓ | ▲ Improved | -4% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 125% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 0% | 0% |
Release a package to NPM. Ensures version bump, changelog, release branch, CI pipeline, and npm publish.
The package is identified by the <package-name> argument, which is the directory name under packages/ (e.g., ocr-ggml, qvac-sdk, tts-onnx). The skill reads packages/<package-name>/package.json to determine the package type and npm scope.
/release <package-name> [base-branch]
Where:
<package-name> is the directory name under packages/ (e.g., ocr-ggml, tts-onnx)[base-branch] is optional — the branch to create the release from. Defaults to main. Use this for patches, e.g., /release ocr-ggml release-ocr-ggml-0.11.0packages/$ARGUMENTS/package.json to get the current version and npm package name.bash npm view <npm-package-name> version
^## \[<version>\] — heading must be bracketed (Keep-a-Changelog style). Soft phrasing like "section for 0.1.0" is not enough; the heading line must literally be ## [0.1.0].Run this exact check (mirrors the regex in .github/workflows/create-github-release.yml): bash version=$(node -p "require('./packages/<package>/package.json').version") if ! grep -qE "^## \[${version}\]" "packages/<package>/CHANGELOG.md"; then echo "FAIL: packages/<package>/CHANGELOG.md is missing a '## [${version}]' heading." echo " A heading like '## ${version}' (no brackets) will NOT match — publish-release will fail." exit 1 fi
If the check fails, fix the heading or generate the section first:
/qv-addon-changelog/qv-sdk-changelogDisplay a summary and ask for confirmation before proceeding:
Release summary:
Package: <package>
Version: <version>
Branch: release-<package>-<version>
Target: NPM (latest tag)
Proceed? (y/n)bash git checkout <base-branch> git pull origin <base-branch> Where <base-branch> is determined in Step 1 (main for new releases, release-<package>-<base-version> for patches).
bash git checkout -b release-<package>-<version>
bash git push origin release-<package>-<version>
bash gh workflow run "on-merge-<package>.yml" --repo tetherto/qvac --ref release-<package>-<version>
This workflow:
release-merge-guard (validates version bump + changelog)latest tag<package>-v<version>Use /loop to poll the pipeline status every 2 minutes:
/loop 2m Check the CI pipeline status for the release branch release-<package>-<version>. Run: gh run list --branch release-<package>-<version> --limit 5. If all runs completed successfully, report SUCCESS and stop. If any run failed, report the failure details. If still running, report progress.Once CI completes successfully:
bash npm view @qvac/<package>@<version> version (Note: some packages may not have the @qvac/ scope — check package.json for the actual package name)
bash gh release view <package>-v<version>
Release complete: Package: <npm-package-name>@<version> NPM: published GitHub Release: <package>-v<version> Branch: release-<package>-<version>
Verify the published package is publicly accessible without authentication by installing it in a clean temp directory with no npm token:
bash# Create a temp directory and install without any auth TMPDIR=$(mktemp -d) cd $TMPDIR echo "registry=https://registry.npmjs.org/" > .npmrc npm install <npm-package-name>@<version> --ignore-scripts --no-package-lock
If the install succeeds, the package is publicly accessible. If it fails with a 401/403, the package may still be private — flag this to the user.
Sanity checks on the installed package:
bash# Verify the tarball contents look correct npm pack <npm-package-name>@<version> --pack-destination $TMPDIR tar tf $TMPDIR/<tarball-filename> | head -20 # Check that key files are present in the installed package: ls $TMPDIR/node_modules/<npm-package-name>/ # Expected: package.json, README.md, index.js (or similar entry point), prebuilds/ (for addons) # Verify package.json version matches node -e "console.log(require('$TMPDIR/node_modules/<npm-package-name>/package.json').version)"
Clean up:
bashrm -rf $TMPDIR
If any check fails, report the issue to the user before proceeding.
bashgit checkout main
release-merge-guard fails: the version or changelog is missing/incorrect. Fix and re-trigger the workflow.gh run view <run-id> --log-failed.npm view), or if NPM_TOKEN is valid.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 10,359 | 2,639 | -75% | 1 | 1 | 0% | 1,927 | 2,029 | +5% | 0 | 0 | — |
case-06 | fail→pass | 10,840 | 2,395 | -78% | 1 | 1 | 0% | 2,009 | 2,146 | +7% | 0 | 0 | — |
case-02 | fail→fail | 3,370 | 4,860 | +44% | 1 | 1 | 0% | 401 | 2,043 | +409% | 0 | 0 | — |
case-03 | fail→fail | 4,450 | 3,052 | -31% | 1 | 1 | 0% | 529 | 2,026 | +283% | 0 | 0 | — |
case-04 | fail→pass | 10,014 | 3,092 | -69% | 1 | 1 | 0% | 1,840 | 2,216 | +20% | 0 | 0 | — |
case-05 | pass→pass | 7,900 | 2,694 | -66% | 1 | 1 | 0% | 1,305 | 2,199 | +69% | 0 | 0 | — |
case-07 | fail→pass | 11,525 | 1,536 | -87% | 1 | 1 | 0% | 2,042 | 1,968 | -4% | 0 | 0 | — |
case-08 | fail→fail | 4,744 | 4,518 | -5% | 1 | 1 | 0% | 922 | 1,948 | +111% | 0 | 0 | — |
case-09 | pass→pass | 7,015 | 4,737 | -32% | 1 | 1 | 0% | 1,153 | 2,536 | +120% | 0 | 0 | — |
case-10 | fail→pass | 5,144 | 1,612 | -69% | 1 | 1 | 0% | 868 | 1,953 | +125% | 0 | 0 | — |
case-11 | fail→pass | 11,191 | 1,668 | -85% | 1 | 1 | 0% | 1,904 | 1,910 | +0% | 0 | 0 | — |
case-12 | fail→pass | 16,123 | 2,813 | -83% | 1 | 1 | 0% | 2,601 | 2,206 | -15% | 0 | 0 | — |
case-13 | fail→pass | 8,896 | 2,316 | -74% | 1 | 1 | 0% | 1,590 | 2,099 | +32% | 0 | 0 | — |
case-14 | fail→fail | 4,032 | 2,360 | -41% | 1 | 1 | 0% | 714 | 2,077 | +191% | 0 | 0 | — |
case-15 | fail→pass | 9,277 | 3,349 | -64% | 1 | 1 | 0% | 1,592 | 2,255 | +42% | 0 | 0 | — |
case-16 | fail→pass | 9,899 | 5,160 | -48% | 1 | 1 | 0% | 1,791 | 2,639 | +47% | 0 | 0 | — |
case-17 | pass→pass | 10,051 | 4,371 | -57% | 1 | 1 | 0% | 1,864 | 2,541 | +36% | 0 | 0 | — |
case-18 | fail→pass | 4,208 | 1,965 | -53% | 1 | 1 | 0% | 681 | 2,008 | +195% | 0 | 0 | — |
case-19 | pass→pass | 4,704 | 2,543 | -46% | 1 | 1 | 0% | 799 | 2,088 | +161% | 0 | 0 | — |
case-20 | fail→fail | 11,301 | 7,134 | -37% | 1 | 1 | 0% | 1,759 | 2,773 | +58% | 0 | 0 | — |
case-21 | fail→fail | 5,985 | 4,917 | -18% | 1 | 1 | 0% | 1,018 | 2,097 | +106% | 0 | 0 | — |
case-22 | pass→pass | 5,503 | 13,850 | +152% | 1 | 1 | 0% | 992 | 4,489 | +353% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +45 percentage points is the difference between those two pass rates over the 20 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.