File contents Commit Changes
Validates changes, stages all new and modified files, generates a conventional commit message, creates a GPG-signed commit, and pushes to origin.
Usage
/bkff:git-commit [--message "custom message"] [--co-author "Name <email>"]
Options
Option
Description
--message
Override the auto-generated commit message
--co-author
Add a co-author to the commit
What It Does
Validates changes using build tool (make lint, npm run lint, etc.)
Halts if validation fails with error details
Stages all changes (git add -A)
Analyzes changes to generate conventional commit type and scope
Creates a GPG-signed commit
Pushes to origin
Conventional Commit Types
Change Pattern
Generated Type
New files in src/
feat
Bug fixes, modifications
fix
Refactoring
refactor
Test file changes only
test
Documentation changes
docs
Build/config changes
build
Example Output
## Commit Created
### Validation
- ✓ Build tool validation passed
### Changes Committed
- **Files**: 3 files changed
- M src/auth.ts
- A src/utils.ts
- M README.md
### Commit
- **Hash**: abc1234
- **Message**: feat(auth): implement login functionality
- **Signed**: Yes
### Push
- **Status**: Success
Requirements
Must be run inside a git worktree
git CLI for commit and push
GPG configured for commit signing
Build tool with validate/lint target (optional)
Error Cases
No changes : "Nothing to commit"
Validation failed : Shows lint/test errors
GPG unavailable : Error with configuration instructions
Push failed : Commit preserved locally, retry instructions
Implementation
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
source "$PLUGIN_DIR/lib/common.sh"
source "$PLUGIN_DIR/lib/git-helpers.sh"
source "$PLUGIN_DIR/lib/validation.sh"
# Parse arguments
CUSTOM_MESSAGE=""
CO_AUTHOR=""
while [[ $# -gt 0 ]]; do
case "$1" in
--message|-m)
CUSTOM_MESSAGE="$2"
shift 2
;;
--co-author)
CO_AUTHOR="$2"
shift 2
;;
*)
shift
;;
esac
done
require_worktree
# Check for changes
if ! has_changes; then
info "Nothing to commit. Working directory is clean."
exit 0
fi
echo "## Commit Process"
echo ""
# FR-012, FR-013: Run validation
echo "### Validation"
if has_validate_target; then
if run_validation; then
echo "- ✓ Build tool validation passed"
else
echo "- ✗ Build tool validation failed"
echo ""
error_exit "Fix validation errors before committing."
fi
else
echo "- ⊘ No validation target found (skipped)"
fi
echo ""
# FR-016: Check GPG signing availability
if ! has_signing_available; then
error_exit "GPG signing required but unavailable. Configure GPG key first:\n git config --global user.signingkey <KEY_ID>\n git config --global commit.gpgsign true"
fi
# FR-014: Stage all changes
info "Staging all changes..."
git add -A
# Get list of staged files for display and analysis
STAGED_FILES=$(git diff --cached --name-status)
STAGED_COUNT=$(echo "$STAGED_FILES" | grep -c '^' || echo "0")
echo "### Changes to Commit"
echo "- **Files**: $STAGED_COUNT files"
echo "$STAGED_FILES" | while IFS=$'\t' read -r status file; do
printf " - %s %s\n" "$status" "$file"
done
echo ""
# FR-015: Generate conventional commit message
generate_commit_type() {
local files="$1"
# Check for new files (feat)
if echo "$files" | grep -q '^A'; then
# New source files = feat
if echo "$files" | grep -qE '^A.*\.(ts|js|py|go|rs|java|sh)$'; then
echo "feat"
return
fi
fi
# Check for test files only
if echo "$files" | grep -qE 'test|spec' && ! echo "$files" | grep -vqE 'test|spec'; then
echo "test"
return
fi
# Check for docs only
if echo "$files" | grep -qE '\.(md|txt|rst)$' && ! echo "$files" | grep -vqE '\.(md|txt|rst)$'; then
echo "docs"
return
fi
# Check for build/config files
if echo "$files" | grep -qE '(Makefile|package\.json|Cargo\.toml|\.yml|\.yaml)'; then
echo "build"
return
fi
# Default to fix for modifications
echo "fix"
}
generate_scope() {
local files="$1"
# Extract common directory from changed files
local first_dir
first_dir=$(echo "$files" | head -1 | awk -F'\t' '{print $2}' | cut -d'/' -f1)
# If it's a known directory, use it as scope
case "$first_dir" in
src|lib|pkg|cmd|internal)
# Get the next level directory as scope
local scope
scope=$(echo "$files" | head -1 | awk -F'\t' '{print $2}' | cut -d'/' -f2)
if [[ -n "$scope" && "$scope" != *.* ]]; then
echo "$scope"
return
fi
;;
skills|plugins|commands)
echo "$first_dir"
return
;;
esac
echo ""
}
generate_description() {
local commit_type="$1"
local files="$2"
# Get the first changed file for context
local first_file
first_file=$(echo "$files" | head -1 | awk -F'\t' '{print $2}' | xargs basename 2>/dev/null || echo "files")
first_file="${first_file%.*}" # Remove extension
case "$commit_type" in
feat) echo "add ${first_file} functionality" ;;
fix) echo "update ${first_file}" ;;
docs) echo "update documentation" ;;
test) echo "update tests" ;;
build) echo "update build configuration" ;;
*) echo "update ${first_file}" ;;
esac
}
if [[ -n "$CUSTOM_MESSAGE" ]]; then
COMMIT_MSG="$CUSTOM_MESSAGE"
else
COMMIT_TYPE=$(generate_commit_type "$STAGED_FILES")
COMMIT_SCOPE=$(generate_scope "$STAGED_FILES")
COMMIT_DESC=$(generate_description "$COMMIT_TYPE" "$STAGED_FILES")
if [[ -n "$COMMIT_SCOPE" ]]; then
COMMIT_MSG="${COMMIT_TYPE}(${COMMIT_SCOPE}): ${COMMIT_DESC}"
else
COMMIT_MSG="${COMMIT_TYPE}: ${COMMIT_DESC}"
fi
fi
# Add co-author if specified
if [[ -n "$CO_AUTHOR" ]]; then
COMMIT_MSG="${COMMIT_MSG}
Co-authored-by: ${CO_AUTHOR}"
fi
# FR-016: Create signed commit
info "Creating signed commit..."
if git commit -S -m "$COMMIT_MSG"; then
COMMIT_HASH=$(git rev-parse --short HEAD)
success "Commit created: $COMMIT_HASH"
else
error_exit "Failed to create commit"
fi
echo ""
echo "### Commit"
echo "- **Hash**: $COMMIT_HASH"
echo "- **Message**: $(echo "$COMMIT_MSG" | head -1)"
echo "- **Signed**: Yes"
[[ -n "$CO_AUTHOR" ]] && echo "- **Co-Author**: $CO_AUTHOR"
echo ""
# FR-017: Push to origin
echo "### Push"
info "Pushing to origin..."
if git push; then
echo "- **Status**: Success"
echo ""
success "Commit pushed to origin."
else
warn "Push failed (commit preserved locally)"
echo "- **Status**: Failed"
echo ""
echo "Run 'git push' to retry."
fi
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1 --- 2 name: git-commit-39 3 description: Add co-author attribution (format "Name <email>") Use when this capability is needed. 4 --- 5 6 # Commit Changes 7 8 Validates changes, stages all new and modified files, generates a conventional commit message, creates a GPG-signed commit, and pushes to origin. 9 10 ## Usage 11 12 ``` 13 /bkff:git-commit [--message "custom message"] [--co-author "Name <email>"] 14 ``` 15 16 ## Options 17 18 | Option | Description | 19 |--------|-------------| 20 | `--message` | Override the auto-generated commit message | 21 | `--co-author` | Add a co-author to the commit | 22 23 ## What It Does 24 25 1. Validates changes using build tool (make lint, npm run lint, etc.) 26 2. Halts if validation fails with error details 27 3. Stages all changes (`git add -A`) 28 4. Analyzes changes to generate conventional commit type and scope 29 5. Creates a GPG-signed commit 30 6. Pushes to origin 31 32 ## Conventional Commit Types 33 34 | Change Pattern | Generated Type | 35 |----------------|----------------| 36 | New files in `src/` | `feat` | 37 | Bug fixes, modifications | `fix` | 38 | Refactoring | `refactor` | 39 | Test file changes only | `test` | 40 | Documentation changes | `docs` | 41 | Build/config changes | `build` | 42 43 ## Example Output 44 45 ``` 46 ## Commit Created 47 48 ### Validation 49 - ✓ Build tool validation passed 50 51 ### Changes Committed 52 - **Files**: 3 files changed 53 - M src/auth.ts 54 - A src/utils.ts 55 - M README.md 56 57 ### Commit 58 - **Hash**: abc1234 59 - **Message**: feat(auth): implement login functionality 60 - **Signed**: Yes 61 62 ### Push 63 - **Status**: Success 64 ``` 65 66 ## Requirements 67 68 - Must be run inside a git worktree 69 - `git` CLI for commit and push 70 - GPG configured for commit signing 71 - Build tool with validate/lint target (optional) 72 73 ## Error Cases 74 75 - **No changes**: "Nothing to commit" 76 - **Validation failed**: Shows lint/test errors 77 - **GPG unavailable**: Error with configuration instructions 78 - **Push failed**: Commit preserved locally, retry instructions 79 80 ## Implementation 81 82 ```bash 83 #!/usr/bin/env bash 84 set -euo pipefail 85 86 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 87 PLUGIN_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")" 88 source "$PLUGIN_DIR/lib/common.sh" 89 source "$PLUGIN_DIR/lib/git-helpers.sh" 90 source "$PLUGIN_DIR/lib/validation.sh" 91 92 # Parse arguments 93 CUSTOM_MESSAGE="" 94 CO_AUTHOR="" 95 while [[ $# -gt 0 ]]; do 96 case "$1" in 97 --message|-m) 98 CUSTOM_MESSAGE="$2" 99 shift 2 100 ;; 101 --co-author) 102 CO_AUTHOR="$2" 103 shift 2 104 ;; 105 *) 106 shift 107 ;; 108 esac 109 done 110 111 require_worktree 112 113 # Check for changes 114 if ! has_changes; then 115 info "Nothing to commit. Working directory is clean." 116 exit 0 117 fi 118 119 echo "## Commit Process" 120 echo "" 121 122 # FR-012, FR-013: Run validation 123 echo "### Validation" 124 if has_validate_target; then 125 if run_validation; then 126 echo "- ✓ Build tool validation passed" 127 else 128 echo "- ✗ Build tool validation failed" 129 echo "" 130 error_exit "Fix validation errors before committing." 131 fi 132 else 133 echo "- ⊘ No validation target found (skipped)" 134 fi 135 echo "" 136 137 # FR-016: Check GPG signing availability 138 if ! has_signing_available; then 139 error_exit "GPG signing required but unavailable. Configure GPG key first:\n git config --global user.signingkey <KEY_ID>\n git config --global commit.gpgsign true" 140 fi 141 142 # FR-014: Stage all changes 143 info "Staging all changes..." 144 git add -A 145 146 # Get list of staged files for display and analysis 147 STAGED_FILES=$(git diff --cached --name-status) 148 STAGED_COUNT=$(echo "$STAGED_FILES" | grep -c '^' || echo "0") 149 150 echo "### Changes to Commit" 151 echo "- **Files**: $STAGED_COUNT files" 152 echo "$STAGED_FILES" | while IFS=$'\t' read -r status file; do 153 printf " - %s %s\n" "$status" "$file" 154 done 155 echo "" 156 157 # FR-015: Generate conventional commit message 158 generate_commit_type() { 159 local files="$1" 160 161 # Check for new files (feat) 162 if echo "$files" | grep -q '^A'; then 163 # New source files = feat 164 if echo "$files" | grep -qE '^A.*\.(ts|js|py|go|rs|java|sh)$'; then 165 echo "feat" 166 return 167 fi 168 fi 169 170 # Check for test files only 171 if echo "$files" | grep -qE 'test|spec' && ! echo "$files" | grep -vqE 'test|spec'; then 172 echo "test" 173 return 174 fi 175 176 # Check for docs only 177 if echo "$files" | grep -qE '\.(md|txt|rst)$' && ! echo "$files" | grep -vqE '\.(md|txt|rst)$'; then 178 echo "docs" 179 return 180 fi 181 182 # Check for build/config files 183 if echo "$files" | grep -qE '(Makefile|package\.json|Cargo\.toml|\.yml|\.yaml)'; then 184 echo "build" 185 return 186 fi 187 188 # Default to fix for modifications 189 echo "fix" 190 } 191 192 generate_scope() { 193 local files="$1" 194 195 # Extract common directory from changed files 196 local first_dir 197 first_dir=$(echo "$files" | head -1 | awk -F'\t' '{print $2}' | cut -d'/' -f1) 198 199 # If it's a known directory, use it as scope 200 case "$first_dir" in 201 src|lib|pkg|cmd|internal) 202 # Get the next level directory as scope 203 local scope 204 scope=$(echo "$files" | head -1 | awk -F'\t' '{print $2}' | cut -d'/' -f2) 205 if [[ -n "$scope" && "$scope" != *.* ]]; then 206 echo "$scope" 207 return 208 fi 209 ;; 210 skills|plugins|commands) 211 echo "$first_dir" 212 return 213 ;; 214 esac 215 216 echo "" 217 } 218 219 generate_description() { 220 local commit_type="$1" 221 local files="$2" 222 223 # Get the first changed file for context 224 local first_file 225 first_file=$(echo "$files" | head -1 | awk -F'\t' '{print $2}' | xargs basename 2>/dev/null || echo "files") 226 first_file="${first_file%.*}" # Remove extension 227 228 case "$commit_type" in 229 feat) echo "add ${first_file} functionality" ;; 230 fix) echo "update ${first_file}" ;; 231 docs) echo "update documentation" ;; 232 test) echo "update tests" ;; 233 build) echo "update build configuration" ;; 234 *) echo "update ${first_file}" ;; 235 esac 236 } 237 238 if [[ -n "$CUSTOM_MESSAGE" ]]; then 239 COMMIT_MSG="$CUSTOM_MESSAGE" 240 else 241 COMMIT_TYPE=$(generate_commit_type "$STAGED_FILES") 242 COMMIT_SCOPE=$(generate_scope "$STAGED_FILES") 243 COMMIT_DESC=$(generate_description "$COMMIT_TYPE" "$STAGED_FILES") 244 245 if [[ -n "$COMMIT_SCOPE" ]]; then 246 COMMIT_MSG="${COMMIT_TYPE}(${COMMIT_SCOPE}): ${COMMIT_DESC}" 247 else 248 COMMIT_MSG="${COMMIT_TYPE}: ${COMMIT_DESC}" 249 fi 250 fi 251 252 # Add co-author if specified 253 if [[ -n "$CO_AUTHOR" ]]; then 254 COMMIT_MSG="${COMMIT_MSG} 255 256 Co-authored-by: ${CO_AUTHOR}" 257 fi 258 259 # FR-016: Create signed commit 260 info "Creating signed commit..." 261 if git commit -S -m "$COMMIT_MSG"; then 262 COMMIT_HASH=$(git rev-parse --short HEAD) 263 success "Commit created: $COMMIT_HASH" 264 else 265 error_exit "Failed to create commit" 266 fi 267 268 echo "" 269 echo "### Commit" 270 echo "- **Hash**: $COMMIT_HASH" 271 echo "- **Message**: $(echo "$COMMIT_MSG" | head -1)" 272 echo "- **Signed**: Yes" 273 [[ -n "$CO_AUTHOR" ]] && echo "- **Co-Author**: $CO_AUTHOR" 274 echo "" 275 276 # FR-017: Push to origin 277 echo "### Push" 278 info "Pushing to origin..." 279 if git push; then 280 echo "- **Status**: Success" 281 echo "" 282 success "Commit pushed to origin." 283 else 284 warn "Push failed (commit preserved locally)" 285 echo "- **Status**: Failed" 286 echo "" 287 echo "Run 'git push' to retry." 288 fi 289 ``` 290 291 --- 292 > Converted and distributed by [TomeVault](https://tomevault.io/claim/kbrockhoff) — claim your Tome and manage your conversions. 293 <!-- tomevault:4.0:skill_md:2026-04-14 -->
tomevault-io/skills-registry/tree/main/kbrockhoff--brockhoff-tools-claude--git-commit commit 4242ab2ea3
Frequently asked questions How do I install the Git Commit skill? Run npx skillmds@latest add tomevault-io/git-commit-39 in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
What does the Git Commit skill do? Add co-author attribution (format "Name <email>") Use when this capability is needed. It is listed under Productivity on SkillMD.
Is Git Commit safe to use? This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
Which AI agents work with Git Commit? This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Is Git Commit free to use? Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
Who published Git Commit? tomevault-io (@tomevault-io) published this skill. Their other Agent Skills are listed on their SkillMD profile.