prgen-cli 0.2.5__tar.gz → 0.3.0__tar.gz

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 (28) hide show
  1. prgen_cli-0.3.0/PKG-INFO +283 -0
  2. prgen_cli-0.3.0/README.md +257 -0
  3. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/pyproject.toml +2 -1
  4. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/api_errors.py +22 -2
  5. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/cli.py +113 -55
  6. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/config.py +42 -6
  7. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/defaults.py +1 -1
  8. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/prompts/pr_description.txt +2 -2
  9. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/providers/gemini_provider.py +0 -1
  10. prgen_cli-0.3.0/src/prgen/providers/ollama_provider.py +48 -0
  11. prgen_cli-0.3.0/src/prgen/ui.py +193 -0
  12. prgen_cli-0.3.0/src/prgen_cli.egg-info/PKG-INFO +283 -0
  13. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen_cli.egg-info/SOURCES.txt +1 -0
  14. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen_cli.egg-info/requires.txt +1 -0
  15. prgen_cli-0.2.5/PKG-INFO +0 -151
  16. prgen_cli-0.2.5/README.md +0 -126
  17. prgen_cli-0.2.5/src/prgen/ui.py +0 -87
  18. prgen_cli-0.2.5/src/prgen_cli.egg-info/PKG-INFO +0 -151
  19. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/LICENSE +0 -0
  20. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/setup.cfg +0 -0
  21. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/__main__.py +0 -0
  22. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/about.py +0 -0
  23. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/git_utils.py +0 -0
  24. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/prompting.py +0 -0
  25. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen/providers/openai_provider.py +0 -0
  26. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen_cli.egg-info/dependency_links.txt +0 -0
  27. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen_cli.egg-info/entry_points.txt +0 -0
  28. {prgen_cli-0.2.5 → prgen_cli-0.3.0}/src/prgen_cli.egg-info/top_level.txt +0 -0
