Commit
Create a single well-formed commit after assessing every visible changed file to determine whether it should actually be committed.
Autonomy Routing
A commit request is approval to triage, stage repository-appropriate files, compose a conventional commit message, and create the commit without turning the routine path into an approval loop. Ask only for unresolved REVIEW items, override scope, secrets handling, destructive cleanup, ignore-policy changes, or a message/scope decision that materially affects user intent. Reuse explicit file selections and valid human overrides; an ALLOWED label alone does not require a second confirmation. Do not ask whether to use another workflow wrapper unless the user is really requesting history cleanup, PR creation, or handoff.
Usage
/commit
/commit "message hint"
message hint is optional seed text for the commit message subject.
Workflow
Step 1 — Survey the working tree
git status --short
git stash list | head -3
Collect:
- Staged files (will appear in next commit as-is unless you unstage)
- Unstaged modifications to tracked files
- Untracked files
- Whether the branch has unpushed commits
Read repository policy before classifying: applicable AGENTS.md/CLAUDE.md,
.gitignore, contribution docs, tracked-file status, and recent history for
ambiguous generated or planning files. Repository policy outranks the generic
heuristics below unless it would expose a secret or violate an active safety
instruction.
Also check for a human-maintained override file:
cat .githooks/commit-allow 2>/dev/null
This file lists patterns that are explicitly permitted to be committed even though they would normally be ignored. It is maintained by humans only — agents must never write to it.
Step 2 — Triage every file
For every file visible in git status, assign one of four verdicts:
| Verdict | Meaning |
|---|---|
| COMMIT | Clearly part of the work; stage and commit |
| ALLOWED | Normally ignored, but explicitly permitted by .githooks/commit-allow |
| SKIP | Should never be in version control; do not stage |
| REVIEW | Ambiguous; present to user before deciding |
Check .githooks/commit-allow first. If a file matches a pattern in that
file, assign ALLOWED before applying any SKIP rule. ALLOWED always wins over
SKIP. Never assign ALLOWED based on your own judgement — only based on what
is written in the allow file by the human.
Default SKIP heuristics for untracked files
Apply these defaults when repository policy and history do not establish that a file belongs in version control. A tracked file modified by the requested work is normally COMMIT; do not untrack it merely because its name matches a generic pattern. Explicit repository policy and authorized file selections settle these generic heuristics. Only unresolved policy conflicts are REVIEW; do not silently SKIP a project-authoritative plan or source document.
Untracked planning / AI session artifacts
VISION.md,IMPLEMENTATION_PLAN.md,PROMPT.md,RALPH_PROMPT.md,NEXT_SHELL_PROMPT.mdIDEAS.md,DECISIONS_LOG.txt,RFC_INSTRUCTIONS.md,ISSUES_FOUND.mdPHASE_*_SUMMARY.md,PHASE_*_IMPLEMENTATION.md*VALIDATION*.md,*VALIDATION*.txt,UNDOCUMENTED_APIS*.md
Untracked agent runtime state
.yore/,.yore-test/,.yore-audit/.cultivar/,.claude/(session state only),.codex/,.agent/.ralph/,.haake/,.workmerge/,.worktrees/,.playwright-mcp/artifacts/,agent_reports/
Untracked build / cache / generated output
__pycache__/,*.pyc,*.pyo,.mypy_cache/,.ruff_cache/,.pytest_cache/target/(Rust),node_modules/,dist/,out/,.next/,.nuxt/*.egg-info/,.tox/,htmlcov/,coverage/,.nyc_output/*.tsbuildinfo,.eslintcache,.parcel-cache
Secrets / credentials
.env,.env.*(any variant),*.pem,*.key,*.p12,*.pfx- Files matching
*credentials*.json,*service_account*.json id_rsa,id_ed25519,id_ecdsa,*.keystore,*.secret
Note: Secrets must never receive ALLOWED verdict regardless of what is in the allow file. Flag them as SKIP and warn the user explicitly.
Untracked session-only .md files, absent project ownership evidence.
Ordinary source/reference documentation is COMMIT when selected by the task;
these familiar names are examples, not an exhaustive allow-list:
README.md, CHANGELOG.md, CHANGES.md, LICENSE.md, CONTRIBUTING.md,
SECURITY.md, CODE_OF_CONDUCT.md
Default COMMIT heuristics
- Source files:
.py,.rs,.ts,.js,.tsx,.jsx,.go,.hs,.sh,.bash,.css,.scss,.html,.sql - Project config that clearly belongs:
Cargo.toml,pyproject.toml,package.json,tsconfig.json,.gitignore,Makefile,*.yaml/*.tomlwhen they are project-owned config (not agent state) - Test files (
.test.ts,*_test.go,test_*.py,*_spec.rb, etc.)
REVIEW — ask the user
- Any
.mdfile not covered by the auto-skip, auto-commit, or ALLOWED rules - Lock files (
Cargo.lock,package-lock.json,yarn.lock,poetry.lock,go.sum) — confirm whether this repo commits them - Large generated files (>500 lines, clearly machine-written)
- New top-level files with an unusual extension
Step 3 — Present the assessment
Print a verdict table before touching the index:
File assessment:
COMMIT lib/staged-guard.sh (modified — new function)
COMMIT .githooks/pre-commit (modified — wired new check)
ALLOWED VISION.md (normally ignored — permitted by .githooks/commit-allow)
SKIP IMPLEMENTATION_PLAN.md (planning artifact — will not stage)
SKIP .claude/session.json (agent state — will not stage)
REVIEW Cargo.lock (lock file — commit in this repo?)
ALLOWED files must be shown distinctly — never buried in COMMIT. The user needs to see at a glance that an override is in play.
Never silently skip a SKIP file. Name every one so the user can override.
If a material REVIEW, secret-handling, cleanup or ignore-policy decision remains unresolved, present that exact choice before dependent staging. Do not ask again for already-authorized file selections or a valid human override.
If all staged files are ordinary COMMIT verdicts and all SKIP handling is unambiguous, continue without a second approval; the user's commit request is the approval.
Step 3b — Respect repository ignore policy
SKIP means "leave unstaged" for this invocation. It does not authorize changing
global Git configuration, writing ~/.config/git/ignore, editing .gitignore,
deleting files, or removing tracked files from the index. Never run
git rm --cached as commit housekeeping.
If ignored noise is recurring, report the exact paths and recommend a
repository-local policy change for separate approval. Only edit .gitignore
when the user explicitly requests that change and it belongs to this repository.
Never write .githooks/commit-allow; it is human-maintained.
Step 4 — Stage approved files
git add path/to/file1 path/to/file2 ...
Include both COMMIT and ALLOWED files. Never use git add . or git add -A
— always name explicit paths.
Step 5 — Read the diff and compose the commit message
git diff --cached --stat
git diff --cached
Compose a conventional commit message:
<type>(<scope>): <subject>
<body — optional, explain WHY not WHAT, wrap at 72 chars>
Types: feat · fix · chore · docs · refactor · test · style · ci · build
Rules:
- Subject ≤ 72 characters, imperative mood ("Add", not "Added" or "Adds")
- No trailing period on the subject line
- Scope = primary module, directory, or subsystem (omit if changes are repo-wide)
- If changes span multiple types, use the dominant one; list secondary changes in body
- Body only when the "why" is not obvious from the subject
- If any ALLOWED files are staged, note them in the body:
Permitted overrides: VISION.md (see .githooks/commit-allow) - If the user provided a message hint, incorporate it
Use the proposed message without asking for approval unless the user requested interactive review, supplied conflicting message guidance, or the correct subject/scope is materially ambiguous. Include the final message in the summary.
Step 6 — Commit
git commit -m "$(cat <<'EOF'
<type>(<scope>): <subject>
<body if needed>
EOF
)"
Step 7 — Confirm and summarise
git show --stat HEAD
Print:
✓ <short-sha>: <subject>
N files changed, X insertions(+), Y deletions(-)
If ALLOWED files were committed, call them out again here so the audit trail is visible even if the user wasn't watching:
⚠ Permitted overrides committed: VISION.md
Step 8 — If the user is really asking for history cleanup, switch skills
If the user asks to squash, tidy, compress, clean up, or rewrite commit
history, do not improvise with ad-hoc git rebase from this skill.
Use the /squash-commits skill instead.
History cleanup requires a different safety model: recording original HEAD, backup refs, rerere, per-pass health checks, and conflict abort policies. This skill is for staging and creating a commit from the current working tree, not for rewriting existing history.
Safety rules
- Never pass
--no-verify. If a hook fails, diagnose and fix — don't bypass. - Never amend a pushed commit without explicit user instruction.
- Never push unless the user explicitly asks after the commit is done.
- Never write to
.githooks/commit-allow— only humans maintain that file. - Never grant ALLOWED to secrets regardless of the allow file.
- Never casually rewrite history from this skill — route to
/squash-commits. - If
staged-guardfires during the commit hook, treat it as a signal: unstage the flagged file, re-examine it, and proceed only after resolution. - If after SKIP filtering there is nothing left to commit, report:
Nothing to commit after filtering artifacts. Working tree is clean or only artifacts remain. and stop.
- If you are unsure whether a file is an artifact, bias toward REVIEW, not COMMIT.
The .githooks/commit-allow file
This file is the human-controlled override mechanism. Format:
# Allow VISION.md to be committed — this project tracks vision in git
VISION.md
# Allow the phase summary for the current sprint
PHASE_3_SUMMARY.md
- One gitignore-style pattern per line
#comments supported- Agents read this file during triage but never write to it
- An agent that wants to commit a normally-ignored file must tell the human and ask them to add the pattern here first
- Secrets (
*.key,.env, etc.) are never honoured even if listed here