Store Submit
zhitongblog/solomd
Publish a SoloMD release to the stores that have no usable submission API — Google Play Console and Microsoft Partner Center — by driving them through the local Unzoo Browser REST API.
A skill your agent uses when cutting a geoparquet-io release - builds the CHANGELOG section from merged PRs in the house style, stops for human review, then bumps, tags and posts the GitHub release…
$ npx skills add geoparquet/geoparquet-io --skill release -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install geoparquet/geoparquet-io release --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/geoparquet/geoparquet-io.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/release .claude/skills/release && rm -rf skills-srcUse ~/.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/
Install the "release" agent skill from https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/release into .claude/skills/release/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "release", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/releaseType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add geoparquet/geoparquet-io --skill release -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install geoparquet/geoparquet-io release --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geoparquet/geoparquet-io.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/release .agents/skills/release && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "release" agent skill from https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/release into .agents/skills/release/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "release", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add geoparquet/geoparquet-io --skill release -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install geoparquet/geoparquet-io release --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geoparquet/geoparquet-io.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/release .cursor/skills/release && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "release" agent skill from https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/release into .cursor/skills/release/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "release", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/geoparquet/geoparquet-io.git --path .claude/skills/release--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add geoparquet/geoparquet-io --skill release -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install geoparquet/geoparquet-io release --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geoparquet/geoparquet-io.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/release .gemini/skills/release && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "release" agent skill from https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/release into .gemini/skills/release/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "release", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install geoparquet/geoparquet-io releaseInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add geoparquet/geoparquet-io --skill release -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/geoparquet/geoparquet-io.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/release .github/skills/release && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "release" agent skill from https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/release into .github/skills/release/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "release", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add geoparquet/geoparquet-io --skill release -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install geoparquet/geoparquet-io release --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geoparquet/geoparquet-io.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/release .opencode/skills/release && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "release" agent skill from https://github.com/geoparquet/geoparquet-io/tree/main/.claude/skills/release into .opencode/skills/release/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "release", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
releaseA skill your agent uses when cutting a geoparquet-io release - builds the CHANGELOG section from merged PRs in the house style, stops for human review, then bumps, tags and posts the GitHub release…
Release is an agent skill from geoparquet/geoparquet-io. Use when cutting a geoparquet-io release - builds the CHANGELOG section from merged PRs in the house style, stops for human review, then bumps, tags and posts the GitHub release notes.
Its SKILL.md is about 2.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Development, covering Changelog and release notes and App store release. It works with GitHub. The repository describes itself as: A collection of tools for GeoParquet, built on DuckDB, GDAL & Obstore. The licence is Apache-2.0.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 36cf228. It shows what the files ask for, not the result of running them.
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.
Shell commands in SKILL.md call:
uvgitghpython3From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use uv, git and gh, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Release loads about 2.3k tokens when it runs. Until then it costs about 48 tokens; SKILL.md has 1,133 words of instructions outside code blocks.
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.
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.
The full file from geoparquet/geoparquet-io at commit 36cf228, republished under its Apache-2.0 licence (© geoparquet). 1,133 words, ~2,290 tokens.
.claude/skills/release/SKILL.md (or your agent's skills folder).Every release section of CHANGELOG.md is generated, never hand-written. It is
GitHub's own release-note list — one line per pull request, with its author and
number — grouped into Keep a Changelog sections, under two to four paragraphs of
highlights that you write.
There is a mandatory human review checkpoint at step 5. Nothing is bumped, tagged or published before the user approves the changelog section.
git checkout main && git pull
gh run list --branch main --limit 5 # main must be green
git status --short # must be clean
uv run pytest -n auto -m "not slow and not network and not meta"Pick the version from what merged: a ! title or a withdrawn command means
minor at least (this project is 1.x and pre-1.0 rules no longer apply), new
commands mean minor, fixes alone mean patch.
uv run python scripts/release_notes.py <version> --previous v<previous> --writeThis replaces the ## Unreleased block with the new section. It refuses to run
twice for one version. Without --write it prints to stdout, which is the way
to preview.
### UncategorizedPull requests whose titles carry no conventional-commit type land there. Do not
edit the changelog by hand and do not touch the pull request: add a rewritten
title to scripts/release_title_overrides.json, keyed by PR number, and run the
generator again. The type you give it is what files the entry.
"645": "fix(geometry): stop the SIGSEGV in repair on tables with NULL geometry rows"Read each pull request before you retitle it, and write the line a user should
read. A test, ci, chore, style or build type files the entry as
housekeeping, which is not listed — correct for a chore, wrong for a fix wearing
the wrong type, so pick deliberately. Two judgements the script cannot make:
! when the change removes a command, changes a default, or
withdraws a capability, even though the merged title had none. Squash merges
take the PR title, so a ! written in a commit body is already lost. This is
how an entry reaches ### Breaking.build(deps) so they sit with the bot bumps.Regenerate until ### Uncategorized is gone. Rerunning is safe: the overrides
file makes the whole section reproducible, so nothing is lost to a second run.
Replace the <!-- TODO ... --> placeholder with two to four paragraphs, written
after reading the Breaking, Added and Changed entries. Cover, in this order:
The last paragraph is not optional. Get the material from:
uv run python scripts/release_notes.py <version> --previous v<previous> --contributorsThat prints every pull request each new contributor wrote, not only the first one GitHub names. For each person: say how many pull requests they sent when it was more than one, summarize the work in a sentence or two — the actual substance of it, so they can see they were read — thank them, and close by inviting them back. Do not reduce a run of ten pull requests to "various fixes".
Do not restate the entry list. Aim for what a user needs to decide whether to upgrade, and what a contributor needs to feel their work was noticed.
Show the user the rendered section and wait for explicit approval. Say what you want checked:
### Uncategorized, and anything you promoted to
### BreakingDo not run step 6 until the user approves. If the release ships alongside other work, put the changelog in that pull request and let review happen there.
update_changelog_on_bump is off, so cz bump touches versions only and leaves
the section you just wrote alone.
git checkout -b release/bump-v<version>
uv run cz bump --yes # pyproject.toml + [tool.commitizen].versioncz bump usually cannot commit here. A pre-commit hook rewrites files
mid-run, cz sees a dirty tree and stops, so you get the version edit with no
commit and no tag. That is fine — make the commit yourself, with cz's own
message format, because publish.yml triggers on a head commit that starts
with bump::
git commit -am "bump: version <previous> → <version>" # re-run if a hook edits filesCheck what you are committing. cz bump leaves uv.lock alone, so bump the
geoparquet-io package version in it by hand — one line:
[[package]]
name = "geoparquet-io"
version = "<version>"Never run uv sync to do that. An older local uv rewrites the whole lockfile
into an older format (revision = 3 → revision = 1, every upload-time
stripped, thousands of lines) which is a downgrade, not a dependency change.
uv lock --check tells you whether your uv agrees with the committed lock; if
it does not, upgrade uv rather than committing the churn.
git push -u origin release/bump-v<version>
gh pr create --title "bump: version <previous> → <version>"The PR title matters twice: the squash commit is what publish.yml matches on,
and pr-title checks it. bump is a valid commitizen type, so this passes.
Merging that PR fires .github/workflows/publish.yml, which tags v<version>,
publishes to PyPI, and creates the GitHub release.
The workflow's release body is a placeholder. Replace it with the section you wrote, plus a link back to the changelog anchor. This drops GitHub's own listing of the internal and dependency pull requests, which is the intent: the compare link at the end of the section still reaches all of them.
python3 - <<'PY' > /tmp/notes.md
import pathlib, re
v = "<version>"
t = pathlib.Path("CHANGELOG.md").read_text()
start = t.index(f"## v{v} ")
end = t.find("\n## ", start + 1)
heading, body = t[start:end].split("\n", 1)
# GitHub's anchor: the heading lowercased, anything but a letter, digit, space
# or hyphen dropped, then spaces to hyphens. "## v1.4.0 (2026-08-30)" gives
# "v140-2026-08-30" - the dots go, so do not build this from the version string.
anchor = re.sub(r"[^a-z0-9 -]", "", heading[3:].lower()).replace(" ", "-")
print(body.strip())
print()
print(f"Full changelog entry: https://github.com/geoparquet/geoparquet-io/blob/main/CHANGELOG.md#{anchor}")
PY
gh release edit v<version> --notes-file /tmp/notes.mdOpen the printed link and confirm it lands on the heading before you finish.
Check the published artifact, not the local tree:
uv run --isolated --no-project --with "geoparquet-io==<version>" gpio --version
gh release view v<version> --json assets --jq '[.assets[].name]'The release should carry four assets: the wheel, the sdist, and an attestation for each.
The workflow creates the tag before it uploads, so a failed upload leaves a
tag with no release and nothing on PyPI. Nothing is half-published — the
upload is the last step — so do not delete the tag. Fix the cause on main,
then re-run:
gh workflow run publish.yml --ref mainThat is the documented recovery path: the run sees the tag already exists and the release does not, skips tag creation, rebuilds, publishes and creates the release.
Seen once, for the record: gh-action-pypi-publish v1.14.0 rejected the wheel
with InvalidDistribution: '2.5' is not a valid metadata version, because
hatchling had started writing Metadata-Version: 2.5 and the action's bundled
Twine predated it. Fixed by bumping the action pin, not by downgrading the
build backend or skipping verification.
- <title> by @<author> in #<number>. Titles come
from the pull request, or from scripts/release_title_overrides.json where one
did not follow the convention. .github/workflows/pr-title.yml checks new
titles, so the overrides file should stop growing.docs/CHANGELOG.md is generated from the root file by the doc-sync
pre-commit hook. Never edit it.© geoparquet, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/release of geoparquet/geoparquet-io.
Open the folder on GitHubat commit 36cf228
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Release this skillgeoparquet/geoparquet-io | 172 | — | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| Store Submitzhitongblog/solomd | 1.2k | — | ~1.7k | Automated safety check: Notes | MIT | |
| Release New Versionkcsujeet/ilamy-calendar | 351 | — | ~5.8k | Automated safety check: Pass | MIT | |
| Release Asc CLIrorkai/App-Store-Connect-CLI | 7.7k | — | ~2.4k | Automated safety check: Pass | MIT | |
| Releasebmeares/Meerschaum | 154 | — | ~1.1k | Automated safety check: Notes | Apache-2.0 | |
| Cutting A ReleaseTriliumNext/Trilium | 38k | — | ~3.2k | Automated safety check: Pass | AGPL-3.0 |
zhitongblog/solomd
Publish a SoloMD release to the stores that have no usable submission API — Google Play Console and Microsoft Partner Center — by driving them through the local Unzoo Browser REST API.
kcsujeet/ilamy-calendar
Cut a new release of @ilamy/calendar — analyze commits since the last tag, suggest a semver bump, draft a CHANGELOG entry in the project's existing style, run the CI gate, commit, tag, push to…
rorkai/App-Store-Connect-CLI
Publish and verify a new release of the App-Store-Connect-CLI repository.
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.
TriliumNext/Trilium
A skill your agent uses when cutting, preparing, or debugging a Trilium release — bumping the monorepo version, tagging, or diagnosing a failed "Release" workflow run.
tw93/Mole
Runbook for assessing and executing a Mole CLI release: distribution channels, pre-flight checks, capital-V tags, build artifacts and the handoff to curated release notes.
Works with
Categories
A skill your agent uses when cutting a geoparquet-io release - builds the CHANGELOG section from merged PRs in the house style, stops for human review, then bumps, tags and posts the GitHub release…. Release is an agent skill from geoparquet/geoparquet-io. Use when cutting a geoparquet-io release - builds the CHANGELOG section from merged PRs in the house style, stops for human review, then bumps, tags and posts the GitHub release notes.
Release fits situations like: cutting a geoparquet-io release - builds the CHANGELOG section from merged PRs in the house style; stops for human review; tags and posts the GitHub release notes.
Run `npx skills add geoparquet/geoparquet-io --skill release -a claude-code`. Or copy the skill folder (.claude/skills/release in geoparquet/geoparquet-io) into .claude/skills/release in your project. Claude Code loads it when a task matches its description.
Run `npx skills add geoparquet/geoparquet-io --skill release -a codex`. Or copy the skill folder (.claude/skills/release in geoparquet/geoparquet-io) into .agents/skills/release in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add geoparquet/geoparquet-io --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.
Going by SKILL.md and its folder, Release needs the command-line tools its instructions call (uv, git, gh and python3). Our summary lists: Python 3.
SKILL.md contains no URLs. Its commands use uv, git and gh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
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.
Release is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.3k tokens (SKILL.md is roughly 9.2k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Release: Store Submit (zhitongblog/solomd, 1.2k stars), Release New Version (kcsujeet/ilamy-calendar, 351 stars), Release Asc CLI (rorkai/App-Store-Connect-CLI, 7.7k stars) and Release (bmeares/Meerschaum, 154 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
geoparquet (a GitHub organization) maintains it in geoparquet/geoparquet-io, which has 172 GitHub stars. The repository was last updated on October 4, 2026.
Source: geoparquet/geoparquet-io on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.