# Git commit message generator for Claude Code # Generates a commit message file based on current changes without creating a commit # No signatures or automated text added # Generate commit message file based on staged and unstaged changes export def "commit-msg" [ --file (-f): string = "COMMIT_MSG.txt" # Output file for commit message --staged (-s): bool = false # Only consider staged changes --unstaged (-u): bool = false # Only consider unstaged changes --show: bool = false # Show changes without generating message ] -> nothing { if $show { show-git-changes return } # Determine what changes to analyze let analyze_staged = if $staged or (not $unstaged) { true } else { false } let analyze_unstaged = if $unstaged or (not $staged) { true } else { false } # Get git status let git_status = (git status --porcelain | lines | where { $in | str length > 0 }) if ($git_status | is-empty) { print "No changes to commit" return } # Analyze changes mut files_modified = [] mut files_added = [] mut files_deleted = [] for line in $git_status { let status_code = ($line | str substring 0..2) let file_path = ($line | str substring 3..) # Parse git status codes match $status_code { " M" => { if $analyze_unstaged { $files_modified = ($files_modified | append $file_path) } } "M " => { if $analyze_staged { $files_modified = ($files_modified | append $file_path) } } "MM" => { $files_modified = ($files_modified | append $file_path) } "A " => { if $analyze_staged { $files_added = ($files_added | append $file_path) } } "??" => { if $analyze_unstaged { $files_added = ($files_added | append $file_path) } } " D" => { if $analyze_unstaged { $files_deleted = ($files_deleted | append $file_path) } } "D " => { if $analyze_staged { $files_deleted = ($files_deleted | append $file_path) } } _ => {} } } # Analyze file types and changes let config_files = ($files_modified | where { $in | str ends-with ".toml" or $in | str ends-with ".nu" or $in | str ends-with ".yaml" }) let core_files = ($files_modified | where { $in | str contains "core/" }) let provider_files = ($files_modified | where { $in | str contains "provider" }) let migration_files = ($files_modified | where { $in | str contains "migration" }) # Generate commit message based on changes mut commit_type = "chore" mut commit_scope = "" mut commit_description = "" # Determine commit type and scope based on project patterns if (not ($files_added | is-empty)) { $commit_type = "feat" if ($files_added | any { $in | str contains "taskserv" }) { $commit_scope = "taskserv" $commit_description = "add new task service" } else if ($files_added | any { $in | str contains "provider" }) { $commit_scope = "provider" $commit_description = "add new provider" } else { $commit_description = "add new functionality" } } else if (not ($files_deleted | is-empty)) { $commit_type = "refactor" $commit_description = "remove unused components" } else if (not ($migration_files | is-empty)) { $commit_type = "refactor" $commit_scope = "config" $commit_description = "continue config-driven architecture migration" } else if (not ($config_files | is-empty)) { if ($config_files | any { $in | str contains "config.defaults.toml" }) { $commit_type = "feat" $commit_scope = "config" $commit_description = "enhance configuration system" } else { $commit_type = "config" $commit_description = "update configuration settings" } } else if (not ($core_files | is-empty)) { if ($core_files | any { $in | str contains "env.nu" }) { $commit_type = "refactor" $commit_scope = "env" $commit_description = "migrate from ENV to config-driven approach" } else { $commit_type = "refactor" $commit_scope = "core" $commit_description = "improve core functionality" } } else if (not ($provider_files | is-empty)) { $commit_type = "feat" $commit_scope = "providers" $commit_description = "enhance provider capabilities" } else { $commit_type = "chore" $commit_description = "update project files" } # Build commit message let commit_message = if ($commit_scope | is-empty) { $"($commit_type): ($commit_description)" } else { $"($commit_type)\(($commit_scope)\): ($commit_description)" } # Add details section for complex changes mut details = [] if ($files_modified | length) > 5 { $details = ($details | append $"- Update ($files_modified | length) files across multiple modules") } else if (not ($files_modified | is-empty)) { $details = ($details | append $"- Update: ($files_modified | str join ', ')") } if (not ($files_added | is-empty)) { $details = ($details | append $"- Add: ($files_added | str join ', ')") } if (not ($files_deleted | is-empty)) { $details = ($details | append $"- Remove: ($files_deleted | str join ', ')") } # Create full commit message let full_message = if ($details | is-empty) { $commit_message } else { $"($commit_message)\n\n($details | str join '\n')" } # Write to file $full_message | save $file print $"Commit message saved to: ($file)" print "\nGenerated message:" print "==================" print $full_message } # Show current git changes that would be included in commit message export def "show-git-changes" [] -> table { let status_output = (git status --porcelain | lines | where { $in | str length > 0 }) if ($status_output | is-empty) { print "No changes found" return [] } $status_output | each { |line| let status_code = ($line | str substring 0..2) let file_path = ($line | str substring 3..) let change_type = match $status_code { " M" => "Modified (unstaged)" "M " => "Modified (staged)" "MM" => "Modified (both)" "A " => "Added (staged)" "??" => "Untracked" " D" => "Deleted (unstaged)" "D " => "Deleted (staged)" _ => $status_code } { file: $file_path, status: $change_type, code: $status_code } } } # Quick commit message for common patterns export def "quick-commit" [ pattern: string # Pattern: config, fix, feat, refactor, docs, test ] -> nothing { let message = match $pattern { "config" => "config: update configuration settings" "fix" => "fix: resolve issue in functionality" "feat" => "feat: add new functionality" "refactor" => "refactor: improve code structure" "docs" => "docs: update documentation" "test" => "test: add or update tests" _ => $"chore: ($pattern)" } $message | save "COMMIT_MSG.txt" print $"Quick commit message saved: ($message)" }