nitpicker-code-review 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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +201 -0
- data/bin/nitpicker +15 -0
- data/config/prompt +39 -0
- data/lib/nitpicker/version.rb +3 -0
- data/lib/nitpicker.rb +130 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b493182d8ba98bc4e102c13f0a379eaf545f920f9cb4f72ce4b4a0db4d164d51
|
4
|
+
data.tar.gz: 285e6dd3c76d4a2a7d4df310d3618f058fd6e39335dd5d965b1155205376a399
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eb1d96af03c6add163aca48519af15bbccc4ebc685d9d212b3cf52f925b345ff1bbd908c807f686e2e240e5d7075ee12f9e78dbf5ea45abb69d1da9b8ca91ad3
|
7
|
+
data.tar.gz: 54a486f87f322170dd2c0edfb41a225f5723f1507e8280f45d74dfd5a16026ed5a1a529a36eac3d08255c953ee2f076b760fc433e75d2272cc9c0a3c68d68fc8
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Your Name
|
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,201 @@
|
|
1
|
+
# NitPicker
|
2
|
+
|
3
|
+
NitPicker is a command-line tool that provides AI-powered code reviews for your Git changes. It analyzes your staged changes and offers constructive feedback to help improve code quality, security, performance, and maintainability.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- AI-powered code review of staged Git changes
|
8
|
+
- Comprehensive analysis covering code quality, security, performance, and best practices
|
9
|
+
- Customizable AI prompts for tailored review feedback
|
10
|
+
- Support for repository-specific prompts
|
11
|
+
- Choose any AI model (Google Gemini 2.5 Flash by default)
|
12
|
+
- Easy integration into your Git workflow
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
### Requirements
|
17
|
+
|
18
|
+
- Ruby 2.6 or higher
|
19
|
+
- Git
|
20
|
+
|
21
|
+
### Option 1: Install as a Gem (Recommended)
|
22
|
+
|
23
|
+
```bash
|
24
|
+
gem install nitpicker-code-review
|
25
|
+
```
|
26
|
+
|
27
|
+
This automatically adds NitPicker to your PATH.
|
28
|
+
|
29
|
+
### Option 2: Build and Install from Source
|
30
|
+
|
31
|
+
Clone this repository:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
git clone https://github.com/jubishop/NitPicker.git
|
35
|
+
cd NitPicker
|
36
|
+
```
|
37
|
+
|
38
|
+
Build and install the gem:
|
39
|
+
|
40
|
+
```bash
|
41
|
+
gem build gemspec/nitpicker.gemspec
|
42
|
+
gem install nitpicker-code-review-*.gem
|
43
|
+
```
|
44
|
+
|
45
|
+
### Option 3: Manual Installation
|
46
|
+
|
47
|
+
Clone this repository:
|
48
|
+
|
49
|
+
```bash
|
50
|
+
git clone https://github.com/jubishop/NitPicker.git
|
51
|
+
cd NitPicker
|
52
|
+
```
|
53
|
+
|
54
|
+
Make the script executable:
|
55
|
+
|
56
|
+
```bash
|
57
|
+
chmod +x bin/nitpicker
|
58
|
+
```
|
59
|
+
|
60
|
+
Create a symbolic link to make NitPicker available globally:
|
61
|
+
|
62
|
+
```bash
|
63
|
+
ln -s "$(pwd)/bin/nitpicker" /usr/local/bin/nitpicker
|
64
|
+
```
|
65
|
+
|
66
|
+
## Configuration
|
67
|
+
|
68
|
+
### API Key Setup
|
69
|
+
|
70
|
+
NitPicker requires an OpenRouter API key to generate code reviews. You need to set this as an environment variable:
|
71
|
+
|
72
|
+
```bash
|
73
|
+
export OPENROUTER_API_KEY="your_openrouter_api_key"
|
74
|
+
```
|
75
|
+
|
76
|
+
You can get an API key from [OpenRouter](https://openrouter.ai/).
|
77
|
+
|
78
|
+
Optionally, you can specify a different model by setting:
|
79
|
+
|
80
|
+
```bash
|
81
|
+
export GIT_REVIEW_MODEL="openai/gpt-4o"
|
82
|
+
```
|
83
|
+
|
84
|
+
The default model is `google/gemini-2.5-flash-preview-05-20` if not specified.
|
85
|
+
|
86
|
+
### Prompt Configuration
|
87
|
+
|
88
|
+
NitPicker supports two levels of prompt configuration:
|
89
|
+
|
90
|
+
- **Global Prompt (Default)**: Stored in `~/.config/nitpicker/prompt`. This is used for all repositories unless overridden.
|
91
|
+
- **Repository-Specific Prompt**: Create a `.nitpicker_prompt` file in the root of your Git repository to customize the prompt for that specific project.
|
92
|
+
|
93
|
+
When you run NitPicker, it will:
|
94
|
+
- First look for a `.nitpicker_prompt` file in the root of the current Git repository
|
95
|
+
- If not found, fall back to the global prompt at `~/.config/nitpicker/prompt`
|
96
|
+
|
97
|
+
When you run NitPicker for the first time, if there's no global prompt file in the config directory, it will copy `config/prompt` to the config directory automatically.
|
98
|
+
|
99
|
+
The special string `{{DIFF}}` in your prompt will be replaced with the current git diff of staged changes.
|
100
|
+
|
101
|
+
## Usage
|
102
|
+
|
103
|
+
Navigate to your Git repository, stage your changes, and run:
|
104
|
+
|
105
|
+
```bash
|
106
|
+
nitpicker [options]
|
107
|
+
```
|
108
|
+
|
109
|
+
Options:
|
110
|
+
- `--version`: Show version information
|
111
|
+
- `-h, --help`: Show help message
|
112
|
+
|
113
|
+
## Examples
|
114
|
+
|
115
|
+
```bash
|
116
|
+
# Stage some changes first
|
117
|
+
git add .
|
118
|
+
|
119
|
+
# Get AI code review of staged changes
|
120
|
+
nitpicker
|
121
|
+
```
|
122
|
+
|
123
|
+
Example output:
|
124
|
+
```
|
125
|
+
## Code Review Summary
|
126
|
+
|
127
|
+
**Overall Assessment:** The changes look good with a few minor suggestions for improvement.
|
128
|
+
|
129
|
+
### Positive Aspects:
|
130
|
+
- Clean, readable code structure
|
131
|
+
- Proper error handling implemented
|
132
|
+
- Good variable naming conventions
|
133
|
+
|
134
|
+
### Suggestions for Improvement:
|
135
|
+
|
136
|
+
**Security:**
|
137
|
+
- Consider validating user input on line 45 to prevent potential injection attacks
|
138
|
+
|
139
|
+
**Performance:**
|
140
|
+
- The database query on line 23 could be optimized by adding an index on the `user_id` column
|
141
|
+
|
142
|
+
**Best Practices:**
|
143
|
+
- Consider extracting the validation logic into a separate method for better reusability
|
144
|
+
```
|
145
|
+
|
146
|
+
## License
|
147
|
+
|
148
|
+
MIT
|
149
|
+
|
150
|
+
## Development
|
151
|
+
|
152
|
+
### Project Structure
|
153
|
+
|
154
|
+
NitPicker follows a specific project structure where all gemspec files and built gem files (.gem) are placed in the `gemspec/` folder rather than the root directory. This keeps the root directory clean and organized.
|
155
|
+
|
156
|
+
### Rake Tasks
|
157
|
+
|
158
|
+
NitPicker provides several rake tasks to streamline development:
|
159
|
+
|
160
|
+
```bash
|
161
|
+
# Run the test suite
|
162
|
+
rake test
|
163
|
+
|
164
|
+
# Build the gem and place it in the gemspec/ folder
|
165
|
+
rake build
|
166
|
+
|
167
|
+
# Build, install and test the gem
|
168
|
+
rake install
|
169
|
+
|
170
|
+
# Build and push the gem to RubyGems
|
171
|
+
rake push
|
172
|
+
```
|
173
|
+
|
174
|
+
The default task is `rake test`.
|
175
|
+
|
176
|
+
### Testing
|
177
|
+
|
178
|
+
NitPicker uses Minitest for testing. To run the tests:
|
179
|
+
|
180
|
+
```bash
|
181
|
+
bundle install
|
182
|
+
rake test
|
183
|
+
```
|
184
|
+
|
185
|
+
The test suite includes:
|
186
|
+
- Unit tests for the CLI functionality
|
187
|
+
- Tests for version consistency
|
188
|
+
- Mock tests for API interactions (using WebMock)
|
189
|
+
|
190
|
+
## Contributing
|
191
|
+
|
192
|
+
1. Fork the repository
|
193
|
+
2. Create a feature branch
|
194
|
+
3. Make your changes
|
195
|
+
4. Add tests for new functionality
|
196
|
+
5. Ensure all tests pass
|
197
|
+
6. Submit a pull request
|
198
|
+
|
199
|
+
## Author
|
200
|
+
|
201
|
+
Justin Bishop (jubishop)
|
data/bin/nitpicker
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# This file is part of the standard gem pattern for executables.
|
5
|
+
# When installed as a gem, RubyGems will create a wrapper script
|
6
|
+
# that sets up the correct load path and then requires this file.
|
7
|
+
|
8
|
+
# Add lib to the load path when running from source
|
9
|
+
lib_dir = File.expand_path('../lib', __dir__)
|
10
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
11
|
+
|
12
|
+
require 'nitpicker'
|
13
|
+
|
14
|
+
# Execute the CLI
|
15
|
+
NitPicker::CLI.new.run
|
data/config/prompt
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
You are an expert software engineer conducting a thorough code review. Analyze the following git diff and provide constructive feedback focusing on:
|
2
|
+
|
3
|
+
**Code Quality & Best Practices:**
|
4
|
+
- Code readability, maintainability, and organization
|
5
|
+
- Adherence to language-specific conventions and idioms
|
6
|
+
- Proper error handling and edge cases
|
7
|
+
- Code duplication and refactoring opportunities
|
8
|
+
|
9
|
+
**Security & Performance:**
|
10
|
+
- Potential security vulnerabilities
|
11
|
+
- Performance implications and optimization opportunities
|
12
|
+
- Resource management and memory usage
|
13
|
+
- Database query efficiency (if applicable)
|
14
|
+
|
15
|
+
**Testing & Documentation:**
|
16
|
+
- Test coverage for new functionality
|
17
|
+
- Missing or inadequate documentation
|
18
|
+
- API documentation and code comments
|
19
|
+
|
20
|
+
**Architecture & Design:**
|
21
|
+
- Design patterns and architectural consistency
|
22
|
+
- Separation of concerns and modularity
|
23
|
+
- Potential breaking changes or backwards compatibility
|
24
|
+
|
25
|
+
**Specific Issues:**
|
26
|
+
- Logic errors or bugs
|
27
|
+
- Incorrect variable names or typos
|
28
|
+
- Missing validation or sanitization
|
29
|
+
- Hardcoded values that should be configurable
|
30
|
+
|
31
|
+
Provide your feedback in a clear, constructive manner. For each issue identified:
|
32
|
+
1. Explain the problem clearly
|
33
|
+
2. Suggest specific improvements
|
34
|
+
3. Explain why the change would be beneficial
|
35
|
+
|
36
|
+
If the code looks good overall, highlight what was done well and provide any minor suggestions for improvement.
|
37
|
+
|
38
|
+
DIFF:
|
39
|
+
{{DIFF}}
|
data/lib/nitpicker.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'nitpicker/version'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'tmpdir'
|
7
|
+
|
8
|
+
module NitPicker
|
9
|
+
class CLI
|
10
|
+
CONFIG_DIR = File.expand_path('~/.config/nitpicker')
|
11
|
+
PROMPT_FILE = File.join(CONFIG_DIR, 'prompt')
|
12
|
+
REPO_PROMPT_FILE = '.nitpicker_prompt'
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@options = {}
|
16
|
+
setup_config_dir
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_options
|
20
|
+
require 'optparse'
|
21
|
+
|
22
|
+
OptionParser.new do |opts|
|
23
|
+
opts.banner = 'Usage: nitpicker [options]'
|
24
|
+
opts.version = VERSION
|
25
|
+
|
26
|
+
opts.on('-h', '--help', 'Show this help message') do
|
27
|
+
puts opts
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
end.parse!
|
31
|
+
end
|
32
|
+
|
33
|
+
def run
|
34
|
+
parse_options
|
35
|
+
|
36
|
+
# Get git diff of staged changes
|
37
|
+
diff = `git diff --staged`
|
38
|
+
|
39
|
+
if diff.empty?
|
40
|
+
puts "No changes staged for review."
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get AI-generated code review
|
45
|
+
review = generate_code_review(diff)
|
46
|
+
|
47
|
+
# Display the review
|
48
|
+
puts review
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def setup_config_dir
|
54
|
+
unless Dir.exist?(CONFIG_DIR)
|
55
|
+
FileUtils.mkdir_p(CONFIG_DIR)
|
56
|
+
end
|
57
|
+
|
58
|
+
unless File.exist?(PROMPT_FILE)
|
59
|
+
# Check for bundled prompt file in the config directory
|
60
|
+
config_prompt = File.join(File.dirname(__FILE__), '..', 'config', 'prompt')
|
61
|
+
|
62
|
+
if File.exist?(config_prompt)
|
63
|
+
puts "Copying bundled prompt file to #{PROMPT_FILE}"
|
64
|
+
FileUtils.cp(config_prompt, PROMPT_FILE)
|
65
|
+
puts "Prompt file installed successfully."
|
66
|
+
else
|
67
|
+
puts "Error: Prompt file not found at #{PROMPT_FILE}"
|
68
|
+
puts "No bundled prompt file found at: #{config_prompt}"
|
69
|
+
puts "Please create a prompt file with your custom prompt."
|
70
|
+
exit 1 unless defined?(TESTING_MODE) && TESTING_MODE
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_prompt
|
76
|
+
# First check for repository-specific prompt
|
77
|
+
if File.exist?(REPO_PROMPT_FILE)
|
78
|
+
return File.read(REPO_PROMPT_FILE)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Fall back to global prompt
|
82
|
+
File.read(PROMPT_FILE)
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_code_review(diff)
|
86
|
+
api_key = ENV['OPENROUTER_API_KEY']
|
87
|
+
if api_key.nil? || api_key.empty?
|
88
|
+
puts "Error: OPENROUTER_API_KEY environment variable not set"
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
|
92
|
+
model = ENV['GIT_REVIEW_MODEL'] || 'google/gemini-2.5-flash-preview-05-20'
|
93
|
+
|
94
|
+
prompt = get_prompt.gsub('{{DIFF}}', diff)
|
95
|
+
|
96
|
+
uri = URI.parse('https://openrouter.ai/api/v1/chat/completions')
|
97
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
98
|
+
http.use_ssl = true
|
99
|
+
|
100
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
101
|
+
request['Content-Type'] = 'application/json'
|
102
|
+
request['Authorization'] = "Bearer #{api_key}"
|
103
|
+
request['HTTP-Referer'] = 'https://github.com/nitpicker-code-review'
|
104
|
+
|
105
|
+
request.body = {
|
106
|
+
model: model,
|
107
|
+
messages: [
|
108
|
+
{ role: 'user', content: prompt }
|
109
|
+
],
|
110
|
+
max_tokens: 2000
|
111
|
+
}.to_json
|
112
|
+
|
113
|
+
begin
|
114
|
+
response = http.request(request)
|
115
|
+
|
116
|
+
if response.code == '200'
|
117
|
+
result = JSON.parse(response.body)
|
118
|
+
review = result['choices'][0]['message']['content'].strip
|
119
|
+
return review
|
120
|
+
else
|
121
|
+
puts "API Error (#{response.code}): #{response.body}"
|
122
|
+
exit 1
|
123
|
+
end
|
124
|
+
rescue => e
|
125
|
+
puts "Error: #{e.message}"
|
126
|
+
exit 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nitpicker-code-review
|
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-28 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
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rake
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '13.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '13.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: minitest
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '5.0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '5.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: webmock
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
description: NitPicker is a command-line tool that uses AI to review your staged Git
|
69
|
+
changes and provide constructive feedback
|
70
|
+
email:
|
71
|
+
- jubishop@gmail.com
|
72
|
+
executables:
|
73
|
+
- nitpicker
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- LICENSE
|
78
|
+
- README.md
|
79
|
+
- bin/nitpicker
|
80
|
+
- config/prompt
|
81
|
+
- lib/nitpicker.rb
|
82
|
+
- lib/nitpicker/version.rb
|
83
|
+
homepage: https://github.com/jubishop/NitPicker
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 2.6.0
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubygems_version: 3.6.6
|
102
|
+
specification_version: 4
|
103
|
+
summary: AI-powered Git code review tool
|
104
|
+
test_files: []
|