Skip to content
Back to skills

Release

BSecurity

Cut and publish a new ClaudeGate release to the VS Code Marketplace and Open VSX. Use whenever the user asks to "make a release", "publish", "ship", "cut a version", "release vX.Y.Z", "push a new version to the marketplace", or bump the version after landing a change. Handles semver bump, CHANGELOG, tests, bundle, commit, tag, and publishing to both registries (`vsce` + `ovsx`) — pausing for confirmation before the irreversible publish. Trigger even if the user only says "publish this" or "sh...

  • 8 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 23, 2026
ai-agentspythongoshellbashnodeazuregitapidevops

Works with

  • cursor
  • vscode
  • cli
  • api

Security analysis

B80/100
  • mediumUses curl or wget to download content
  • criticalDownloads and executes remote scripts — classic supply chain attack
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 23, 2026

npx -y skills add lntvan166/claudegate --skill release --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Release?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Release
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/lntvan166-release/badge)](https://www.skillsdirectory.com/skills/lntvan166-release)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: release
description: Cut and publish a new ClaudeGate release to the VS Code Marketplace and Open VSX. Use whenever the user asks to "make a release", "publish", "ship", "cut a version", "release vX.Y.Z", "push a new version to the marketplace", or bump the version after landing a change. Handles semver bump, CHANGELOG, tests, bundle, commit, tag, and publishing to both registries (`vsce` + `ovsx`) — pausing for confirmation before the irreversible publish. Trigger even if the user only says "publish this" or "ship it" after finishing a change.
---

# Release ClaudeGate

ClaudeGate is a VS Code extension (`publisher: lntvan166`, `name: claudegate`). A release means: bump the version, record it in the CHANGELOG, verify it builds and tests pass, commit + tag it in git, and publish the `.vsix` to **two** registries — the VS Code Marketplace with `vsce`, and [Open VSX](https://open-vsx.org) with `ovsx`. Open VSX is the registry Cursor, VSCodium, and Windsurf pull from, so shipping there is what lets the extension **auto-update** in those editors — the Marketplace alone doesn't reach them.

The publish step is **irreversible on both registries** — you cannot unpublish or overwrite a version number on either, and neither lets you re-push a version that's already up. So the flow front-loads every check that can fail (tests, bundle, auth) *before* committing anything, and **pauses for the user's explicit go-ahead** before publishing.

Publish the **same `.vsix` artifact** to both registries — build it once with `vsce package`, then hand that one file to `vsce publish` and `ovsx publish`. That guarantees the two registries carry byte-identical builds instead of two independently-bundled ones.

## Before you start

Confirm you're on `main` with a clean-enough tree, and gather the current state so you pick the right version:

```bash
git branch --show-current                       # expect: main
node -p "require('./package.json').version"      # current version
git tag --sort=-v:refname | head -5              # recent tags
git status --short                               # what's uncommitted
```

The uncommitted change being released is usually already in the working tree (like the fix we just made). Note any **untracked** files — they must NOT end up in the release commit (see step 6).

> The zsh line `compdef:153: _comps: assignment to invalid subscript range` is harmless shell-init noise on this machine — ignore it in command output.

## Tooling — install what's missing

The release needs `vsce` and `ovsx` (both required — one per registry) and optionally `gh` (only if the user wants a GitHub Release too). If a required tool is missing, install it rather than stopping — that's expected, not a blocker. Check first, install only the gap:

```bash
vsce --version   # if "command not found": npm install -g @vscode/vsce
ovsx --version   # if "command not found": npm install -g ovsx
gh --version     # only needed for the optional GitHub Release step below
```

- **vsce** — `npm install -g @vscode/vsce`. Publishes to the VS Code Marketplace.
- **ovsx** — `npm install -g ovsx`. Publishes to Open VSX. Note the package is `ovsx`, *not* `@vscode/ovsx`.
- **gh** — install with the platform's package manager (this machine is Debian/Ubuntu Linux: `sudo apt-get install -y gh`; macOS: `brew install gh`). It may prompt for a sudo password — if so, tell the user to run it themselves via `! sudo apt-get install -y gh`. After install, `gh auth login` is needed once before it can create releases.

Installing a global CLI tool modifies the user's system, so mention what you're about to install before doing it. Never install tools the release doesn't actually need.

## Pick the version bump (semver)

Base the bump on the nature of the change being shipped:

- **patch** (`1.3.1 → 1.3.2`) — bug fix, UX/message tweak, docs, internal-only change. Most releases.
- **minor** (`1.3.2 → 1.4.0`) — new command or feature, or a backward-compatible behavior change.
- **major** (`1.4.0 → 2.0.0`) — a breaking change to how users interact with the extension.

If it's ambiguous, state your reasoning and pick the lower bump — under-bumping is cheaper to correct than a premature major.

## Steps

Do 1–5 first (all reversible). Then **stop and ask before 6 onward.**

### 1. Run the full test suite — green baseline before anything else

```bash
npm test
```

This runs the TS unit tests (`test:unit`) and the Python hook tests (`test:hook`). If anything fails, stop and fix it — never publish on red. This is why we test before bumping: no point versioning a broken build.

### 2. Bump the version

```bash
npm version <new-version> --no-git-tag-version
```

`--no-git-tag-version` bumps `package.json` (and `package-lock.json`) without letting npm create its own commit/tag — you control those in steps 6–7 so the message and trailer are right.

Note: `package-lock.json` has historically drifted (it sat at `1.1.7` for many releases). `npm version` re-syncs it, so **include it in the commit** even though it looks unrelated.

### 3. Add the CHANGELOG entry

`CHANGELOG.md` follows [Keep a Changelog](https://keepachangelog.com/) + semver. Insert a new section above the previous version's, using today's date and the `### Added / ### Changed / ### Fixed / ### Internal / ### Notes` headings that apply. Match the existing voice: each bullet leads with a **bold plain-English summary of the user-visible effect**, then explains the mechanism and the *why*. Look at the top two existing entries and mirror their density.

If the change requires users to re-run **Setup Hook** (any `hooks/hook.py` change), add a `### Notes` bullet saying so.

### 4. Verify the production bundle builds

```bash
npm run bundle
```

This is exactly what `vsce publish` runs via `vscode:prepublish`. Running it now surfaces esbuild/bundling failures while they're still cheap to fix, not mid-publish. Confirm `out/extension.js` is produced.

### 5. Verify publish auth (both registries) — before committing

```bash
vsce verify-pat lntvan166
```

Checking the Marketplace Personal Access Token now means you won't get halfway through (commit + tag pushed) only to discover you can't publish. If it fails, the PAT has expired — the user must refresh it in Azure DevOps (Marketplace → Manage scope) and re-run `vsce login lntvan166`; suggest they do this via `! vsce login lntvan166` so the interactive prompt lands in the session.

**Open VSX auth is different — there's no `verify-pat` equivalent**, so the token is only validated at publish time (step 9). Confirm the two one-time prerequisites are in place before you rely on it:

- **Eclipse Foundation Open VSX Publisher Agreement** must be signed once, via the maintainer's open-vsx.org account (log in with GitHub → user settings → Publisher Agreement). This is the most common first-time failure — `ovsx publish` rejects an unsigned account.
- **Namespace `lntvan166`** must exist. It does (created once with `ovsx create-namespace lntvan166 -p <token>`); re-running that just reports "Namespace already exists", which is fine.

The **access token** comes from https://open-vsx.org/user-settings/tokens. Treat it as a secret: pass it as `-p <token>` on the publish command or via the `OVSX_PAT` env var, and **never write it into a committed file or this skill**. If the user hasn't provided one, ask them to run the publish step themselves via `! ovsx publish … -p <token>` so the secret stays in their session rather than being echoed back through you.

### — PAUSE HERE —

Summarize what's about to happen: new version, the CHANGELOG bullets, test/bundle/auth all green. Then ask the user to confirm before you commit, tag, and publish. Publishing cannot be undone, so this gate is deliberate.

### 6. Commit — only the release files

Stage the version files, the CHANGELOG, and the actual code/hook change being released. **Never `git add -A`** — the working tree often has unrelated untracked files (stray `.release-notes-*.md`, draft docs) that must not enter the release commit or the package.

```bash
git add package.json package-lock.json CHANGELOG.md <changed-source-files>
git commit -F - <<'EOF'
release: vX.Y.Z — <one-line summary of the change>

<optional short body explaining the why>

Co-Authored-By: Claude <noreply@anthropic.com>   # use the model that did the work
EOF
```

Then re-check `git status --short`: only your intended files should be committed; untracked strays should still be sitting there untracked.

### 7. Tag the release

```bash
git tag -a vX.Y.Z -m "release: vX.Y.Z — <same summary>

Co-Authored-By: Claude <noreply@anthropic.com>   # use the model that did the work"
```

Annotated (`-a`) tags carry a message and author — the project uses these, not lightweight tags.

### 8. Push commit and tag to GitHub — BEFORE publishing

```bash
git push origin main
git push origin vX.Y.Z
```

**This must happen before the publish, not after.** The VSIX no longer ships the
README's images (`.vscodeignore` excludes `media/*.mp4`, `media/demo.gif` and the
screenshot PNGs — that's what took the package from 1.41 MB to 81 KB). Both
registries render the README by fetching its images from GitHub over HTTPS, so the
listing has **no packaged fallback**: publish before pushing and the store page
shows broken images until the push lands.

Confirm they resolve before you publish — a 404 here means something is unpushed:

```bash
for u in demo.gif ClaudeGateDemo.png ReviewAllPending.png; do
  printf "%-22s %s\n" "$u" \
    "$(curl -s -o /dev/null -w '%{http_code}' https://raw.githubusercontent.com/lntvan166/claudegate/main/media/$u)"
done   # expect 200 for every line
```

### 9. Package once, then publish to both registries

Build the artifact a single time so both registries get an identical `.vsix`:

```bash
vsce package                                       # → claudegate-X.Y.Z.vsix (runs vscode:prepublish)
```

**Expected output: 13 files, ~82 KB.** That is the regression check — the package
is code + hook + two icons + walkthrough markdown and nothing else. If it comes out
in the hundreds of KB or megabytes, media has crept back in; fix `.vscodeignore`
before publishing rather than shipping a bloated download.

Then publish that same file to each registry:

```bash
vsce publish --packagePath claudegate-X.Y.Z.vsix   # VS Code Marketplace
ovsx publish  claudegate-X.Y.Z.vsix -p <token>     # Open VSX (or set OVSX_PAT and drop -p)
```

Report the version and the Marketplace URL.

**Both registries index AFTER the CLI reports success — poll, don't panic.** A
verification run immediately after publishing returns the **previous** version, and
`https://open-vsx.org/api/.../X.Y.Z` returns **404**. That is propagation delay, not
a failed release. Measured on v1.12.0: Open VSX went live ~75 s after `ovsx` printed
success, the Marketplace ~3.5 min after `vsce` did. Wrap the check in a loop rather
than reading it once:

```bash
for i in $(seq 1 25); do
  o=$(curl -s https://open-vsx.org/api/lntvan166/claudegate | python3 -c "import sys,json;print(json.load(sys.stdin).get('version','?'))" 2>/dev/null)
  m=$(vsce show lntvan166.claudegate 2>/dev/null | grep "^  Version:" | awk '{print $2}')
  echo "t+$((i*20))s  openvsx=$o  marketplace=$m"
  [ "$o" = "X.Y.Z" ] && [ "$m" = "X.Y.Z" ] && echo "BOTH LIVE" && break
  sleep 20
done
```

Before concluding anything is wrong, check how much time has actually passed —
against the release commit's own timestamp (`git log -1 --format=%ci`), not a
session clock. Misjudging that turned a normal 90-second wait into a false alarm once.

**"Already published" on Open VSX is a success, not a failure.** The maintainer also
publishes to Open VSX by a parallel route (an automated/mirror path under the same
`lntvan166` account), so `ovsx publish` may report `Extension lntvan166.claudegate
X.Y.Z is already published` — the version is already live; don't force it. Either
outcome is fine: a clean `🚀 Published` means the manual path won the race. Neither
registry can overwrite an existing version, so a duplicate error is confirmation.

### 10. (Optional) GitHub Release

This project's flow is tags-only, so skip this unless the user asks for a GitHub Release. If they do and `gh` isn't installed, install and authenticate it (see **Tooling** above), then:

```bash
gh release create vX.Y.Z --title "vX.Y.Z" --notes "<paste the CHANGELOG section>"
```

## After publishing

- Confirm the published version on **both** registries and link them:
  - Marketplace: `https://marketplace.visualstudio.com/items?itemName=lntvan166.claudegate`
  - Open VSX: `https://open-vsx.org/extension/lntvan166/claudegate`
- **Check the package file list** that `vsce package` printed. Files under `src/`, `.claude/`, `docs/`, `.github/`, `CLAUDE.md`, and `CHANGELOG.md` are excluded via `.vscodeignore`. If a stray untracked file (e.g. a leftover `.release-notes-*.md`) shows up in the listing, it means `.vscodeignore` is missing a pattern — flag it and offer to add the exclusion before the next release.
- **Delete the local `.vsix`** once both publishes are done (`rm claudegate-X.Y.Z.vsix`) — it's a build artifact, not something to commit.

## What NOT to do

- Don't publish on failing tests or a failing bundle.
- Don't `git add -A` / `git add .` — you'll sweep in untracked strays.
- Don't hardcode the Open VSX token into this skill, a script, or any committed file — it's a secret; pass it at publish time or via `OVSX_PAT`.
- Don't treat an Open VSX "already published" error as a failure — the version is live; a duplicate can't be overwritten on either registry (verify via the API and move on).
- Don't let `vsce` and `ovsx` each build their own package — `vsce package` once and publish that one `.vsix` to both, so the registries stay byte-identical.
- Don't create a GitHub Release unless the user asks — this project's flow is tags-only (step 10 covers it if they want one).
- Don't skip the confirmation pause. Neither registry has an undo.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…