| name | commit |
| description | Create structured git commits by analyzing staged and unstaged changes and grouping them logically into one or more commits with clear, descriptive messages. Use when the user asks to commit, says "commit this" or "commit my changes", wants help writing a commit message, or has finished a chunk of work that needs committing. |
| argument-hint | [message] [--baseline <path>] |
| allowed-tools | Bash(git *), Bash(node *), Read, Glob, Grep |
| shell-timeout | 10 |
| contract | {"produces":{"kind":"side-effect","meta":{"effect":"git-commit"}},"consumes":{"meta":{"world":"dirty-tree"}}} |
Commit Changes
You are tasked with creating git commits for repository changes.
Input
$ARGUMENTS — optional commit message hint, optionally with --baseline <path> (a workflow's run-start snapshot of paths that were already dirty before the run began). Peel the --baseline flag first; the remainder (if any) is the message hint. Empty/literal → infer from history and git diff.
Metadata
node "${SKILL_DIR}/../_shared/git-changes.mjs"
echo "---recent-subjects---"
git log --pretty=%s -n 20 2>/dev/null || true
---recent-subjects--- — up to 20 most recent commit subject lines, used in Step 2 to match the repository's existing commit-message style. Empty on a no-HEAD initial repo.
When --baseline <path> was provided, the Metadata block above was rendered WITHOUT the baseline (render-time substitution cannot capture $ARGUMENTS — same reason code-review's scope helper is LLM-invoked). Before anything else, re-run the snapshot with the baseline threaded and use ITS output as the authoritative ---status--- / ---diffstat--- for the rest of this skill:
node "${SKILL_DIR}/../_shared/git-changes.mjs" --baseline <path>
---pre-existing (do NOT commit — dirty before this run)--- — present in that re-run's output when some listed files were already dirty before the run began. These are out of scope: they are not this run's work. Never git add a path in this section — a workflow commits only the changes it produced. The re-run's ---status--- block already excludes them; they are shown purely so you know they exist and must be left uncommitted.
Context:
- In-session: If there's conversation history, use it to understand what was built/changed
- Standalone: If no context available, rely entirely on git state and file inspection
Process:
-
Check git availability:
- If
in_repo: in the Metadata block is no, tell the user: "This directory is not a git repository. Run git init to initialize one." Stop — do not proceed.
-
Think about what changed:
- If in-session: Review the conversation history to understand what was accomplished.
- The Metadata block gives you the file list and per-file diffstat (insertions/deletions). For files with a small diffstat (≲5 lines), the line counts alone are enough to write the message — skip
git diff. Run git diff <path> only for files where the change is large or the intent isn't obvious from filename + line counts.
- For untracked directories shown in status (e.g.
?? path/), assume their contents are the change unless the directory has many files; do NOT cat/head files to verify obvious purpose.
- Consider whether changes should be one commit or multiple logical commits.
-
Plan your commit(s):
- Identify which files belong together
- Draft clear, descriptive commit messages
- Use imperative mood in commit messages
- Match the subject style observed in
---recent-subjects--- — same prefix convention (e.g. feat: / fix(scope): / docs: for Conventional Commits, gitmoji, bare sentence-case, ticket-prefixed, etc.), same length budget, same casing. If the sample is empty (initial repo) or mixed, default to imperative sentence-case with no prefix.
- Focus on why the changes were made, not just what
- Check for sensitive information (API keys, credentials) before committing
-
Present your plan to the user:
- List the files you plan to add for each commit
- Show the commit message(s) you'll use
- Use the
ask_user_question tool to confirm the commit plan. Question: "{N} commit(s) with {M} files. Proceed?". Header: "Commit". Options: "Commit (Recommended)" (Create the commit(s) as planned); "Adjust" (Change the grouping or commit messages); "Review files" (Show me the full diff before committing).
-
Execute upon confirmation:
- Use
git add with specific files (never use -A or .) — and stage only files from the ---status--- block. Any path under ---pre-existing (do NOT commit …)--- is out of scope: leave it dirty, never stage it.
- Create commits with your planned messages
- Show the result with
git log --oneline -n X (where X = number of commits you just created)
Important:
- NEVER add co-author information or Claude attribution
- Commits should be authored solely by the user
- Do not include any "Generated with Claude" messages
- Do not add "Co-Authored-By" lines
- Write commit messages as if the user wrote them
Remember:
- Adapt your approach: use conversation context if available, otherwise infer from git state
- In-session: you have full context of what was done; Standalone: infer from git analysis
- Group related changes by purpose (feature, fix, refactor, docs)
- Keep commits atomic: one logical change per commit
- Split into multiple commits if: different features, mixing bugs with features, or unrelated concerns
- The user trusts your judgment - they asked you to commit