| name | commit |
| description | Create or amend a local Git commit from the relevant changes. Use only when the user asks to commit, amend, or complete a requested Git action such as push that first requires a commit. Stage only in-scope files and write a repository-matching message. Not for message drafts or branch creation. |
| argument-hint | [additional context] |
| context | fork |
| allowed-tools | ["Bash(git:*)","Bash(cat .git/hooks/pre-commit)","Bash(rg:*)","Bash(fd:*)","Bash(jq:*)","Read"] |
Create one git commit for: $ARGUMENTS. With empty arguments, commit the work from the current conversation.
Contract
- Commit only after an explicit user request.
- Do not push, reset, checkout, rebase, or rewrite history unless the user explicitly asked for that operation.
- Recover motivation from the current conversation, linked issue or plan, project docs, current diff, and targeted agent transcript search when the user wants one commit for work spread across prior conversations or agents.
- Do not read shell history. Treat transcripts as secret surfaces: search them narrowly, do not dump raw snippets into chat, and extract only the motivation needed for the commit message.
- Screen changed paths before reading bodies, then classify them by exposure risk rather than name alone:
- Raw secret surfaces include real
.env* files, private keys, credential stores or dumps, shell history, and logs that may contain secrets. Stop without reading or staging them.
- Opaque ciphertext is established by repository instructions or an encryption marker, not by extension alone. Keep its body out of diffs, but allow metadata inspection and Git stage, commit, rename, or delete operations. Use project or user-supplied change classification as motivation, never infer plaintext, and keep ciphertext-only messages generic.
- Ambiguous paths include names that suggest secrets without proving plaintext or ciphertext, PEM bundles, unknown SSH material, and source or fixture names containing
credential, secret, or token. Report only the caution count and ask for one explicit classification before reading or staging them. Public certificates, public keys, authorized_keys, known_hosts, and SSH client configuration are not secret by type.
Explain why, not what
The diff shows what changed. The message captures what the diff cannot: motivation, trade-offs, why this approach beat alternatives, and non-obvious consequences for future readers. Lead with the reason the change exists, end with the chosen approach. The body should read as a self-contained story that doubles as the PR description without rewriting. A body that inventories changes (add X, update Y, remove Z) without naming motivation has zero value.
Wrong: chore: update package manager path with body Move the package manager home to the new directory.
Right: chore: keep package binaries and store on one volume with body explaining that cross-volume installs recreated the store, and colocating the binary directory, global installs, and store removes that mismatch without extra configuration.
Message Rules
- Build the message from an evidence ledger:
diff: a staged hunk or committed doc proves the changed artifact, behavior, policy, path, config key, tool, spec, or external integration.
motivation: the conversation, issue, plan, or transcript explains why a staged change exists.
report: uncommitted local config, operator workflow, skipped tools, environment state, or rejected alternatives.
- For opaque ciphertext,
diff evidence proves only path, status, and encrypted format. Derive no plaintext claim from it; use the ordinary changed files for behavior evidence and the user's classification only for motivation.
- Use
diff evidence for the subject, approach, and every named path, tool, config key, policy, service, spec, external behavior, and changed behavior. Use motivation evidence only for why the staged change exists. Move report evidence to the post-commit report.
- Bug fixes name the root cause. Features name the user-visible gap. Refactors name the constraint that forced the restructure.
- Anchor every body bullet to ledger entries. Rewrite or remove sentences whose source is missing or whose source category is
report.
- Use concrete verbs:
reject empty subscriber list, validate write access before subscribing, reduce p99 from 200ms to 50ms.
- Replace vague verbs with the exact behavior, metric, bound, invariant, or threat model that changed. Avoid
tighten, streamline, enhance, refine, polish, bare optimize, and bare harden.
- Use backticks for code references. Reference related commits by short hash only when the new commit depends on them.
Format precedence:
- Dialect, tense, and subject case come from
git log --oneline -10.
- Type (
feat, fix, chore, refactor) comes from the intent of this change.
- Scope comes only from declarative config:
commitlint, commitizen, or a Scopes section in CONTRIBUTING.md. If no config pins scopes, omit scope even when recent commits use one.
Format:
- Subject is 50 characters or fewer, imperative present tense, and has no trailing period.
- Body wraps at 72 characters, after one blank line below the subject.
- Do not refer to "this PR" or "this commit" inside the body.
- Do not quote the new commit's own hash.
Process
- Gather context in one read-only batch:
git diff -z --name-only HEAD
git ls-files -z --others --exclude-standard
git diff --cached -z --name-only
git diff -z --name-only
git branch --show-current
git log --oneline -10
cat .git/hooks/pre-commit if present
- Classify every changed path under the Contract. Abort on raw secret surfaces. Record opaque ciphertext separately, exclude its body from every later diff, and continue with ordinary paths once every ambiguous path is classified.
- Decide ordinary commit mode unless the user explicitly asked to amend the previous git commit. In amend mode, read
git show --stat --patch HEAD and treat staged changes as the net replacement relative to HEAD^; ordinary commit mode must not use git commit --amend.
- Read
git diff HEAD for ordinary commit mode or the amend-mode net diff, limited to ordinary paths. Inspect opaque ciphertext through --name-status, --stat, or encryption markers only.
- If the log dialect is Conventional Commits, look for scope config with:
rg -l --no-ignore-vcs '"?commitlint"?|"?commitizen"?' -g '!node_modules' -g '!.git' .
fd CONTRIBUTING -d 3 .
- Record the pre-staged set from
git diff --cached -z --name-only. Before any git add, compute the intersection of planned commit paths with git diff -z --name-only; if a pre-staged planned file also has unstaged changes, abort with abort: partially staged path in commit scope and the count. Do not collapse staged and unstaged hunks with git add <path>.
- Stage only files that belong to the requested commit. If an unrelated staged file is already present, stop and report it instead of unstaging user work.
- Verify
git diff --staged --name-only matches every file named by the message.
- Search the current conversation, linked issue, plan, and project docs for motivation behind each staged change. For dotfile or config changes, check the tool's documentation or changelog for the reason the path, key, or default changed. If a search returns zero hits, verify the search syntax before concluding motivation is absent (
rg uses | for alternation, not \|; grep is the opposite).
- If motivation is still missing or the user indicates prior agent work, use the transcript recovery workflow below.
- Build an evidence ledger for the subject, lead paragraph, and each body bullet. Mark each entry as
diff, motivation, or report, and name the staged path, hunk, issue, plan, or transcript source.
- Draft the message from ledger-approved entries, applying the Message Rules source categories.
- Scan the draft message for banned vague verbs from Message Rules. Treat each match as a hard error.
- Commit with a single-quoted heredoc:
git commit -F - <<'COMMIT_MSG_END'
<message exactly as it should read in git log>
COMMIT_MSG_END
Single quotes on the terminator preserve backticks, $, \, !, and ".
In amend mode only, replace git commit with git commit --amend.
- After commit, run
git status --short.
Transcript Recovery
Use transcripts to recover motivation when the final commit spans multiple agents, directories, or conversations.
Search targets:
- Claude Code:
~/.claude/projects/**.jsonl and ~/.claude/projects/**/subagents/*.jsonl
- Codex:
~/.codex/sessions/**/*.jsonl
Workflow:
- Build search terms from changed file paths, branch names, issue IDs, function names, and user-provided context. Do not use broad terms such as
fix, update, or commit.
- Search in this order:
- Claude current-project slug under
~/.claude/projects
- Codex sessions mentioning the current repo absolute path, repo basename, active branch, or changed path
- Global transcript search only when the user indicates cross-agent or cross-directory work and at least two specific search terms are available
- List candidate transcript files with
rg -l --fixed-strings <term> <transcript-root>. Cap broad searches with date, project slug, or another term before reading.
- Prefer assistant summaries, final messages, plan text, and tool-call result summaries. Avoid raw command output, environment dumps, logs, process lists, auth output, and secret-like paths.
- For JSONL files, use
jq to extract bounded text fields instead of printing whole records. Keep only lines needed to identify motivation, accepted trade-offs, test results, or manual verification gaps.
- If the transcript evidence conflicts with the current diff, trust the current diff for what changed and use transcripts only for why the work happened.
- Route transcript-only facts about uncommitted local config, rejected alternatives, skipped tools, or operator workflow to the post-commit report.
- If no targeted evidence appears after one broad search plus one refinement, ask one specific motivation question rather than continuing to trawl transcripts.
Failure Modes
- Cross-check abort: first line is
abort: <reason>, followed by the exact mismatch.
- Raw-secret path abort: first line is
abort: raw secret path in commit scope, followed by the count only.
- Pre-commit hook failure: surface the hook output and stop.
- Do not bypass failures with
--no-verify.
Output
Return a labeled report:
- Commit: short hash and subject.
- Auto-staged: files this skill staged that were not pre-staged, or
none.
- Leftover: modified or untracked files still present, each with a one-line relevance note.