@@ -0,0 +1,283 @@
1
+ Metadata-Version: 2.4
2
+ Name: prgen-cli
3
+ Version: 0.3.0
4
+ Summary: Generate PR titles and descriptions from git diff
5
+ Author: Jean Paul Fernandez
6
+ License-Expression: GPL-3.0-only
7
+ Project-URL: Homepage, https://github.com/jpxoi/prgen
8
+ Project-URL: Repository, https://github.com/jpxoi/prgen
9
+ Project-URL: Issues, https://github.com/jpxoi/prgen/issues
10
+ Keywords: cli,git,pull-request,diff,llm,openai,gemini
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Topic :: Software Development :: Version Control
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: google-genai>=1.70.0
21
+ Requires-Dist: ollama>=0.6.1
22
+ Requires-Dist: openai>=2.30.0
23
+ Requires-Dist: rich>=14.3.3
24
+ Requires-Dist: typer>=0.24.1
25
+ Dynamic: license-file
26
+
27
+ # prgen
28
+
29
+ Generate a pull request title and description from `git diff` and commit history.
30
+
31
+ ![prgen CLI help](images/help.png)
32
+
33
+ **Author:** Jean Paul Fernandez · [github.com/jpxoi/prgen](https://github.com/jpxoi/prgen)
34
+
35
+ Licensed under the [GNU General Public License v3.0](LICENSE) (GPL-3.0-only).
36
+
37
+ ## Requirements
38
+
39
+ - Python 3.10+
40
+ - `git` on your `PATH`
41
+ - One of:
42
+ - OpenAI API access
43
+ - Google Gemini API access
44
+ - A local or remote Ollama server
45
+
46
+ ## Install
47
+
48
+ From [PyPI](https://pypi.org/project/prgen-cli/):
49
+
50
+ ```bash
51
+ pip install prgen-cli
52
+ # or
53
+ uv tool install prgen-cli
54
+ ```
55
+
56
+ From a clone:
57
+
58
+ ```bash
59
+ uv sync
60
+ ```
61
+
62
+ Run the CLI with:
63
+
64
+ ```bash
65
+ prgen --help
66
+ ```
67
+
68
+ ## What It Does
69
+
70
+ `prgen` compares `HEAD` against a base ref, collects:
71
+
72
+ - `git diff <base>...HEAD`
73
+ - `git log <base>..HEAD`
74
+
75
+ It sends that context to an LLM and prints:
76
+
77
+ - a PR title from `<summary>...</summary>`
78
+ - a PR description from `<body>...</body>`
79
+
80
+ If the model does not return those tags, prgen prints the raw model output instead.
81
+
82
+ ## Providers
83
+
84
+ `prgen` supports three backends:
85
+
86
+ - `openai`
87
+ - `gemini`
88
+ - `ollama`
89
+
90
+ `--provider auto` is the default.
91
+
92
+ In `auto` mode:
93
+
94
+ - Gemini is chosen when `GOOGLE_API_KEY` is available
95
+ - otherwise OpenAI is chosen when `OPENAI_API_KEY` is available
96
+ - if neither key is configured, prgen exits with an error
97
+
98
+ Ollama is always explicit:
99
+
100
+ - use `--provider ollama`
101
+ - also pass `--model <name>`
102
+ - `--tier` presets do not apply to Ollama
103
+
104
+ ## Quick Start
105
+
106
+ OpenAI:
107
+
108
+ ```bash
109
+ prgen config set OPENAI_API_KEY sk-...
110
+ prgen
111
+ ```
112
+
113
+ Gemini:
114
+
115
+ ```bash
116
+ prgen config set GOOGLE_API_KEY your-key
117
+ prgen --provider gemini
118
+ ```
119
+
120
+ Ollama:
121
+
122
+ ```bash
123
+ prgen --provider ollama --model llama3.1:8b
124
+ ```
125
+
126
+ If the Ollama model is missing locally, let prgen pull it:
127
+
128
+ ```bash
129
+ prgen --provider ollama --model llama3.1:8b --pull
130
+ ```
131
+
132
+ ## Configuration
133
+
134
+ Configuration lives in `~/.config/prgen/config.json`.
135
+
136
+ If `XDG_CONFIG_HOME` is set, prgen uses:
137
+
138
+ ```bash
139
+ $XDG_CONFIG_HOME/prgen/config.json
140
+ ```
141
+
142
+ You can manage the file with:
143
+
144
+ ```bash
145
+ prgen config
146
+ prgen config show
147
+ prgen config path
148
+ ```
149
+
150
+ Supported persisted keys:
151
+
152
+ - `OPENAI_API_KEY`
153
+ - `GOOGLE_API_KEY`
154
+ - `OLLAMA_HOST`
155
+ - `base`
156
+ - `provider`
157
+ - `tier`
158
+
159
+ Notes:
160
+
161
+ - `OPENAI_API_KEY` and `GOOGLE_API_KEY` are treated as secrets
162
+ - `OLLAMA_HOST` is not secret and is merged into the environment if set
163
+ - `base`, `provider`, and `tier` are optional CLI defaults
164
+ - `model` and `context` are not persisted in config
165
+
166
+ Examples:
167
+
168
+ ```bash
169
+ prgen config
170
+ prgen config set OPENAI_API_KEY sk-...
171
+ prgen config set GOOGLE_API_KEY your-key
172
+ prgen config set OLLAMA_HOST http://127.0.0.1:11434
173
+ prgen config set base origin/main
174
+ prgen config set provider ollama
175
+ prgen config set tier pro
176
+ prgen config unset OLLAMA_HOST
177
+ prgen config show
178
+ ```
179
+
180
+ To read a secret value from stdin:
181
+
182
+ ```bash
183
+ prgen config set OPENAI_API_KEY - < key.txt
184
+ ```
185
+
186
+ ## Defaults
187
+
188
+ Built-in defaults:
189
+
190
+ | Option | Default | Notes |
191
+ | --- | --- | --- |
192
+ | `--repo`, `-C` | current directory | Uses the current git repo unless you point elsewhere |
193
+ | `--base` | `origin/main` | The ref must resolve locally |
194
+ | `--provider` | `auto` | Prefers Gemini over OpenAI when both keys exist |
195
+ | `--tier` | `default` | Used only for OpenAI and Gemini |
196
+ | `--model` | unset | Overrides tier selection; required for Ollama |
197
+ | `--context` | `none` | Extra text merged into the prompt |
198
+ | `--pull` | `false` | Only relevant for Ollama |
199
+
200
+ Config-file defaults apply only when you omit the matching flag:
201
+
202
+ - `base`
203
+ - `provider`
204
+ - `tier`
205
+
206
+ Explicit flags always win over the config file.
207
+
208
+ Current model presets:
209
+
210
+ - OpenAI `default`: `gpt-5-mini`
211
+ - OpenAI `pro`: `gpt-5.4`
212
+ - Gemini `default`: `gemini-3-flash-preview`
213
+ - Gemini `pro`: `gemini-3.1-pro-preview`
214
+
215
+ ## Usage
216
+
217
+ Basic usage:
218
+
219
+ ```bash
220
+ prgen
221
+ ```
222
+
223
+ Pick a different base:
224
+
225
+ ```bash
226
+ prgen --base main
227
+ ```
228
+
229
+ Run against another repository:
230
+
231
+ ```bash
232
+ prgen -C ~/src/my-project
233
+ ```
234
+
235
+ Override the model directly:
236
+
237
+ ```bash
238
+ prgen --provider openai --model gpt-5.4
239
+ prgen --provider gemini --model gemini-3.1-pro-preview
240
+ prgen --provider ollama --model mistral-small3.1
241
+ ```
242
+
243
+ Add extra context:
244
+
245
+ ```bash
246
+ prgen --context "Focus on customer-facing impact and rollout notes."
247
+ ```
248
+
249
+ ## Behavior Notes
250
+
251
+ - prgen validates that `--base` resolves before generating anything
252
+ - if there are no commits and no file changes vs the base ref, prgen exits with an error
253
+ - when `--provider ollama --pull` is used, prgen can download the model automatically
254
+ - when stderr is a TTY, loading states and Ollama downloads use Rich UI output
255
+
256
+ ## Development
257
+
258
+ Install local dependencies:
259
+
260
+ ```bash
261
+ uv sync
262
+ ```
263
+
264
+ Format and lint:
265
+
266
+ ```bash
267
+ uv run ruff format .
268
+ uv run ruff check .
269
+ ```
270
+
271
+ Run from the repo without installing globally:
272
+
273
+ ```bash
274
+ uv run prgen --help
275
+ ```
276
+
277
+ Install the local checkout as a global tool:
278
+
279
+ ```bash
280
+ uv tool install .
281
+ # or
282
+ pipx install .
283
+ ```
@@ -0,0 +1,257 @@
1
+ # prgen
2
+
3
+ Generate a pull request title and description from `git diff` and commit history.
4
+
5
+ ![prgen CLI help](images/help.png)
6
+
7
+ **Author:** Jean Paul Fernandez · [github.com/jpxoi/prgen](https://github.com/jpxoi/prgen)
8
+
9
+ Licensed under the [GNU General Public License v3.0](LICENSE) (GPL-3.0-only).
10
+
11
+ ## Requirements
12
+
13
+ - Python 3.10+
14
+ - `git` on your `PATH`
15
+ - One of:
16
+ - OpenAI API access
17
+ - Google Gemini API access
18
+ - A local or remote Ollama server
19
+
20
+ ## Install
21
+
22
+ From [PyPI](https://pypi.org/project/prgen-cli/):
23
+
24
+ ```bash
25
+ pip install prgen-cli
26
+ # or
27
+ uv tool install prgen-cli
28
+ ```
29
+
30
+ From a clone:
31
+
32
+ ```bash
33
+ uv sync
34
+ ```
35
+
36
+ Run the CLI with:
37
+
38
+ ```bash
39
+ prgen --help
40
+ ```
41
+
42
+ ## What It Does
43
+
44
+ `prgen` compares `HEAD` against a base ref, collects:
45
+
46
+ - `git diff <base>...HEAD`
47
+ - `git log <base>..HEAD`
48
+
49
+ It sends that context to an LLM and prints:
50
+
51
+ - a PR title from `<summary>...</summary>`
52
+ - a PR description from `<body>...</body>`
53
+
54
+ If the model does not return those tags, prgen prints the raw model output instead.
55
+
56
+ ## Providers
57
+
58
+ `prgen` supports three backends:
59
+
60
+ - `openai`
61
+ - `gemini`
62
+ - `ollama`
63
+
64
+ `--provider auto` is the default.
65
+
66
+ In `auto` mode:
67
+
68
+ - Gemini is chosen when `GOOGLE_API_KEY` is available
69
+ - otherwise OpenAI is chosen when `OPENAI_API_KEY` is available
70
+ - if neither key is configured, prgen exits with an error
71
+
72
+ Ollama is always explicit:
73
+
74
+ - use `--provider ollama`
75
+ - also pass `--model <name>`
76
+ - `--tier` presets do not apply to Ollama
77
+
78
+ ## Quick Start
79
+
80
+ OpenAI:
81
+
82
+ ```bash
83
+ prgen config set OPENAI_API_KEY sk-...
84
+ prgen
85
+ ```
86
+
87
+ Gemini:
88
+
89
+ ```bash
90
+ prgen config set GOOGLE_API_KEY your-key
91
+ prgen --provider gemini
92
+ ```
93
+
94
+ Ollama:
95
+
96
+ ```bash
97
+ prgen --provider ollama --model llama3.1:8b
98
+ ```
99
+
100
+ If the Ollama model is missing locally, let prgen pull it:
101
+
102
+ ```bash
103
+ prgen --provider ollama --model llama3.1:8b --pull
104
+ ```
105
+
106
+ ## Configuration
107
+
108
+ Configuration lives in `~/.config/prgen/config.json`.
109
+
110
+ If `XDG_CONFIG_HOME` is set, prgen uses:
111
+
112
+ ```bash
113
+ $XDG_CONFIG_HOME/prgen/config.json
114
+ ```
115
+
116
+ You can manage the file with:
117
+
118
+ ```bash
119
+ prgen config
120
+ prgen config show
121
+ prgen config path
122
+ ```
123
+
124
+ Supported persisted keys:
125
+
126
+ - `OPENAI_API_KEY`
127
+ - `GOOGLE_API_KEY`
128
+ - `OLLAMA_HOST`
129
+ - `base`
130
+ - `provider`
131
+ - `tier`
132
+
133
+ Notes:
134
+
135
+ - `OPENAI_API_KEY` and `GOOGLE_API_KEY` are treated as secrets
136
+ - `OLLAMA_HOST` is not secret and is merged into the environment if set
137
+ - `base`, `provider`, and `tier` are optional CLI defaults
138
+ - `model` and `context` are not persisted in config
139
+
140
+ Examples:
141
+
142
+ ```bash
143
+ prgen config
144
+ prgen config set OPENAI_API_KEY sk-...
145
+ prgen config set GOOGLE_API_KEY your-key
146
+ prgen config set OLLAMA_HOST http://127.0.0.1:11434
147
+ prgen config set base origin/main
148
+ prgen config set provider ollama
149
+ prgen config set tier pro
150
+ prgen config unset OLLAMA_HOST
151
+ prgen config show
152
+ ```
153
+
154
+ To read a secret value from stdin:
155
+
156
+ ```bash
157
+ prgen config set OPENAI_API_KEY - < key.txt
158
+ ```
159
+
160
+ ## Defaults
161
+
162
+ Built-in defaults:
163
+
164
+ | Option | Default | Notes |
165
+ | --- | --- | --- |
166
+ | `--repo`, `-C` | current directory | Uses the current git repo unless you point elsewhere |
167
+ | `--base` | `origin/main` | The ref must resolve locally |
168
+ | `--provider` | `auto` | Prefers Gemini over OpenAI when both keys exist |
169
+ | `--tier` | `default` | Used only for OpenAI and Gemini |
170
+ | `--model` | unset | Overrides tier selection; required for Ollama |
171
+ | `--context` | `none` | Extra text merged into the prompt |
172
+ | `--pull` | `false` | Only relevant for Ollama |
173
+
174
+ Config-file defaults apply only when you omit the matching flag:
175
+
176
+ - `base`
177
+ - `provider`
178
+ - `tier`
179
+
180
+ Explicit flags always win over the config file.
181
+
182
+ Current model presets:
183
+
184
+ - OpenAI `default`: `gpt-5-mini`
185
+ - OpenAI `pro`: `gpt-5.4`
186
+ - Gemini `default`: `gemini-3-flash-preview`
187
+ - Gemini `pro`: `gemini-3.1-pro-preview`
188
+
189
+ ## Usage
190
+
191
+ Basic usage:
192
+
193
+ ```bash
194
+ prgen
195
+ ```
196
+
197
+ Pick a different base:
198
+
199
+ ```bash
200
+ prgen --base main
201
+ ```
202
+
203
+ Run against another repository:
204
+
205
+ ```bash
206
+ prgen -C ~/src/my-project
207
+ ```
208
+
209
+ Override the model directly:
210
+
211
+ ```bash
212
+ prgen --provider openai --model gpt-5.4
213
+ prgen --provider gemini --model gemini-3.1-pro-preview
214
+ prgen --provider ollama --model mistral-small3.1
215
+ ```
216
+
217
+ Add extra context:
218
+
219
+ ```bash
220
+ prgen --context "Focus on customer-facing impact and rollout notes."
221
+ ```
222
+
223
+ ## Behavior Notes
224
+
225
+ - prgen validates that `--base` resolves before generating anything
226
+ - if there are no commits and no file changes vs the base ref, prgen exits with an error
227
+ - when `--provider ollama --pull` is used, prgen can download the model automatically
228
+ - when stderr is a TTY, loading states and Ollama downloads use Rich UI output
229
+
230
+ ## Development
231
+
232
+ Install local dependencies:
233
+
234
+ ```bash
235
+ uv sync
236
+ ```
237
+
238
+ Format and lint:
239
+
240
+ ```bash
241
+ uv run ruff format .
242
+ uv run ruff check .
243
+ ```
244
+
245
+ Run from the repo without installing globally:
246
+
247
+ ```bash
248
+ uv run prgen --help
249
+ ```
250
+
251
+ Install the local checkout as a global tool:
252
+
253
+ ```bash
254
+ uv tool install .
255
+ # or
256
+ pipx install .
257
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "prgen-cli"
3
- version = "0.2.5"
3
+ version = "0.3.0"
4
4
  description = "Generate PR titles and descriptions from git diff"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -18,6 +18,7 @@ classifiers = [
18
18
  ]
19
19
  dependencies = [
20
20
  "google-genai>=1.70.0",
21
+ "ollama>=0.6.1",
21
22
  "openai>=2.30.0",
22
23
  "rich>=14.3.3",
23
24
  "typer>=0.24.1",
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Literal
6
6
 
7
- Backend = Literal["openai", "gemini"]
7
+ Backend = Literal["openai", "gemini", "ollama"]
8
8
 
9
9
 
10
10
  def _trim(msg: str, max_len: int = 220) -> str:
@@ -18,7 +18,27 @@ def format_provider_error(exc: BaseException, *, backend: Backend) -> str:
18
18
  """Map SDK exceptions to a short stderr-safe line (no traceback)."""
19
19
  if backend == "openai":
20
20
  return _openai_user_message(exc)
21
- return _gemini_user_message(exc)
21
+ if backend == "gemini":
22
+ return _gemini_user_message(exc)
23
+ return _ollama_user_message(exc)
24
+
25
+
26
+ def _ollama_user_message(exc: BaseException) -> str:
27
+ try:
28
+ from ollama import RequestError, ResponseError
29
+ except ImportError:
30
+ return f"Ollama: {_trim(str(exc))}"
31
+
32
+ if isinstance(exc, RequestError):
33
+ return f"Ollama: request failed — is `ollama serve` running? {_trim(exc.error)}"
34
+ if isinstance(exc, ResponseError):
35
+ if exc.status_code == 404:
36
+ return (
37
+ "Ollama: model not found — run `ollama pull <name>`, fix --model, "
38
+ "or retry with --pull."
39
+ )
40
+ return f"Ollama: {_trim(str(exc))}"
41
+ return f"Ollama: {_trim(str(exc))}"
22
42
 
23
43
 
24
44
  def _openai_user_message(exc: BaseException) -> str: