aigcm 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1f0e2c18c6c1c820563cc9f640a319709b1cbb752fdee4464617759cd2e6f963
4
+ data.tar.gz: 3a74e5f33183449a690f5ae8892bd55d438cff57193eb90af1b358458f215c77
5
+ SHA512:
6
+ metadata.gz: e203e403e07b9865c879d6bee4cedb9545fc460a8cbaa990d9257e00e49a7bf735ac5ee4bd403f2e7dd1ad4ee399734e194d49e55c723d7f184684cee8c5a548
7
+ data.tar.gz: 22ff6406f1aba1ab8defeac098bc1dab5b0aece00c04801c3aa4b888399a23db974ed89b0387e373a5f05e77a0a99b7834c1da8ffb95c240f926429330d6b1ba
data/.envrc ADDED
@@ -0,0 +1,4 @@
1
+
2
+ export RR=`pwd`
3
+
4
+ PATH_add $RR/bin
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ ## [Unreleased]
4
+
5
+ ## [0.1.0] - 2025-02-08
6
+
7
+ - changed gem name to aigc
8
+
9
+ ## [0.1.0] - 2025-02-07
10
+
11
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Dewayne VanHoozer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # aigcm
2
+
3
+ The **AI git commit message** generator.
4
+ ƒ
5
+ ## Overview
6
+
7
+ **aigcm** is a Ruby gem designed to generate high-quality commit messages for git diffs. It leverages AI to analyze changes in your codebase and create concise, meaningful commit messages following best practices.
8
+
9
+ ## Features
10
+
11
+ - **Automatic Commit Message Generation**: Automatically generate commit messages based on code diffs.
12
+ - **Security-Aware Provider Selection**: Detects execution in a private repository and ensures non-local providers are not used for security reasons. This means that if you are working within a private repository, the gem will default to local providers unless explicitly forced otherwise.
13
+ - **Configurable Style Guide**: Allows using a specific style guide for commit messages, either from a default location or specified by the user.
14
+ - **AI Model Integration**: Integration with various AI models for enhanced message generation.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'aigcm'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ ```shell
27
+ bundle install
28
+ ```
29
+
30
+ Or install it yourself as:
31
+
32
+ ```shell
33
+ gem install aigcm
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ To generate a commit message:
39
+
40
+ ```shell
41
+ aigcm [options] [ref]
42
+ ```
43
+
44
+ ### Options
45
+
46
+ - `-a, --amend`: Amend the last commit.
47
+ - `-c, --context=CONTEXT`: Extra context beyond the diff.
48
+ - `-d, --dry`: Dry run the command without making any changes.
49
+ - `-m, --model=MODEL`: Specify the AI model to use.
50
+ - `--provider=PROVIDER`: Specify the provider (ollama, openai, anthropic, etc). Note: This only needs to be used when the specified model is available from multiple providers; otherwise, the owner of the model is used by default.
51
+ - `--force-external`: Force using external AI provider even for private repos.
52
+ - `-s, --style=STYLE`: Path to the style guide file. If not provided, the system looks for `COMMITS.md` in the repo root or uses the default style guide.
53
+ - `--default`: Print the default style guide and exit the application.
54
+ - `--version`: Show version.
55
+
56
+ ### Examples
57
+
58
+ If your commit involves refactoring a function to improve its performance, you might provide context like:
59
+ ```shell
60
+ aigcm -m MODEL -c "Refactored to improve performance by using algorithm X"
61
+ ```
62
+
63
+ This context helps the AI craft a more informative commit message.
64
+
65
+ When your commit is related to a specific JIRA ticket:
66
+ ```shell
67
+ aigcm -m MODEL -c "Resolved issues as per JIRA ticket JIRA-1234"
68
+ ```
69
+
70
+ Including the JIRA ticket helps relate the commit to external tracking systems.
71
+
72
+ Including multiple context strings:
73
+ ```shell
74
+ aigcm -m MODEL -c "Refactored for performance" -c "JIRA-1234"
75
+ ```
76
+
77
+ Multiple context strings can be added by repeating the `-c` option.
78
+
79
+ Using environment variables in context:
80
+ ```shell
81
+ aigcm -c "Put the work ticket as the first entry on the subject line" -c "Ticket: $TICKET"
82
+ ```
83
+
84
+ This allows you to dynamically include environment variables in your commit message.
85
+
86
+ ### Style Guide Example
87
+
88
+ The style guide is used as part of the generative AI prompt that instructs the large language model (LLM) how to craft its summary of the `git diff` results. The see the default style guide use the `--default` option.
89
+
90
+ You can create your own style guide named `COMMITS.md` in the root directory of your repository. You can also use the `--style` option to point `aigcm` to your style guide if you choose to keep it in a different place. This is handy when you want to have consistent commit messages across several different projects.
91
+
92
+ This would be a simple style guide:
93
+
94
+ ```
95
+ - Use conventional commits format (type: description)
96
+ - Keep first line under 72 characters
97
+ - Use present tense ("add" not "added")
98
+ - Be descriptive but concise
99
+ - Have fun. Be creative. Add ASCII art if you feel like it.
100
+ ```
101
+
102
+ ## Last Thoughts
103
+
104
+ This gem saves its commit message in the file `.aigcm_msg` at the root directory of the repository. Its there even if you do a `--dry` run. This could be handy if you want to incorporate `aigcm` into some larger workflow.
105
+
106
+ Remember that the style guide can be extended using one or more `--context` strings. For example you could create a shell alias like this:
107
+
108
+ ```
109
+ alias gc='aigcm -c "JIRA $JIRA_TICKET"'
110
+ ```
111
+
112
+ ## Development
113
+
114
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
115
+
116
+ To install this gem onto your local machine, run `bundle exec rake install`.
117
+
118
+ ## Contributing
119
+
120
+ 1. Fork it (<https://github.com/your_username/aigcm/fork>)
121
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
122
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
123
+ 4. Push to the branch (`git push origin my-new-feature`)
124
+ 5. Create a new Pull Request
125
+
126
+ ## License
127
+
128
+ The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ task default: :test
data/bin/aigcm ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/aigcm'
4
+
5
+ Aigcm.run
@@ -0,0 +1,113 @@
1
+
2
+ require "net/http"
3
+ require "json"
4
+ require "open3"
5
+ require "ai_client"
6
+
7
+ module Aigcm
8
+ class CommitMessageGenerator
9
+ class Error < StandardError; end
10
+
11
+ MAX_DIFF_SIZE = 4000 # Characters
12
+
13
+ def initialize(model:, provider:, max_tokens:, force_external:)
14
+ @force_external = force_external
15
+ validate_model_provider_combination(model)
16
+ check_provider_availability
17
+
18
+ @client = AiClient.new(model, provider: provider)
19
+ rescue StandardError => e
20
+ raise Error, "Failed to initialize AI client: #{e.message}"
21
+ end
22
+
23
+ def generate(diff, style_guide, context = [])
24
+ return "No changes to commit" if diff.strip.empty?
25
+
26
+ check_repository_privacy unless @force_external
27
+
28
+ # Truncate diff if too large
29
+ if diff.length > MAX_DIFF_SIZE
30
+ diff = diff[0...MAX_DIFF_SIZE] + "\n...[diff truncated]"
31
+ end
32
+
33
+ processed_context = process_context(context)
34
+ prompt = build_prompt(diff, style_guide, processed_context)
35
+
36
+ begin
37
+ response = @client.chat(prompt)
38
+ response.to_s.strip
39
+ rescue StandardError => e
40
+ "Error generating commit message: #{e.message}"
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def validate_model_provider_combination(model)
47
+ client = AiClient.new(model)
48
+ @provider = client.provider
49
+ rescue ArgumentError => e
50
+ raise Error, "Invalid model/provider combination: #{e.message}"
51
+ end
52
+
53
+ def check_provider_availability
54
+ case @provider
55
+ when :ollama
56
+ check_ollama_running
57
+ when :localai
58
+ check_localai_running
59
+ end
60
+ rescue StandardError => e
61
+ raise Error, "Provider not available: #{e.message}"
62
+ end
63
+
64
+ def check_ollama_running
65
+ Net::HTTP.get(URI("http://localhost:11434/api/version"))
66
+ rescue StandardError
67
+ raise Error, "Ollama is not running. Please start ollama first."
68
+ end
69
+
70
+ def check_localai_running
71
+ Net::HTTP.get(URI("http://localhost:8080/v1/models"))
72
+ rescue StandardError
73
+ raise Error, "LocalAI is not running. Please start localai first."
74
+ end
75
+
76
+ def process_context(context_array)
77
+ context_array.map do |ctx|
78
+ if ctx.start_with?("@")
79
+ filename = ctx[1..]
80
+ File.read(filename) rescue "Could not read #{filename}"
81
+ else
82
+ ctx
83
+ end
84
+ end
85
+ end
86
+
87
+ def check_repository_privacy
88
+ return if @provider == :ollama # Local provider is always safe
89
+
90
+ stdout, _, status = Open3.capture3("gh repo view --json isPrivate -q '.isPrivate'")
91
+
92
+ if status.success? && stdout.strip == "true"
93
+ raise Error, "This is a private repository. Use a local model (ollama) or run with --force-external flag"
94
+ end
95
+ rescue Errno::ENOENT
96
+ puts "Warning: Unable to check repository privacy status (gh command not found)"
97
+ end
98
+
99
+ def build_prompt(diff, style_guide, context)
100
+ <<~PROMPT
101
+ Generate a commit message for the git diff that follows these instructions.
102
+ Do not wrap your response in a code block.
103
+ Follow these style guidelines when constructing your response:
104
+ #{style_guide}
105
+
106
+ #{context.join("\n") unless context.empty?}
107
+
108
+ Git diff:
109
+ #{diff}
110
+ PROMPT
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,44 @@
1
+ require "open3"
2
+
3
+ module Aigcm
4
+ class GitDiff
5
+ class Error < StandardError; end
6
+
7
+ def initialize(dir:, commit_hash: nil, amend: false)
8
+ @dir = dir
9
+ @commit_hash = commit_hash
10
+ @amend = amend
11
+ validate_git_repo
12
+ end
13
+
14
+ def generate_diff
15
+ Dir.chdir(@dir) do
16
+ cmd = if @amend
17
+ "git diff --cached HEAD^ 2>/dev/null || git diff --cached"
18
+ elsif @commit_hash
19
+ "git diff #{@commit_hash}^..#{@commit_hash}"
20
+ else
21
+ "git diff --cached"
22
+ end
23
+
24
+ stdout, _, status = Open3.capture3(cmd)
25
+
26
+ raise Error, "Git command failed" unless status.success?
27
+ raise Error, "No changes detected" if stdout.strip.empty?
28
+
29
+ stdout
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def validate_git_repo
36
+ Dir.chdir(@dir) do
37
+ _, _, status = Open3.capture3("git rev-parse --git-dir")
38
+ raise Error, "Not a git repository" unless status.success?
39
+ end
40
+ rescue Errno::ENOENT
41
+ raise Error, "Directory not found: #{@dir}"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,50 @@
1
+ require 'erb'
2
+
3
+ module Aigcm
4
+ class StyleGuide
5
+ LINE_MAX = 72
6
+ DEFAULT_GUIDE = ERB.new(
7
+ File.read(__FILE__)
8
+ .split("__END__")
9
+ .last
10
+ .strip
11
+ ).result
12
+
13
+ def self.load(dir, custom_path = nil)
14
+ # If a custom path is provided, use it
15
+ if custom_path
16
+ return load_from_file(custom_path)
17
+ end
18
+
19
+ # Check for COMMITS.md in the repository root
20
+ config_file = File.join(dir, "COMMITS.md")
21
+ return load_from_file(config_file) if File.exist?(config_file)
22
+
23
+ # Fallback to the default style guide
24
+ DEFAULT_GUIDE
25
+ rescue StandardError => e
26
+ puts "Warning: Error reading style guide: #{e.message}"
27
+ DEFAULT_GUIDE
28
+ end
29
+
30
+ private_class_method def self.load_from_file(path)
31
+ File.read(path)
32
+ end
33
+ end
34
+ end
35
+
36
+ __END__
37
+
38
+ 1. Craft a Clear Subject Line:
39
+ • Summarize Concisely: Begin with a brief summary (<%= Aigcm::StyleGuide::LINE_MAX %> characters max).
40
+ • Capitalize the Subject: Start the subject line with a capital letter.
41
+ • Omit Periods in Subject Line: Avoid ending with a period to save space.
42
+ • Use Imperative Mood: Phrase commands as direct actions (e.g., "Add feature" instead of "Added feature").
43
+
44
+ 2. Provide a Detailed Body:
45
+ • Seperate the body from the subject line with a blank line.
46
+ • Explain the Reason: Clearly articulate the rationale for the change rather than just summarizing the modification.
47
+ • Wrap Body Text at <%= Aigcm::StyleGuide::LINE_MAX %> Characters: Ensure that the body text wraps at <%= Aigcm::StyleGuide::LINE_MAX %> characters per line.
48
+
49
+ 3. Reference Issues/Tickets:
50
+ • Include relevant issue numbers, ticket IDs and/or references when they are provided. Dp not invent your own reference. Use what has been provided.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aigcm
4
+ VERSION = "0.2.0"
5
+ end
data/lib/aigcm.rb ADDED
@@ -0,0 +1,146 @@
1
+ # lib/aigcm.rb
2
+
3
+ require 'debug_me'
4
+ include DebugMe
5
+
6
+ require 'optparse'
7
+ require 'ai_client'
8
+ require 'time'
9
+
10
+ require_relative 'aigcm/version'
11
+ require_relative 'aigcm/git_diff'
12
+ require_relative 'aigcm/commit_message_generator'
13
+ require_relative 'aigcm/style_guide'
14
+
15
+ module Aigcm
16
+ COMMIT_MESSAGE_FILE = '.aigcm_msg'
17
+ RECENT_THRESHOLD = 60 # seconds (1 minute)
18
+
19
+ class Error < StandardError; end
20
+
21
+ def self.run(test_mode: false)
22
+ dir = Dir.pwd
23
+ options = parse_options
24
+
25
+ if options[:amend]
26
+ system('git commit --amend')
27
+ return
28
+ end
29
+
30
+ commit_message = check_recent_commit(dir)
31
+
32
+ # Generate a new commit message if not reusing an existing one
33
+ commit_message ||= generate_commit_message(dir, options)
34
+
35
+ perform_commit(dir, commit_message, options)
36
+
37
+ rescue OptionParser::InvalidOption => e
38
+ STDERR.puts "Error: '#{e.message}'"
39
+ exit 1
40
+ rescue GitDiff::Error => e
41
+ puts "Git error: #{e.message}"
42
+ exit 1
43
+ rescue StandardError => e
44
+ puts "Error: #{e.message}"
45
+ exit 1
46
+ end
47
+
48
+ private_class_method def self.parse_options
49
+ options = {
50
+ amend: false,
51
+ context: [],
52
+ dry: false,
53
+ model: 'gpt-4o-mini',
54
+ provider: nil,
55
+ force_external: false,
56
+ style: nil
57
+ }
58
+
59
+ OptionParser.new do |opts|
60
+ opts.banner = "Usage: aigcm [options] [ref]"
61
+
62
+ opts.on("-a", "--amend", "Amend the last commit") { options[:amend] = true }
63
+
64
+ opts.on("-cCONTEXT", "--context=CONTEXT", "Extra context beyond the diff") do |context|
65
+ options[:context] << context
66
+ end
67
+
68
+ opts.on("-d", "--dry", "Dry run the command") { options[:dry] = true }
69
+
70
+ opts.on("-mMODEL", "--model=MODEL", "The model to use") { |model| options[:model] = model }
71
+
72
+ opts.on("--provider=PROVIDER", "Specify the provider (ollama, openai, anthropic, etc)") do |provider|
73
+ provider = provider.to_sym
74
+ unless [:ollama, :openai, :anthropic, :google, :mistral].include?(provider)
75
+ puts "Invalid provider specified. Valid providers are: ollama, openai, anthropic, google, mistral"
76
+ exit 1
77
+ end
78
+ options[:provider] = provider
79
+ end
80
+
81
+ opts.on("--force-external", "Force using external AI provider even for private repos") {
82
+ options[:force_external] = true
83
+ }
84
+
85
+ opts.on("-sSTYLE", "--style=STYLE", "Path to the style guide file") { |style| options[:style] = style }
86
+
87
+ opts.on("--default", "Print the default style guide and exit") do
88
+ puts "\nDefault Style Guide:"
89
+ puts "-------------------"
90
+ puts StyleGuide::DEFAULT_GUIDE
91
+ exit
92
+ end
93
+
94
+ opts.on("--version", "Show version") { puts Aigcm::VERSION; exit }
95
+
96
+ end.parse!
97
+
98
+ options
99
+ end
100
+
101
+ private_class_method def self.check_recent_commit(dir)
102
+ commit_file_path = File.join(dir, COMMIT_MESSAGE_FILE)
103
+
104
+ if File.exist?(commit_file_path)
105
+ file_mod_time = File.mtime(commit_file_path)
106
+ current_time = Time.now
107
+ if (current_time - file_mod_time).to_i < RECENT_THRESHOLD
108
+ return File.read(commit_file_path)
109
+ end
110
+ end
111
+
112
+ nil
113
+ end
114
+
115
+ private_class_method def self.generate_commit_message(dir, options)
116
+ diff_generator = GitDiff.new(dir: dir, commit_hash: ARGV.shift, amend: options[:amend])
117
+ diff = diff_generator.generate_diff
118
+
119
+ style_guide = StyleGuide.load(dir, options[:style])
120
+ generator = CommitMessageGenerator.new(
121
+ model: options[:model],
122
+ provider: options[:provider],
123
+ max_tokens: 1000,
124
+ force_external: options[:force_external]
125
+ )
126
+
127
+ commit_message = generator.generate(diff, style_guide, options[:context])
128
+ File.write(File.join(dir, COMMIT_MESSAGE_FILE), commit_message)
129
+ commit_message
130
+ end
131
+
132
+ private_class_method def self.perform_commit(dir, commit_message, options)
133
+ commit_file_path = File.join(dir, COMMIT_MESSAGE_FILE)
134
+
135
+ if options[:dry]
136
+ puts "\nDry run - would generate commit message:"
137
+ puts "-"*StyleGuide::LINE_MAX
138
+ puts commit_message
139
+ puts "-"*StyleGuide::LINE_MAX
140
+ puts
141
+ else
142
+ File.write(commit_file_path, commit_message)
143
+ system("git commit --edit -F #{commit_file_path}")
144
+ end
145
+ end
146
+ end
data/sig/aicommit.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Aicommit
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aigcm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Dewayne VanHoozer
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-02-09 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ai_client
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.4.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.4.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: minitest
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.16'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.16'
40
+ - !ruby/object:Gem::Dependency
41
+ name: mocha
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rubocop
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.21'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.21'
82
+ description: |
83
+ `aigcm` generates meaningful git commit messages using artificial
84
+ intelligence. It supports multiple AI providers including OpenAI,
85
+ Anthropic, Google, and local models via Ollama. The gem
86
+ automatically detects private repositories and defaults to using
87
+ local models for security. It integrates seamlessly with git
88
+ workflows and supports various commit scenarios including amending
89
+ commits and handling staged changes. The gem follows conventional
90
+ commit message formats and allows customization of commit message
91
+ styles through configuration.
92
+ email:
93
+ - dvanhoozer@gmail.com
94
+ executables:
95
+ - aigcm
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - ".envrc"
100
+ - CHANGELOG.md
101
+ - LICENSE.txt
102
+ - README.md
103
+ - Rakefile
104
+ - bin/aigcm
105
+ - lib/aigcm.rb
106
+ - lib/aigcm/commit_message_generator.rb
107
+ - lib/aigcm/git_diff.rb
108
+ - lib/aigcm/style_guide.rb
109
+ - lib/aigcm/version.rb
110
+ - sig/aicommit.rbs
111
+ homepage: https://github.com/MadBomber/aigcm
112
+ licenses:
113
+ - MIT
114
+ metadata:
115
+ allowed_push_host: https://rubygems.org
116
+ homepage_uri: https://github.com/MadBomber/aigcm
117
+ source_code_uri: https://github.com/MadBomber/aigcm
118
+ changelog_uri: https://github.com/MadBomber/aigcm/blob/main/CHANGELOG.md
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: 3.1.0
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.6.3
134
+ specification_version: 4
135
+ summary: AI-powered git commit message generator
136
+ test_files: []