agentsclimarketplace

Git trunk branch and pr automation

Skill stealth-engine/skills/skills/git-trunk-branch-and-pr-automation

Agent skills we use daily in the studio — reusable, on-demand context for Claude Code, Cursor & other skills.sh-compatible AI agents. Install: npx skills add stealth-engine/skills

Install
npx -y skills add stealth-engine/skills --skill git-trunk-branch-and-pr-automation

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Trunk-based Git workflow with enforced branch naming and squash-merge PR titles. Use when setting up or standardising a branch/PR workflow, naming branches (feature/ fix/ hotfix/ and AI-agent prefixes claude/ cursor/ codex/ copilot/ codegen-bot/ dependabot/), configuring squash-only merges where the PR title becomes the commit and the body is the concatenated commits, making the PR title a valid Conventional Commit, adding GitHub Actions that validate branch names or auto-normalise PR titles, fixing a PR-title bot that loops, or deciding trunk vs release branches. Covers the GitHub repo settings, the validation/normalisation workflows, and how it feeds semantic-release.

SKILL.md

8.5 KB, as published. Nobody here has run it

Trunk-based branches + squash-PR automation

A trunk-based workflow where every change is a short-lived branch off main, merged via squash with a Conventional Commit PR title. That title becomes the single commit on main that semantic-release reads — so naming and title hygiene aren't cosmetic, they drive the release.

Templates: templates/ — branch-name validation, the PR-title normaliser workflow, and the shared normalize-pr-title.js.

The model

  • Trunk-based: branch off main, keep PRs small, merge frequently; main stays releasable. Don't use long-lived develop/release branches unless you must stabilise a release while trunk moves on, or support multiple live versions.
  • Branch naming: feature/<desc>, fix/<desc>, hotfix/<desc> — plus AI-agent prefixes claude/ cursor/ codex/ copilot/ codegen-bot/ dependabot/ for agent- and bot-authored branches. Validated by branch-name-check.yml.

Squash merge: the PR title is the commit

Configure the repo so a merge collapses to one clean, semantic commit:

  • GitHub → Settings → General → Pull Requests: enable Squash merging only (turn off merge commits and rebase). Set "Default commit message" → "Pull request title and commit details" — GitHub then uses the PR title as the squash subject (it appends (#<PR-number>), which doesn't affect Conventional Commit parsing) and concatenates the PR's commit messages into the body.
  • So: the title must be a valid Conventional Commit (it's what semantic-release analyses → version + changelog); the body (the concatenated commits) preserves the detailed history.
  • Keep a PR to one logical change (in a monorepo, one package) so the single squashed commit maps cleanly to one type+scope. See conventional-commits.

PR-title automation

pr-title-manager.yml + normalize-pr-title.js keep the title valid:

  • On open/reopen/synchronize it normalises the title to Conventional Commits (lowercasing the type, or synthesising <type>: <subject> from the PR's commits / branch prefix when the title isn't conventional).
  • A correct title is left untouched; the skip-title-automation label opts out of the auto-rewrite for the rare edge case (still validated — see Opting out below).
  • It posts a sticky comment explaining the squash convention.
  • Install the script at .github/scripts/normalize-pr-title.js; the workflow sparse-checkouts the .github/scripts directory to load it.

Pair it with branch-name-check.yml, and in branch protection require both checks (plus your release/CI checks) before a PR can merge.

Opting out of the auto-rewrite

There are two cases — and the first covers almost everyone:

  1. Just write a valid Conventional Commit title. The normaliser only rewrites a title that isn't already conventional; a correct title (feat: add x, fix(api): …) is left completely untouched. There's nothing to "skip" — this is the intended path.
  2. Add the skip-title-automation label (create it once in the repo) only for the rare case where the title isn't conventional yet and you don't want the bot auto-editing it / posting its comment while you sort it out (e.g. mid-review). The label suppresses the auto-rewrite + sticky comment — but not validation: the required check still fails until the title is a valid Conventional Commit (or a type!: breaking commit is reflected by a !). So the label changes who fixes the title (you, not the bot), never whether it must be valid before merge.

The opt-out is a label, not a string in the title, on purpose: the PR title becomes the squash commit semantic-release reads, so any marker left in the title would land in the release commit and silently produce no release. The label is also ignored on the fork/bot validate path (it never edits there, so there's nothing to suppress).

Gotchas

  • Three modes — and don't loop on your own edits. The template classifies each PR: skip only for github-actions[bot] (its own title edits — the workflow listens for edited to re-validate human changes, and skipping its own identity stops the loop). With the default GITHUB_TOKEN this is belt-and-braces — GitHub deliberately doesn't retrigger workflows on events its own token caused, so the bot's edit wouldn't re-fire anyway; the skip only matters if you swap in a PAT or GitHub App token (whose edits do retrigger), so keep it. validate for forks and other bots like dependabot (read-only/untrusted → title is checked but never auto-edited); normalize for same-repo human PRs (run the script + fix the title). Don't blanket-skip all bots — a non-self bot with a non-conventional title would otherwise merge unchecked.
  • Agent/bot branch prefixes don't infer a type. claude/ cursor/ codex/ … are valid branch names, but the normaliser derives the type from the PR's commits (which should be conventional), not the prefix — falling back to chore only if neither title nor commits are conventional. Keep agent commits conventional so the bump is right.
  • Fork / bot PRs are validate-only. pull_request from a fork gets a read-only token and an attacker-controlled checkout, so the template never checks out or runs the (PR-modifiable) script for them — it validates the title inline via the API (read-only) and fails if it isn't a valid Conventional Commit (any type, including non-releasing docs:/chore:), or if a type!:-style breaking commit isn't reflected by a ! in the title. Same-repo human branches (the norm for this trunk-based workflow) are the only ones auto-edited. Configure dependabot with a conventional commit-message.prefix so its titles pass.
  • Squash settings are per-repo and easy to miss — if "Default commit message" is left as "Default" (the first commit's message) instead of "Pull request title and commit details", your carefully-named PR title is ignored at merge.
  • The opt-out suppresses the rewrite, not the validation. The skip-title-automation label stops the auto-edit + sticky comment but the title is still checked (the required check fails until it's a valid Conventional Commit) — full details in Opting out above. A green check always means a releasable title; the label can't bypass that.

See also

Sources

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.