Releasing Php Package
yansongda/pay
A skill your agent uses when preparing to publish a new version of a PHP Composer package and need to write or update CHANGELOG, upgrade guides, and documentation before tagging and releasing
Cut a new Marko release. An agent skill from marko-php/marko.
$ npx skills add marko-php/marko --skill release -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install marko-php/marko 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/marko-php/marko.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/marko-php/marko/tree/develop/.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/marko-php/marko/tree/develop/.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 marko-php/marko --skill release -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install marko-php/marko release --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/marko-php/marko.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/marko-php/marko/tree/develop/.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 marko-php/marko --skill release -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install marko-php/marko release --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/marko-php/marko.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/marko-php/marko/tree/develop/.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/marko-php/marko.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 marko-php/marko --skill release -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install marko-php/marko release --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/marko-php/marko.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/marko-php/marko/tree/develop/.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 marko-php/marko 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 marko-php/marko --skill release -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/marko-php/marko.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/marko-php/marko/tree/develop/.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 marko-php/marko --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 marko-php/marko release --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/marko-php/marko.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/marko-php/marko/tree/develop/.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.
releaseCut a new Marko release. An agent skill from marko-php/marko.
Release is an agent skill from marko-php/marko. Cut a new Marko release. Reads every PR merged since the last tag, audits their release-notes labels, recommends the next version number with reasoning, and — only after you confirm or override it — runs ./bin/release.sh. Use this skill whenever the user types /release or asks to cut, ship, publish, or tag a release. Takes no arguments; the version is decided in conversation, not on the command line.
Its SKILL.md is about 2.9k 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. It works with PHP and Git. The repository describes itself as: The modular PHP framework. The licence is MIT.
7 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 0a400a7. 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:
gitghphpcomposerFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
packagist.orgFrom 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.9k tokens when it runs. Until then it costs about 104 tokens; SKILL.md has 1,536 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 marko-php/marko at commit 0a400a7, republished under its MIT licence (© marko-php). 1,536 words, ~2,866 tokens.
.claude/skills/release/SKILL.md (or your agent's skills folder).bin/release.sh already automates everything mechanical: the full test suite, the
develop → main merge, changelog generation, the tag, the GitHub Release, and the
merge-back to develop. It does not decide whether to release or what to call it.
That judgment is this skill's only job.
Two things must be right before a tag is pushed, and both are listed as manual in
.claude/release-process.md:
There is exactly one approval gate: present the recommendation, stop, and wait. Do not tag on your own initiative — not even for an obviously-correct patch bump.
None. /release takes no arguments; the version is settled at the approval gate in step 5.
If the user does type something after /release anyway, treat it as an authoritative
override and skip straight to validating it (same checks as an override at the gate).
git fetch --quiet --tags origin develop main
git status --short # must be empty
git rev-parse --abbrev-ref HEAD # must be develop
git rev-list --count origin/develop..develop # must be 0 (nothing unpushed)
git rev-list --count develop..origin/develop # must be 0 (nothing unpulled)
php -v # must be 8.5.x, else set PHP_BIN
command -v gh jq # both required by bin/release.shAlso confirm there is something to release: git log $(git tag --sort=-v:refname | head -1)..develop --oneline must be non-empty.
If any check fails, say exactly which one and stop. Do not quietly fix it — an unpushed commit or a dirty tree usually means work is still in flight, which is the user's call, not yours.
If php -v is not 8.5, don't abandon the run — pass an explicit interpreter through to
the script instead: PHP_BIN=/path/to/php8.5 ./bin/release.sh X.Y.Z.
LAST_TAG=$(git tag --sort=-v:refname | head -1)
git log "$LAST_TAG"..develop --pretty='%s' | grep -oE '#[0-9]+' | sort -uRead every PR you found — title, body, and labels. Commit subjects alone will mislead you about scope:
gh pr view <N> --json number,title,body,labels,urlFlag any commit on develop with no #NN reference. bin/release.sh builds the notes
by walking git log and resolving PR numbers, so an unreferenced commit is silently
omitted from both CHANGELOG.md and the GitHub Release. Surface these at the gate; the fix
is a follow-up commit that mentions the PR, not a hand-edited changelog.
.github/release.yml buckets PRs into release-notes sections by label. Anything unlabeled
lands in "Other Changes"; anything mislabeled lands in the wrong section.
| Label | Section |
|---|---|
breaking | Breaking Changes |
enhancement | New Features |
bug | Bug Fixes |
documentation | Documentation |
refactor | Refactoring |
testing | Testing |
ci | CI |
maintenance | Maintenance |
duplicate, invalid, wontfix, question, good first issue, and help wanted are
excluded from the notes entirely — a release-worthy PR carrying only one of those is a
labeling bug.
Propose label corrections at the gate rather than applying them silently. When applying
them, note that gh pr edit silently fails on this repo (GraphQL Projects-classic bug) —
use the REST endpoint:
gh api repos/marko-php/marko/issues/<N>/labels -f "labels[]=bug"
gh api repos/marko-php/marko/issues/<N>/labels/enhancement -X DELETEMarko is in 0.x: all 70 packages share one version, and 1.0.0 is the first release with
semver guarantees. Compute from the latest tag.
0.8.4 → 0.8.5) — bug fixes, documentation, CI, refactors, tests, and
additive changes that add no public API surface.0.8.4 → 0.9.0) — a new package, new public API, or any breaking change.
While in 0.x there is no separate major channel, so breaking changes ride the minor.1.0.0) — never infer this. Only when the user says the API is stable.Labels route a PR into a release-notes section. They say nothing about the bump. The
enhancement label feeds a section titled "New Features" — that is a heading, not a minor
version. Judge every enhancement on its own merits; do not let one in the batch
mechanically escalate a patch to a minor.
Classify each PR by what a consumer can observe after composer update:
Never leaves the monorepo — .claude/, bin/, .github/, root tests/, repo docs.
Only packages/* is copied into split repos, so nothing here can reach anyone's
vendor/. Irrelevant to the version, whatever its label. Confirm mechanically:
gh pr view <N> --json files -q '[.files[].path] | map(select(startswith("packages/"))) | length'A 0 means repo-internal tooling. This is the common case for maintainer-facing
enhancement PRs — a new skill, a CI tweak, a release script improvement.
Ships in a package but adds no callable surface — CLI output or prompt wording, a
docs page, an internal refactor, a new fake in marko/testing used only by our own
suite. Nothing new for an app developer to call, extend, configure, or depend on.
Patch. This includes internals added in service of a fix — a new exception factory,
for instance, is thrown at consumers rather than built against, so it does not make a
bug fix into a feature.
Adds or changes surface a consumer builds against — a new interface, method, attribute, config key, container binding, event, console command, or an entire package. Also anything that changes existing behavior an app could already be relying on. Minor.
Only tier 3 forces the minor. A batch of tier-1 and tier-2 work plus a bug fix is a patch,
even when several PRs carry enhancement.
Calibration example — the batch that shipped as 0.8.5, which carried two enhancement
labels and was still correctly a patch:
| PR | Label | Tier | Why |
|---|---|---|---|
| #142, #144 | documentation | 1 | repo docs and skills, nothing under packages/ |
| #143 | enhancement | 2 | a devai:install prompt tip — no new callable surface |
| #146 | enhancement | 1 | maintainer-only /release skill under .claude/ |
| #145 | bug | 2 | unblocked db:migrate; its new exception factory is thrown, not built against |
The tiebreaker for a genuinely mixed batch is Composer reachability. In 0.x, Composer
treats the minor as the breaking position: ^0.8.4 accepts 0.8.5 but refuses 0.9.0. A
patch reaches every downstream project on a plain composer update; a minor sits unnoticed
until someone edits their constraint. So when the release exists to get a fix into users'
hands, and the rest of the batch is tier 1 or 2, prefer the patch. Do not use this as cover
for hiding tier-3 work in a patch — that earns the minor even if it means a slower rollout.
State the decision in one or two lines and cite the PRs driving it. Also check whether the bug being fixed makes a released version unusable — that is the difference between "worth releasing now" and "wait for more to accumulate", and the user should hear which one this is.
Show, concisely:
enhancement in the batch did not escalate the bump, say so explicitly and
why, rather than leaving the user to wonder whether it was overlooked.develop into main, run the full suite
including the integration-destructive group, generate CHANGELOG.md, commit, tag,
push, create the GitHub Release, merge back to develop.Be precise about the failure state — do not promise a clean abort. bin/release.sh
checks out main and merges develop before it runs the tests. A test failure therefore
leaves the local repo checked out on main with the merge already made. Nothing is pushed,
no tag exists, and CHANGELOG.md is untouched — but it is not a no-op. Recovery is
git checkout develop, fix the failure, and re-run; the merge is idempotent. Mention this
when describing what will happen, and note that re-running while still on main trips the
Step 1 branch precondition.
Then wait. If the user overrides the version, validate it before running: X.Y.Z with no
v prefix and no pre-release suffix, strictly greater than the latest tag, and not an
existing tag. If it looks wrong, say so once — then defer if they confirm.
From develop, with a clean tree:
./bin/release.sh <version>Expect this to run for several minutes — the destructive integration group builds real
installs. Let it finish; do not run it in the background and do not re-run it after a
partial failure without reading the error first. If it failed in the test phase you are now
on main — git checkout develop before retrying.
Give the user the version shipped and the GitHub Release URL, then point at the two asynchronous things that finish after the tag:
If the script aborted, relay its error verbatim and stop.
CHANGELOG.md. bin/release.sh generates and commits it; a manual
edit produces a duplicate section and a redundant commit.develop, and never commit directly to
main — the script owns that merge.--exclude-group, no skipping.
A failing destructive-integration test means the release would ship a broken install.enhancement — only tier-3
surface changes force it.© marko-php, MIT. 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 marko-php/marko.
Open the folder on GitHubat commit 0a400a7
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 skillmarko-php/marko | 397 | — | ~2.9k | Automated safety check: Pass | MIT | |
| Releasing Php Packageyansongda/pay | 5.4k | — | ~1.6k | Automated safety check: Pass | MIT | |
| Chamilo Changelog Updaterchamilo/chamilo-lms | 1k | — | ~4.2k | Automated safety check: Pass | GPL-3.0 | |
| React Router Release Notes Prepremix-run/react-router | 57k | — | ~1.1k | Automated safety check: Pass | MIT | |
| Draft Release Notesjamiepine/voicebox | 57k | — | ~941 | Automated safety check: Pass | MIT | |
| Mole Release Notes Publishertw93/Mole | 69k | — | ~1.9k | Automated safety check: Pass | GPL-3.0 |
yansongda/pay
A skill your agent uses when preparing to publish a new version of a PHP Composer package and need to write or update CHANGELOG, upgrade guides, and documentation before tagging and releasing
chamilo/chamilo-lms
Adds commits for a new Chamilo release to the changelog page, classifying them into categories and skipping those already listed for that version.
remix-run/react-router
Polishes pending React Router change files before the versioning scripts run, and decides whether a long-form What's Changed section is warranted.
jamiepine/voicebox
Writes or refreshes the Unreleased section of CHANGELOG.md as a themed narrative built from the commits, PRs and diff since the last version tag.
tw93/Mole
Publishes curated, bilingual release notes for an existing Mole version tag with gh release edit, including contributor thanks and reactions, after the release workflow finishes.
jamiepine/voicebox
Ends a release cycle by moving the Unreleased changelog notes under a dated version heading, bumping version files with bumpversion and tagging the commit.
marko-php/marko
Scaffold a new Marko module — a self-contained Composer package with composer.json, namespaced src/, and Pest tests.
marko-php/marko
Create a Marko plugin — a class that intercepts methods on another class to modify behavior without subclassing.
Categories
Cut a new Marko release. An agent skill from marko-php/marko. Release is an agent skill from marko-php/marko. Cut a new Marko release.
Release fits situations like: the user types /release; tasks that involve Changelog and release notes.
Run `npx skills add marko-php/marko --skill release -a claude-code`. Or copy the skill folder (.claude/skills/release in marko-php/marko) into .claude/skills/release in your project. Claude Code loads it when a task matches its description.
Run `npx skills add marko-php/marko --skill release -a codex`. Or copy the skill folder (.claude/skills/release in marko-php/marko) 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 marko-php/marko --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 (git, gh, php and composer).
SKILL.md names 1 domain. As links in the text: packagist.org. 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 MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.9k tokens (SKILL.md is roughly 11k 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: Releasing Php Package (yansongda/pay, 5.4k stars), Chamilo Changelog Updater (chamilo/chamilo-lms, 1k stars), React Router Release Notes Prep (remix-run/react-router, 57k stars) and Draft Release Notes (jamiepine/voicebox, 57k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
marko-php (a GitHub organization) maintains it in marko-php/marko, which has 397 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on October 6, 2026.
Source: marko-php/marko on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.