jeeves-git-commit 1.0.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.
Files changed (8) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +129 -0
  4. data/bin/jeeves +8 -0
  5. data/lib/jeeves/version.rb +3 -0
  6. data/lib/jeeves.rb +151 -0
  7. data/prompt +17 -0
  8. metadata +62 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0dd0e12b327978c0f394aabd34219bf22258b301cef48863cb3e0f9934ac22ab
4
+ data.tar.gz: aebc9e5ad350aa9590e851e60be5933762b810f1b27c5687bccbdaf7e3dcd440
5
+ SHA512:
6
+ metadata.gz: 05b9de03a92ad61959eab40ce88a8e8afdd301717cbe3a626fcea92aa2124c90682dfbbd2a36b87d0a9f63845fea062f8bdc4192efc4cf4a6f8f6a602a1f4284
7
+ data.tar.gz: cba84b40e5d16f40d929b06c30bbb3cd4ad57966373a5ae69d3099b0b48c246f93ebdfc828aa64943b537c7427731cdae33ef187b6a491b9d9917ea00adad661
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Justin Bishop
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # Jeeves
2
+
3
+ <p align="center">
4
+ <img src="jeeves.png" alt="Jeeves Logo" width="200">
5
+ </p>
6
+
7
+ Jeeves is a command-line tool that helps you create AI-powered Git commit messages. It streamlines your Git workflow by automatically generating meaningful commit messages based on your code changes.
8
+
9
+ ## Features
10
+
11
+ - Generate intelligent commit messages based on your staged changes
12
+ - Option to automatically stage all changes before committing
13
+ - Option to push changes after committing
14
+ - Customizable AI prompts for tailored commit message generation
15
+
16
+ ## Installation
17
+
18
+ ### Requirements
19
+
20
+ - Ruby 2.6 or higher
21
+ - Git
22
+
23
+ ### Option 1: Install as a Gem (Recommended)
24
+
25
+ ```bash
26
+ gem install jeeves-git-commit
27
+ ```
28
+
29
+ This automatically adds Jeeves to your PATH.
30
+
31
+ ### Option 2: Build and Install from Source
32
+
33
+ 1. Clone this repository:
34
+
35
+ ```bash
36
+ git clone https://github.com/jubishop/Jeeves.git
37
+ cd Jeeves
38
+ ```
39
+
40
+ 2. Build and install the gem:
41
+
42
+ ```bash
43
+ gem build jeeves.gemspec
44
+ gem install jeeves-git-commit-*.gem
45
+ ```
46
+
47
+ ### Option 3: Use the Install Script
48
+
49
+ 1. Clone this repository:
50
+
51
+ ```bash
52
+ git clone https://github.com/jubishop/Jeeves.git
53
+ cd Jeeves
54
+ ```
55
+
56
+ 2. Run the install script:
57
+
58
+ ```bash
59
+ ./install.sh
60
+ ```
61
+
62
+ The script will:
63
+ - Install Jeeves to `/usr/local/bin` (or `~/.local/bin` if you don't have write access)
64
+ - Add the install location to your PATH if necessary
65
+ - Set up the config directory with the default prompt file
66
+ - Make sure the script is executable
67
+
68
+ ### Option 4: Manual Installation
69
+
70
+ 1. Clone this repository:
71
+
72
+ ```bash
73
+ git clone https://github.com/jubishop/Jeeves.git
74
+ cd Jeeves
75
+ ```
76
+
77
+ 2. Make the script executable:
78
+
79
+ ```bash
80
+ chmod +x bin/jeeves
81
+ ```
82
+
83
+ 3. Create a symbolic link to make Jeeves available globally:
84
+
85
+ ```bash
86
+ ln -s "$(pwd)/bin/jeeves" /usr/local/bin/jeeves
87
+ ```
88
+
89
+ ## Usage
90
+
91
+ Navigate to your Git repository and run:
92
+
93
+ ```bash
94
+ jeeves [options]
95
+ ```
96
+
97
+ Options:
98
+
99
+ - `-a, --all`: Stage all changes before committing
100
+ - `-p, --push`: Push changes after committing
101
+ - `--version`: Show version information
102
+ - `-h, --help`: Show help message
103
+
104
+ ## Configuration
105
+
106
+ Jeeves stores its configuration in `~/.config/jeeves/`. You can customize the AI prompt by editing the `prompt` file in this directory.
107
+
108
+ When you run Jeeves for the first time, if there's no prompt file in the config directory, it will check for a bundled prompt file in the same directory as the script and copy it to the config directory automatically.
109
+
110
+ ## Examples
111
+
112
+ ```bash
113
+ # Generate a commit message for already staged changes
114
+ jeeves
115
+
116
+ # Stage all changes and generate a commit message
117
+ jeeves -a
118
+
119
+ # Stage all changes, generate a commit message, and push
120
+ jeeves -a -p
121
+ ```
122
+
123
+ ## License
124
+
125
+ MIT
126
+
127
+ ## Author
128
+
129
+ [Justin Bishop (jubishop)](https://github.com/jubishop)
data/bin/jeeves ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'jeeves'
5
+
6
+ if $PROGRAM_NAME == __FILE__
7
+ Jeeves::CLI.new.run
8
+ end
@@ -0,0 +1,3 @@
1
+ module Jeeves
2
+ VERSION = '1.0.0'
3
+ end
data/lib/jeeves.rb ADDED
@@ -0,0 +1,151 @@
1
+ require 'jeeves/version'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'json'
5
+ require 'fileutils'
6
+ require 'tmpdir'
7
+
8
+ module Jeeves
9
+ class CLI
10
+ CONFIG_DIR = File.expand_path('~/.config/jeeves')
11
+ PROMPT_FILE = File.join(CONFIG_DIR, 'prompt')
12
+
13
+ def initialize
14
+ @options = {
15
+ all: false,
16
+ push: false
17
+ }
18
+ setup_config_dir
19
+ end
20
+
21
+ def parse_options
22
+ require 'optparse'
23
+
24
+ OptionParser.new do |opts|
25
+ opts.banner = 'Usage: jeeves [options]'
26
+ opts.version = VERSION
27
+
28
+ opts.on('-a', '--all', 'Stage all changes before committing') do
29
+ @options[:all] = true
30
+ end
31
+
32
+ opts.on('-p', '--push', 'Push changes after committing') do
33
+ @options[:push] = true
34
+ end
35
+
36
+ opts.on('-h', '--help', 'Show this help message') do
37
+ puts opts
38
+ exit
39
+ end
40
+ end.parse!
41
+ end
42
+
43
+ def run
44
+ parse_options
45
+
46
+ if @options[:all]
47
+ system('git add -A')
48
+ end
49
+
50
+ # Get git diff of staged changes
51
+ diff = `git diff --staged`
52
+
53
+ if diff.empty?
54
+ puts "No changes staged for commit."
55
+ exit 1
56
+ end
57
+
58
+ # Get AI-generated commit message
59
+ commit_message = generate_commit_message(diff)
60
+
61
+ # Write commit message to temp file for git to use
62
+ temp_file = File.join(Dir.tmpdir, 'jeeves_commit_message')
63
+ File.write(temp_file, commit_message)
64
+
65
+ # Commit with the generated message
66
+ system("git commit -F #{temp_file}")
67
+
68
+ # Clean up temp file
69
+ File.unlink(temp_file) if File.exist?(temp_file)
70
+
71
+ # Push if requested
72
+ if @options[:push]
73
+ puts "Pushing changes..."
74
+ system('git push')
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def setup_config_dir
81
+ unless Dir.exist?(CONFIG_DIR)
82
+ FileUtils.mkdir_p(CONFIG_DIR)
83
+ end
84
+
85
+ unless File.exist?(PROMPT_FILE)
86
+ # Check for bundled prompt file in the gem's data directory
87
+ gem_prompt = File.join(File.dirname(__FILE__), '..', '..', 'prompt')
88
+
89
+ if File.exist?(gem_prompt)
90
+ puts "Copying bundled prompt file to #{PROMPT_FILE}"
91
+ FileUtils.cp(gem_prompt, PROMPT_FILE)
92
+ puts "Prompt file installed successfully."
93
+ else
94
+ puts "Error: Prompt file not found at #{PROMPT_FILE}"
95
+ puts "No bundled prompt file found at #{gem_prompt}"
96
+ puts "Please create a prompt file with your custom prompt."
97
+ exit 1
98
+ end
99
+ end
100
+ end
101
+
102
+ def generate_commit_message(diff)
103
+ api_key = ENV['OPENROUTER_API_KEY']
104
+ if api_key.nil? || api_key.empty?
105
+ puts "Error: OPENROUTER_API_KEY environment variable not set"
106
+ exit 1
107
+ end
108
+
109
+ model = ENV['GIT_COMMIT_MODEL'] || 'openai/gpt-4.1-mini'
110
+
111
+ prompt = File.read(PROMPT_FILE).gsub('{{DIFF}}', diff)
112
+
113
+ uri = URI.parse('https://openrouter.ai/api/v1/chat/completions')
114
+ http = Net::HTTP.new(uri.host, uri.port)
115
+ http.use_ssl = true
116
+
117
+ request = Net::HTTP::Post.new(uri.request_uri)
118
+ request['Content-Type'] = 'application/json'
119
+ request['Authorization'] = "Bearer #{api_key}"
120
+ request['HTTP-Referer'] = 'https://github.com/jeeves-git-commit'
121
+
122
+ request.body = {
123
+ model: model,
124
+ messages: [
125
+ { role: 'user', content: prompt }
126
+ ],
127
+ max_tokens: 500
128
+ }.to_json
129
+
130
+ begin
131
+ response = http.request(request)
132
+
133
+ if response.code == '200'
134
+ result = JSON.parse(response.body)
135
+ commit_message = result['choices'][0]['message']['content'].strip
136
+ puts "Generated commit message:"
137
+ puts "------------------------"
138
+ puts commit_message
139
+ puts "------------------------"
140
+ return commit_message
141
+ else
142
+ puts "API Error (#{response.code}): #{response.body}"
143
+ exit 1
144
+ end
145
+ rescue => e
146
+ puts "Error: #{e.message}"
147
+ exit 1
148
+ end
149
+ end
150
+ end
151
+ end
data/prompt ADDED
@@ -0,0 +1,17 @@
1
+ Generate a git commit message based on the following diff.
2
+
3
+ The commit message should:
4
+ - Start with an appropriate gitmoji based on the nature of the changes
5
+ - Follow the Conventional Commits format (https://www.conventionalcommits.org/en/v1.0.0/)
6
+ - Explain WHAT changed, WHY it changed, and HOW it improves or fixes the current state
7
+ - Assume the audience is educated software engineers
8
+
9
+ Example format:
10
+ :emoji: type(scope): concise description
11
+
12
+ Detailed explanation of the changes, why they were necessary, and their impact.
13
+
14
+ Additional context or technical details when relevant.
15
+
16
+ DIFF:
17
+ {{DIFF}}
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jeeves-git-commit
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Justin Bishop
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-05-20 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: json
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.0'
26
+ description: Jeeves is a command-line tool that helps you create AI-powered Git commit
27
+ messages
28
+ email:
29
+ - jubishop@gmail.com
30
+ executables:
31
+ - jeeves
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - LICENSE
36
+ - README.md
37
+ - bin/jeeves
38
+ - lib/jeeves.rb
39
+ - lib/jeeves/version.rb
40
+ - prompt
41
+ homepage: https://github.com/jubishop/Jeeves
42
+ licenses:
43
+ - MIT
44
+ metadata: {}
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.6.0
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.6.6
60
+ specification_version: 4
61
+ summary: AI-powered Git commit message generator
62
+ test_files: []