skill
git-authoring
Agent skill that turns your git diff into clean Conventional Commits — plus on-request file staging and full pull-request drafting. Works with Claude, Codex, Cursor, and Gemini.
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/n-shadloo/git-authoring itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 17, 2026git-authoring
A full git skill for AI coding agents — built for Claude, and portable to Codex, Cursor, and Gemini CLI. It has seven request-selected modes: generate an exact commit command for staged changes; choose one coherent set of files and generate staging plus commit commands; write a pull-request title and description; stage, commit, and push autonomously when explicitly told to do it all; write the release note for a version from what actually landed since the last release; review an incoming pull request and hand you the review comment or the squash-merge message to paste; or work the repository itself — branches, rebases, squashes, cherry-picks, reverts, conflicts, stashes, and recovery through the reflog.
Why
Most commit-message helpers stop at the format: they slap a type: on the front and call it done. The format is the easy part. The hard part is choosing the right type, writing a subject that actually says what changed, and using the body to record why — the context the diff can't show and that you'll want back six months later when git blame drops you on a line. This skill treats the format as table stakes and spends its effort on intent — for pull requests and release notes as much as commits.
It defaults to Conventional Commits (imperative subject, type(scope): …, breaking-change notation, issue references) and enforces that discipline consistently. It also reads the repository's history first, so if a project uses a different convention it matches that instead of imposing one.
What it does
- Reads the staged diff — not just filenames — to infer the change and its intent.
- Picks an accurate Conventional Commit type and a sensible scope.
- Writes an imperative subject within length limits, and a body explaining the why when the change isn't self-evident.
- Notates breaking changes with
!and aBREAKING CHANGE:footer. - Adds issue references (
Closes #123) — and, on request only,Co-authored-by:,Signed-off-by:, and the rest. - Tells you when staged changes should be split into separate commits, and gives you the commands to do it.
- On request, chooses which unstaged files belong together as one coherent commit and gives you the exact staging and commit commands.
- On request, writes a complete pull-request title and description — summary, what changed, testing, breaking changes — from the branch's diff against its base.
- On request, writes the release note for a version from the real range since the last release, in the style your project's previous releases already use.
- On request, reviews an incoming pull request with you — reads its diff, checks, and existing comments, separates what actually blocks a merge from what's only a suggestion, and hands you the review comment or the squash-merge message — or, when you ask, submits the review or merges the pull request itself.
- On request, works the repository itself — branching, merging and rebasing, squashing and splitting commits, cherry-picking, reverting and resetting, stashing, worktrees, resolving merge conflicts, and recovering lost work through the reflog — by reading the real state and giving you the exact commands.
- Keeps every mode except the autonomous one read-only by default, and carries out any git or pull-request action the user asks for: staging, committing, pushing, opening a PR, merging it once its checks pass, submitting a review, tagging, or publishing a release.
- Adds no attribution trailers in any mode unless you ask for them — see Attribution and trailers.
- Runs staging, committing, and pushing itself only when you explicitly ask for the autonomous mode — and tags and publishes a release only on a further explicit ask.
Works with
Claude, Codex, and Cursor all read this as an Agent Skill: SKILL.md plus the
references/ folder, loaded on demand so deeper guidance is pulled in only when a
commit, pull request, or release note needs it. The skill format is a shared standard
across those three tools, so the same folder works in each without changes.
Gemini CLI doesn't read skills — it reads GEMINI.md at the repo root, which carries
the same conventions. A self-contained AGENTS.md at the root is also provided as
always-on project context for any agent that reads it.
Install
The repo is a folder of plain-Markdown instruction files. Claude reads it as an
Agent Skill (SKILL.md plus the references/ folder, loaded on demand).
OpenAI Codex CLI and Cursor reuse the same canonical content through their
native discovery mechanisms, while Gemini CLI reads a single GEMINI.md
context file. Nothing to build; no dependencies beyond git.
Claude
One project:
git clone https://github.com/n-shadloo/git-authoring.git \
.claude/skills/git-authoring
All your projects:
git clone https://github.com/n-shadloo/git-authoring.git \
~/.claude/skills/git-authoring
For claude.ai or the API, upload the folder as a custom skill in Settings.
Codex CLI
Codex CLI discovers Agent Skills from the .agents/skills/ directory and reads
AGENTS.md for always-on project context.
One project:
git clone https://github.com/n-shadloo/git-authoring.git \
.agents/skills/git-authoring
All your projects:
git clone https://github.com/n-shadloo/git-authoring.git \
~/.agents/skills/git-authoring
Codex automatically discovers the skill when appropriate. AGENTS.md provides
project-wide conventions alongside the skill.
Cursor
Cursor also supports Agent Skills, so the same clone works:
git clone https://github.com/n-shadloo/git-authoring.git \
.cursor/skills/git-authoring
Cursor additionally reads AGENTS.md at the repository root.
Gemini CLI
Gemini CLI doesn't read Agent Skills directly; it reads GEMINI.md.
- Per project: copy
GEMINI.mdinto the repository root. - All projects: copy it to
~/.gemini/GEMINI.md.
GEMINI.md carries the same conventions and points at AGENTS.md for the full
detail.
The only requirement is git on your path and a Git repository to run in. GitHub CLI (gh) is optional: release-note mode uses it to read your previous releases and match their style, and the autonomous mode needs it to publish one. Without it, the skill falls back to any CHANGELOG.md / RELEASE*.md in the repo for style and hands you the note as Markdown, telling you which check failed.
Self-improvement
This skill improves itself. After a task, the agent that used the skill can correct wrong or old content and add content that the task needed. SELF-IMPROVEMENT.md gives the rules. Each change needs evidence from the task. The rules keep each change small and keep the core of the skill fixed.
- During a task: the agent writes each skill defect that it finds to
~/.skill-improvements/NOTES.mdat once. Each final report ends with aSkill defects:line, with the outcome of each note or "No skill defect found." - Your copy: the agent changes your local copy. It writes a record of each change to
~/.skill-improvements/git-authoring/. The record stays after an update of the skill. If an update removes a local change, the agent writes the change again at the next use. - The owner: the agent asks you to send the records to the owner as a GitHub issue. It sends nothing without your approval. The owner examines each issue and adds the change for all users.
- To stop it: make the file
~/.skill-improvements/OFF. Then the agent does not change the skill and writes no record.
Use
The skill has one default and five on-request modes. All of them are read-only except the autonomous one: the agent inspects git and gives you commands or Markdown, but you run any operation yourself. Only mode 4 lets the agent mutate git and GitHub, and it carries out exactly the actions you ask for: a commit and a push, opening a pull request, merging one, or submitting a review.
1. Get a commit command for staged changes — the default
Stage what you want to commit, then ask — or just tell the agent you're about to commit:
> write a commit message for my staged changes
It reads the staged diff and returns the exact command for you to run:
git commit -F - <<'COMMIT_MSG'
fix(serializers): handle null profile in user payload
A user without a profile row raised AttributeError during serialization.
Return an empty profile object so the endpoint responds 200 with nulls
instead of 500.
Closes #517
COMMIT_MSG
If the staged changes cover more than one thing, it says so and hands you a sequence of specific staging and heredoc commit commands to split them instead of writing one muddled message. It never runs those commands for you in this mode.
2. Ask it to choose files and prepare the commands — on request
When you have a pile of unstaged work and want the agent to decide what belongs together, ask for it explicitly:
> choose the files that belong in one commit and give me the commands
It reads the staged and unstaged changes, selects the files that form one coherent change — related work only, not everything, not an arbitrary mix — and returns commands like these:
git add users/serializers.py users/tests/test_serializers.py
git commit -F - <<'COMMIT_MSG'
fix(serializers): handle null profile in user payload
COMMIT_MSG
If several unrelated changes are in flight, it selects the strongest coherent group and points out what it deliberately left out. You run both commands; the agent never stages or commits in this mode.
3. Ask for a pull-request title and description — on request
When the branch is ready to open, ask for PR content explicitly:
> write a PR title and description for this branch
It detects the base branch (main/master), reads the branch's commits and its diff against that base, and writes a complete PR as plain Markdown: a strong title and a description with a summary, what changed, testing, and any breaking changes — plus a reviewer/testing checklist where it helps. It verifies what it can from the history and diff, and by default you get the Markdown to paste, or a gh pr create … command. Ask it to open the PR — and to merge it once CI passes — and it does both itself, with no bypass of a failing check or of branch protection unless you ask for that too.
4. Ask it to stage, commit, and push — explicit autonomous mode
Use unambiguous wording when you want the agent to perform the operations itself:
> stage, commit, and push this for me — do it all yourself
The agent inspects the staged and unstaged hunks, selects one coherent change, stages only its specific paths, verifies the staged diff, commits with the quoted-heredoc form, and pushes the current branch to its upstream. It never uses git add -A and it never force-pushes. It never passes --no-verify either: a hook that fails is a finding it reports, not an obstacle it removes. It treats work in the repository it did not create as yours — it inspects that work, never sweeps it into a commit, and never rewrites it.
Six conditions stop it: a rejected push, an ambiguous remote or upstream, staged work that will not group into one commit, a tag or release that already exists, a hook that fails, and a pull request whose checks fail or that cannot merge. A rejected push means someone else moved the branch. The agent fetches, reads the divergence, and reports the exact commits on each side. It never rebases or merges that divergence for you.
Every stop hands the work back with the same five things. The goal, and the exact blocked step. What it attempted, and the git output, verbatim. The causes it eliminated, and how. The one decision it needs from you. The state that remains, and whether it is safe to leave.
It claims completion only from git log -1 --format=full and git status. It runs both after the push, and it shows you the output. A claim without that output is not a completion.
On a further explicit ask, mode 4 will also tag and publish a GitHub release. It checks that gh is installed and authenticated first, and falls back to handing you the note as Markdown if either check fails. It never overwrites or moves an existing tag or release, never uses --force, and never deletes either — if the version is already tagged or released, it stops and tells you.
Mode 4 is an exception to the read-only rule and to nothing else. In particular it adds no attribution of its own — see Attribution and trailers.
The autonomous mode is never inferred. Asking for a message or commands, saying "commit this," or approving commands with "go ahead" keeps the interaction read-only. Ask the agent explicitly to stage, commit, and push when you intend mode 4.
5. Ask for the release note for a version — on request
When you're cutting a release, ask for the note:
> write the release notes for 2.3.0
It fetches tags, works out the range from the last version tag reachable from HEAD, reads the actual diff over that range — not just the commit subjects — and returns the note as a Markdown block you can paste:
# v2.3.0
Minor release. Adds a fifth mode: the skill now writes the release note for a
version from what actually landed since the last release.
## What changed
**Release notes are grounded in the range, not the subjects.** The note is built
from `git diff <last-tag>..HEAD`, so a commit whose message understated what it
shipped doesn't understate it twice.
## Upgrade notes
Drop-in replacement for 2.2.0. The four existing modes are unchanged.
It matches your project's own release style — tag prefix, title shape, headings, section order — over any built-in template, and says so when the two differ. Sections with nothing real in them are dropped rather than filled with "None".
Two things it won't do. If the repository has no versioning at all — no version tags, no version field, no releases — it says so and stops rather than creating your first tag and silently deciding your scheme for you. And if the last tag disagrees with the version field in your project, it reports the discrepancy and tells you which one it used as the range base instead of quietly picking one.
Publishing is separate: the note lands in the conversation, and writing it to a file or cutting the actual GitHub release each take their own explicit ask (the latter via mode 4).
6. Ask it to review an incoming pull request — on request
This one is for the other side of the table: you're the maintainer, and someone else's branch is waiting on you.
> review PR 412 with me
It reads the PR through gh — the diff, the CI checks, the existing review threads, the linked issue, the commits and their authors, and your repo's merge method — then tells you what the branch does and, more usefully, sorts what it found into two buckets. Blocking means merging leaves you worse off than not merging: a broken build or test, data loss, a security hole, a broken contract, or a change that doesn't do what the PR says. Everything else is a suggestion, and a suggestion is never on its own a reason to hold up a merge.
That distinction is calibrated to your project. A small repo with no stated convention and no CI has a high bar for blocking — missing tests in a project with no test suite isn't a blocker, and neither is ignoring a rule you never wrote down. It won't manufacture an objection to make the review look thorough, and when nothing blocks, that's the first line you read.
Then you decide, and it writes exactly one Markdown block for the decision you made:
- Something blocks it — a review comment, verdict first, blocking items separated from optional ones, pointing at code and locations rather than at the contributor.
- You're accepting — the merge-commit message. On a squash merge this matters more than it looks: GitHub prefills the body with every branch commit concatenated together, and that's the commit that lands on your default branch and lives in
git logforever. It gets written fresh from the diff instead, andCo-authored-by:lines are carried across from the branch's real commits so a squash doesn't erase a second contributor's credit.
By default you paste it into GitHub and click the button. Say "approve it", "request changes", "post the comment", or "merge it", and the agent carries out that action itself; it merges only while the required checks pass. A bare "go ahead" names no action, so it asks which one you mean.
7. Ask it about the repository itself — on request
Anything git does that isn't a message: branches, integration, history editing, undo, moving work, conflicts, recovery.
> this rebase is stuck and I don't know which side is mine
> squash these four commits before I open the PR
> I reset --hard and lost an hour of work
It reads the real state first — status, graph, branches, and the divergence from the upstream when a remote matters — tells you what git is actually reporting, and then gives you the commands. Before anything that can lose work it names the reflog entry or branch that gets it back.
The limits are absolute. It won't rewrite published history on a shared branch. It won't force-push — where you ask it to update your own pushed branch after a rebase it uses --force-with-lease, which refuses if the remote moved since your last fetch, so someone else's commit can't be silently overwritten. It won't discard uncommitted work without you confirming. It won't resolve a conflict by picking a side to make the sequence continue — it reads both sides, decides from what each change was for, and tells you what it decided and why. And it never leaves a rebase, merge, cherry-pick, or bisect half-finished without telling you the state and the command that ends it.
One thing worth knowing, because it's the most common way conflict work goes wrong: ours and theirs swap between a merge and a rebase. In a rebase your own commit arrives as "theirs". The skill reads which operation is in progress rather than assuming.
Like modes 1–3, 5, and 6, this is read-only by default — you get the commands and run them. It executes only under the same explicit autonomous request mode 4 needs.
The same conventions apply in Codex, Cursor, and Gemini. Codex and Cursor read this as a skill, just like Claude; Gemini reads GEMINI.md. Once the files are in place, ask for a commit command, a release note, or explicitly request the autonomous workflow — the same mode boundary applies everywhere.
Attribution and trailers
The default is no attribution trailers at all. No Co-authored-by:, no Signed-off-by:, no Reviewed-by:, and no AI or agent identity of any kind — not in commit messages, not in pull-request descriptions. A commit reads as your own work, authored by whatever git config user.name / user.email resolves to.
The reason is that a trailer is an assertion: that a particular person collaborated on the change, or reviewed it, or is certifying its origin under a DCO. That claim belongs to you, not to a tool guessing on your behalf. A wrong one is worse than none — it puts a name in permanent history that doesn't belong there.
This applies to mode 4 too. There is no autonomous-mode exception. Asking the agent to stage, commit, and push is a request to do the work, not a request to be credited for it, so an autonomous commit carries exactly the same trailers a mode-1 commit would.
One exception, and only one. When you squash-merge someone's pull request in mode 6, Co-authored-by: lines are carried across from the branch's real commits without you asking. A squash collapses every commit into one and credits only the PR author, so transcribing them preserves authorship that already exists rather than asserting anything new — every name and address comes from an actual commit.
Never inferred, and the sources are named. A trailer has exactly two legitimate sources: your words in the session, and the squash transcription above. Everything else is forbidden by name — the agent's own identity, the model or tool name, commit.template, a prepare-commit-msg or commit-msg hook, GIT_AUTHOR_* and GIT_COMMITTER_*, CI variables, editor plugins, and the trailers on your existing commits. A repository whose every commit carries Signed-off-by still gets no sign-off. A template or hook that injects a line is treated as a finding: the line is stripped and you're told which file produced it. The author identity is never set either — no --author, no -c user.name, no writes to git config.
And it's checked, not just stated. After every commit the agent makes itself it runs git log -1 --format=%B | grep -n -i -E '^(co-authored-by|signed-off-by|reviewed-by|generated[- ]with|generated by)|claude|anthropic|copilot|openai|gemini|codex|cursor'. The command must print nothing; if it prints an unrequested line the agent amends it out at once and runs the check again. The same grep runs across every commit a push would publish, and a hit stops the push. A commit isn't reported as done until the check passes.
Still included by default, because neither is attribution:
BREAKING CHANGE:— required by the Conventional Commits grammar.- Issue references (
Refs: #123,Closes #123) when you supply the issue, or when it's unambiguous from the branch name. It never guesses an issue number.
Asking for a trailer on one commit
Say so in the session, in whatever words are natural:
> write the commit message and sign it off
> commit this and add Sara Ahmadi <sara@example.com> as co-author
> credit the agent on this one
You get the same message with the trailer block filled in:
git commit -F - <<'COMMIT_MSG'
fix(serializers): handle null profile in user payload
Co-authored-by: Sara Ahmadi <sara@example.com>
Closes #517
COMMIT_MSG
The request applies to that session's work, not to the repository — the next session starts from the default again.
Turning the harness default off
Claude Code adds Co-authored-by: Claude <noreply@anthropic.com> to every commit and Generated with Claude Code to every pull request by default. That is a harness setting, and this skill treats it as a forbidden source: the check above strips the line whenever the setting is still on. Turn the default off once, in ~/.claude/settings.json for every project or in .claude/settings.json for one project:
{
"attribution": {
"commit": "",
"pr": ""
}
}
Older releases read the boolean includeCoAuthoredBy; set it to false there. Codex, Cursor, and Gemini CLI carry their own equivalents, and the same rule applies: the skill honours your words in the session, never the tool's default.
Making it persistent
For a standing preference, put it in the consuming repository's own agent context file — AGENTS.md, CLAUDE.md, or whatever your agent reads. The skill honours an instruction it finds there. One line is enough:
Sign off every commit with `Signed-off-by:` using my git user.name and user.email.
That's the whole mechanism: an explicit ask in the session, or a standing line in your own context file. There is no config file and no flag to set.
Supported on request
Co-authored-by:Signed-off-by:Reviewed-by:(and the neighbouringAcked-by:/Tested-by:,Reported-by:/Suggested-by:/Helped-by:)- Issue-reference footers
- AI or agent attribution, in whatever form you ask for
Layout
git-authoring/
├── SKILL.md # skill: commit, PR, release, and review authoring
├── SELF-IMPROVEMENT.md # self-improvement rules
├── AGENTS.md # always-on layer; source for the pointers below
├── GEMINI.md # Gemini CLI
├── references/
│ ├── conventional-commits.md # full grammar, types, trailers
│ ├── examples.md # worked commits, incl. splits and staging
│ ├── craft.md # writing subjects and bodies well
│ ├── scopes-and-repos.md # scopes; matching a repo's style
│ ├── pull-requests.md # PR titles and descriptions
│ ├── release-notes.md # release notes; tagging and publishing
│ ├── pr-review.md # reviewing and landing incoming PRs
│ ├── branching-and-history.md # branches, rebase, undo, recovery
│ └── conflicts.md # merge/rebase conflict resolution
├── README.md
└── LICENSE
Claude, Codex, and Cursor load SKILL.md and pull in the reference files only when a change calls for them; GEMINI.md and AGENTS.md carry the same guidance for agents that read a single always-on file.
License
MIT. See LICENSE.