commitstash 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.
- commitstash-0.3.0/.github/workflows/ci.yml +37 -0
- commitstash-0.3.0/.github/workflows/publish.yml +41 -0
- commitstash-0.3.0/.gitignore +24 -0
- commitstash-0.3.0/.pre-commit-config.yaml +12 -0
- commitstash-0.3.0/AGENTS.md +53 -0
- commitstash-0.3.0/CHANGELOG.md +43 -0
- commitstash-0.3.0/LICENSE +21 -0
- commitstash-0.3.0/PKG-INFO +429 -0
- commitstash-0.3.0/README.md +401 -0
- commitstash-0.3.0/autocommit/__init__.py +1 -0
- commitstash-0.3.0/autocommit/changelog.py +86 -0
- commitstash-0.3.0/autocommit/cli.py +777 -0
- commitstash-0.3.0/autocommit/config.py +35 -0
- commitstash-0.3.0/autocommit/explain.py +43 -0
- commitstash-0.3.0/autocommit/git.py +167 -0
- commitstash-0.3.0/autocommit/llm.py +298 -0
- commitstash-0.3.0/autocommit/pr.py +78 -0
- commitstash-0.3.0/autocommit/providers.py +119 -0
- commitstash-0.3.0/autocommit/review.py +83 -0
- commitstash-0.3.0/autocommit/secrets.py +85 -0
- commitstash-0.3.0/autocommit/split.py +106 -0
- commitstash-0.3.0/pyproject.toml +47 -0
- commitstash-0.3.0/tests/__init__.py +0 -0
- commitstash-0.3.0/tests/conftest.py +14 -0
- commitstash-0.3.0/tests/test_changelog.py +48 -0
- commitstash-0.3.0/tests/test_cli.py +135 -0
- commitstash-0.3.0/tests/test_config.py +38 -0
- commitstash-0.3.0/tests/test_explain.py +16 -0
- commitstash-0.3.0/tests/test_git.py +83 -0
- commitstash-0.3.0/tests/test_llm.py +89 -0
- commitstash-0.3.0/tests/test_pr.py +42 -0
- commitstash-0.3.0/tests/test_review.py +40 -0
- commitstash-0.3.0/tests/test_secrets.py +65 -0
- commitstash-0.3.0/tests/test_split.py +85 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
|
|
29
|
+
- name: Lint with ruff
|
|
30
|
+
run: ruff check .
|
|
31
|
+
|
|
32
|
+
- name: Type-check with mypy
|
|
33
|
+
if: matrix.python-version == '3.12'
|
|
34
|
+
run: mypy autocommit/
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: pytest -q
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- name: Set up Python
|
|
14
|
+
uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
|
|
18
|
+
- name: Build sdist and wheel
|
|
19
|
+
run: |
|
|
20
|
+
python -m pip install --upgrade pip build
|
|
21
|
+
python -m build
|
|
22
|
+
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment: pypi
|
|
32
|
+
permissions:
|
|
33
|
+
id-token: write # OIDC token for PyPI trusted publishing — no API key
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/download-artifact@v4
|
|
36
|
+
with:
|
|
37
|
+
name: dist
|
|
38
|
+
path: dist/
|
|
39
|
+
|
|
40
|
+
- name: Publish to PyPI
|
|
41
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.eggs/
|
|
8
|
+
|
|
9
|
+
# Environments
|
|
10
|
+
venv/
|
|
11
|
+
.venv/
|
|
12
|
+
env/
|
|
13
|
+
|
|
14
|
+
# Tooling caches
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# OS / editor
|
|
22
|
+
.DS_Store
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v5.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-added-large-files
|
|
9
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
10
|
+
rev: v0.8.4
|
|
11
|
+
hooks:
|
|
12
|
+
- id: ruff
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Repository Guidelines
|
|
2
|
+
|
|
3
|
+
## Project Structure & Module Organization
|
|
4
|
+
|
|
5
|
+
This repository contains a small Python CLI package for generating commit messages from staged diffs.
|
|
6
|
+
|
|
7
|
+
- `autocommit/cli.py` defines the Click command group, interactive prompts, and subcommands.
|
|
8
|
+
- `autocommit/git.py` wraps git operations such as reading staged files and creating commits.
|
|
9
|
+
- `autocommit/llm.py` builds prompts and calls Anthropic or OpenAI providers.
|
|
10
|
+
- `autocommit/config.py` loads and saves user preferences in `~/.autocommit/config.json`.
|
|
11
|
+
- `README.md` documents user-facing installation, setup, and CLI usage.
|
|
12
|
+
- `pyproject.toml` contains package metadata, dependencies, console script wiring, and Ruff settings.
|
|
13
|
+
|
|
14
|
+
There is no committed `tests/` directory yet; add one with new tests.
|
|
15
|
+
|
|
16
|
+
## Build, Test, and Development Commands
|
|
17
|
+
|
|
18
|
+
Use a virtual environment for local work:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
python -m venv .venv
|
|
22
|
+
source .venv/bin/activate
|
|
23
|
+
pip install -e ".[dev]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Common commands:
|
|
27
|
+
|
|
28
|
+
- `autocommit version` verifies the editable console script is installed.
|
|
29
|
+
- `pytest` runs the test suite once tests exist.
|
|
30
|
+
- `ruff check .` runs lint checks with the repository line length setting.
|
|
31
|
+
- `python -m build` builds distribution artifacts, if the `build` package is installed.
|
|
32
|
+
|
|
33
|
+
For manual testing, stage a small change in a disposable git repo and run `autocommit`.
|
|
34
|
+
|
|
35
|
+
## Coding Style & Naming Conventions
|
|
36
|
+
|
|
37
|
+
Target Python 3.9+. Use 4-space indentation, clear function names, and focused modules. Private helpers use a leading underscore, for example `_build_prompt` and `_do_commit`.
|
|
38
|
+
|
|
39
|
+
Keep lines at or below 100 characters per `[tool.ruff]`. Prefer standard library facilities before adding dependencies. Keep CLI output consistent with the existing Click and Rich style.
|
|
40
|
+
|
|
41
|
+
## Testing Guidelines
|
|
42
|
+
|
|
43
|
+
Use `pytest` for new tests. Place tests under `tests/` and name files `test_<module>.py`, such as `tests/test_config.py`. Prefer unit tests for prompt construction, config behavior, and git wrapper error handling. Mock network clients and subprocess calls; do not require real API keys or commits.
|
|
44
|
+
|
|
45
|
+
## Commit & Pull Request Guidelines
|
|
46
|
+
|
|
47
|
+
Recent history uses Conventional Commit-style messages, for example `docs: add README` and `feat: initial autocommit CLI`. Continue using concise prefixes such as `feat:`, `fix:`, `docs:`, `test:`, and `chore:`.
|
|
48
|
+
|
|
49
|
+
Pull requests should include a short summary, testing performed, and any user-facing CLI behavior changes. Link related issues when available. Include terminal output only when it clarifies interactive CLI changes.
|
|
50
|
+
|
|
51
|
+
## Security & Configuration Tips
|
|
52
|
+
|
|
53
|
+
Never commit API keys or generated local config. `ANTHROPIC_API_KEY` and `OPENAI_API_KEY` must stay in environment variables. Do not persist secrets in `~/.autocommit/config.json` or test fixtures.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.3.0 (2026-07-18)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- initial autocommit CLI — AI-powered git commit message generator
|
|
8
|
+
- **secrets:** add regex-based secret scanner
|
|
9
|
+
- **llm:** add ollama provider and shared completion dispatch
|
|
10
|
+
- **review:** add staged-diff code review module
|
|
11
|
+
- **pr:** add PR description writer and branch helpers
|
|
12
|
+
- **cli:** wire scan, review, and pr commands with secret commit gate
|
|
13
|
+
- **git:** add history, tag, and staging helpers
|
|
14
|
+
- **split:** cluster staged changes into atomic commits
|
|
15
|
+
- **changelog:** generate changelogs from conventional commits
|
|
16
|
+
- **explain:** plain-language explanation of the staged diff
|
|
17
|
+
- **cli:** wire split, explain, and changelog commands
|
|
18
|
+
|
|
19
|
+
### Refactoring
|
|
20
|
+
|
|
21
|
+
- **llm:** extract pluggable provider registry
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
- add README
|
|
26
|
+
- add repository guidelines
|
|
27
|
+
- rewrite README for secret scanning, review, pr, and ollama
|
|
28
|
+
- document split, explain, changelog, and custom providers
|
|
29
|
+
|
|
30
|
+
### Tests
|
|
31
|
+
|
|
32
|
+
- add pytest suite for scanner, review, pr, config, git, and CLI
|
|
33
|
+
|
|
34
|
+
### CI
|
|
35
|
+
|
|
36
|
+
- add GitHub Actions workflow for lint and tests
|
|
37
|
+
|
|
38
|
+
### Chores
|
|
39
|
+
|
|
40
|
+
- add .gitignore and LICENSE, untrack compiled artifacts
|
|
41
|
+
- bump version to 0.2.0 and fix project URLs
|
|
42
|
+
- add mypy and pre-commit tooling
|
|
43
|
+
- rename package to commitpilot, add PyPI publish workflow
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Surya Pratap Singh
|
|
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.
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: commitstash
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: AI-powered git commit message generator — reads your staged diff, writes the commit for you
|
|
5
|
+
Project-URL: Homepage, https://github.com/suryaSPS/autocommit
|
|
6
|
+
Project-URL: Issues, https://github.com/suryaSPS/autocommit/issues
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: ai,cli,commit,developer-tools,git
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Requires-Dist: anthropic>=0.40.0
|
|
18
|
+
Requires-Dist: click>=8.1
|
|
19
|
+
Requires-Dist: rich>=13.0
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
22
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
24
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
25
|
+
Provides-Extra: openai
|
|
26
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
<div align="center">
|
|
30
|
+
|
|
31
|
+
# autocommit
|
|
32
|
+
|
|
33
|
+
**AI-powered git commit message generator — reads your staged diff, writes the commit for you**
|
|
34
|
+
|
|
35
|
+
[](https://www.python.org/)
|
|
36
|
+
[](./LICENSE)
|
|
37
|
+
[](https://pypi.org/project/commitstash/)
|
|
38
|
+
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## The Problem
|
|
44
|
+
|
|
45
|
+
Writing good commit messages is tedious. Most developers either:
|
|
46
|
+
- Write vague messages like `fix bug` or `update stuff`
|
|
47
|
+
- Spend more time on the message than the actual change
|
|
48
|
+
- Skip conventions entirely under time pressure
|
|
49
|
+
|
|
50
|
+
## The Solution
|
|
51
|
+
|
|
52
|
+
`autocommit` reads your staged diff and generates a precise, conventional commit message using Claude or GPT — in under 3 seconds. No API key? Run it fully offline with `--no-ai` and it builds a message straight from the diff, or point it at a local model with Ollama.
|
|
53
|
+
|
|
54
|
+
It does more than messages:
|
|
55
|
+
|
|
56
|
+
- **Blocks secrets** — every commit is scanned for API keys, tokens, and credentials in your staged changes. Leaks are stopped before they land.
|
|
57
|
+
- **Reviews your diff** — `autocommit review` flags bugs and issues before you commit.
|
|
58
|
+
- **Writes your PR** — `autocommit pr` drafts a title and description from your branch's commits and diff.
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
git add orders/views.py orders/serializers.py
|
|
62
|
+
|
|
63
|
+
autocommit
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Staged (2 files):
|
|
68
|
+
· orders/views.py
|
|
69
|
+
· orders/serializers.py
|
|
70
|
+
|
|
71
|
+
╭─ Suggested commit message ────────────────────────────────────╮
|
|
72
|
+
│ feat(orders): add bulk export endpoint with date range filters │
|
|
73
|
+
╰───────────────────────────────────────────────────────────────╯
|
|
74
|
+
|
|
75
|
+
[Enter] commit e edit r regenerate q quit
|
|
76
|
+
>
|
|
77
|
+
✓ Committed successfully
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Installation
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install commitstash
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Setup
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Anthropic Claude (default)
|
|
92
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
93
|
+
|
|
94
|
+
# Or OpenAI
|
|
95
|
+
export OPENAI_API_KEY=sk-...
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Add the export to your `~/.zshrc` or `~/.bashrc` so it persists.
|
|
99
|
+
|
|
100
|
+
**No API key?** Skip setup entirely and use offline mode — see [No-AI mode](#no-ai-offline-mode) below.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Quick Start
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Stage your changes
|
|
108
|
+
git add <files>
|
|
109
|
+
|
|
110
|
+
# Generate and commit
|
|
111
|
+
autocommit
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
That's it. Press Enter to accept, `e` to edit, `r` to regenerate, `q` to quit.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Usage
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Stage everything, then generate
|
|
122
|
+
autocommit -a
|
|
123
|
+
|
|
124
|
+
# Auto-accept without prompting (CI / hooks)
|
|
125
|
+
autocommit -a -y
|
|
126
|
+
|
|
127
|
+
# Change style for one commit
|
|
128
|
+
autocommit --style simple
|
|
129
|
+
autocommit --style angular
|
|
130
|
+
|
|
131
|
+
# Add emoji prefix (✨ feat, 🐛 fix, ♻️ refactor...)
|
|
132
|
+
autocommit --emoji
|
|
133
|
+
|
|
134
|
+
# Include a commit body explaining WHY
|
|
135
|
+
autocommit --body
|
|
136
|
+
|
|
137
|
+
# Switch provider for one commit
|
|
138
|
+
autocommit --provider openai
|
|
139
|
+
|
|
140
|
+
# No API key — generate offline from the diff
|
|
141
|
+
autocommit --no-ai
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## No-AI (offline) mode
|
|
147
|
+
|
|
148
|
+
Don't have an API key, working offline, or just want zero-cost commits? Add `--no-ai`
|
|
149
|
+
and `autocommit` builds the message locally by analyzing your staged diff — no network,
|
|
150
|
+
no key, no SDK required.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
autocommit --no-ai # generate offline
|
|
154
|
+
autocommit --no-ai -a -y # stage all, offline, auto-accept
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
It inspects the diff to pick a sensible message:
|
|
158
|
+
|
|
159
|
+
| What it detects | Example output |
|
|
160
|
+
|---|---|
|
|
161
|
+
| Brand-new file(s) | `feat(auth): add login` |
|
|
162
|
+
| Docs / README changes | `docs: update README` |
|
|
163
|
+
| Test files | `test(tests): add test_llm` |
|
|
164
|
+
| Config / build files | `chore: update pyproject` |
|
|
165
|
+
| Mostly deletions | `refactor(api): remove legacy client` |
|
|
166
|
+
| File removals | `chore: remove old_helper` |
|
|
167
|
+
|
|
168
|
+
The type (`feat`/`fix`/`docs`/`test`/`chore`/`refactor`), scope (derived from the common
|
|
169
|
+
directory), and emoji all respect your configured style. It's a heuristic, not a mind
|
|
170
|
+
reader — press `e` to tweak anything before committing.
|
|
171
|
+
|
|
172
|
+
Make it the default so you never pass the flag:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
autocommit configure # choose "local" when prompted for provider
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Secret Scanning
|
|
181
|
+
|
|
182
|
+
Before every commit, `autocommit` scans your **staged changes** for secrets — AWS keys,
|
|
183
|
+
GitHub tokens, Anthropic/OpenAI keys, Slack/Stripe/Google keys, private key blocks, JWTs,
|
|
184
|
+
and hardcoded `password`/`api_key`/`token` assignments. If it finds one, the commit is
|
|
185
|
+
blocked and the finding is shown with the secret redacted:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
╭──────────────── Secrets detected (1) ────────────────╮
|
|
189
|
+
│ AWS access key ID config.py:12 │
|
|
190
|
+
│ AKIAIOSF…MPLE │
|
|
191
|
+
╰──────────────────────────────────────────────────────╯
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Only **added** lines are scanned, so pre-existing secrets in unrelated files don't block you.
|
|
195
|
+
Obvious placeholders (`your_key_here`, `xxxx`, `${VAR}`, `changeme`) are ignored.
|
|
196
|
+
|
|
197
|
+
Run the scan on its own — it exits non-zero when anything is found, so it drops straight into
|
|
198
|
+
a pre-commit hook or CI step:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
autocommit scan
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Turn the automatic commit-time gate off in `autocommit configure` (or set `"scan_secrets": false`
|
|
205
|
+
in your config).
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Review
|
|
210
|
+
|
|
211
|
+
Get a review of your staged diff before you commit:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
autocommit review # AI review with your configured provider
|
|
215
|
+
autocommit review --no-ai # offline pattern checks only
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
With an AI provider it looks for bugs, security issues, and clear mistakes in the changed
|
|
219
|
+
lines. Offline mode is deterministic — it flags leftover debug statements (`print`,
|
|
220
|
+
`console.log`, `breakpoint()`), merge-conflict markers, and new `TODO`/`FIXME` comments —
|
|
221
|
+
and tells you it isn't a correctness review.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Pull Requests
|
|
226
|
+
|
|
227
|
+
Draft a PR title and description from the commits and diff on your current branch:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
autocommit pr # base branch autodetected (origin/HEAD, then main/master)
|
|
231
|
+
autocommit pr --base develop # compare against a specific branch
|
|
232
|
+
autocommit pr --no-ai # assemble from commit subjects, no API key
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Output is a title plus a `## Summary` / `## Changes` / `## Testing` markdown body — paste it
|
|
236
|
+
straight into GitHub.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Commit Styles
|
|
241
|
+
|
|
242
|
+
| Style | Example output |
|
|
243
|
+
|---|---|
|
|
244
|
+
| `conventional` (default) | `feat(auth): add JWT refresh token rotation` |
|
|
245
|
+
| `angular` | `fix(orders): handle null warehouse on bulk export` |
|
|
246
|
+
| `simple` | `Fix null check in order serializer` |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Configure
|
|
251
|
+
|
|
252
|
+
Run the interactive setup to save your preferences:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
autocommit configure
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Preferences are saved to `~/.autocommit/config.json`.
|
|
259
|
+
API keys are **never** written to disk — always read from environment variables.
|
|
260
|
+
|
|
261
|
+
<details>
|
|
262
|
+
<summary>Manual config (~/.autocommit/config.json)</summary>
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"provider": "anthropic",
|
|
267
|
+
"style": "conventional",
|
|
268
|
+
"include_scope": true,
|
|
269
|
+
"include_body": false,
|
|
270
|
+
"emoji": false,
|
|
271
|
+
"max_diff_lines": 500,
|
|
272
|
+
"scan_secrets": true,
|
|
273
|
+
"ollama_model": "llama3.2",
|
|
274
|
+
"ollama_host": "http://localhost:11434"
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
</details>
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Providers
|
|
283
|
+
|
|
284
|
+
| Provider | Default Model | Env Var |
|
|
285
|
+
|---|---|---|
|
|
286
|
+
| `anthropic` (default) | `claude-opus-4-8` | `ANTHROPIC_API_KEY` |
|
|
287
|
+
| `openai` | `gpt-4o-mini` | `OPENAI_API_KEY` |
|
|
288
|
+
| `ollama` | `llama3.2` (local LLM) | none |
|
|
289
|
+
| `local` | — (offline heuristic) | none |
|
|
290
|
+
|
|
291
|
+
Switch permanently:
|
|
292
|
+
```bash
|
|
293
|
+
autocommit configure # select openai when prompted
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Switch for one commit:
|
|
297
|
+
```bash
|
|
298
|
+
autocommit -p openai
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Ollama (local LLM)
|
|
302
|
+
|
|
303
|
+
Run a real model on your own machine — no API key, no network calls off-box:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
ollama serve
|
|
307
|
+
ollama pull llama3.2
|
|
308
|
+
|
|
309
|
+
autocommit -p ollama # one commit
|
|
310
|
+
autocommit configure # choose "ollama"; set model + host
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Model and host are configurable (`ollama_model`, `ollama_host`).
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Git Hook
|
|
318
|
+
|
|
319
|
+
Install `autocommit` as a `prepare-commit-msg` hook so every `git commit` auto-generates a message:
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
autocommit install-hook
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
To uninstall:
|
|
326
|
+
```bash
|
|
327
|
+
rm .git/hooks/prepare-commit-msg
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Commit Splitting
|
|
333
|
+
|
|
334
|
+
Staged everything at once? `autocommit split` clusters the staged files into
|
|
335
|
+
logical commits — source changes by scope, then tests, docs, and config — and
|
|
336
|
+
commits each group with its own generated message:
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
git add .
|
|
340
|
+
autocommit split
|
|
341
|
+
|
|
342
|
+
Proposed split (3 commits, AI grouping)
|
|
343
|
+
|
|
344
|
+
Commit 1 — auth refactor
|
|
345
|
+
· auth/views.py
|
|
346
|
+
· auth/models.py
|
|
347
|
+
Commit 2 — test changes
|
|
348
|
+
· tests/test_auth.py
|
|
349
|
+
Commit 3 — documentation
|
|
350
|
+
· README.md
|
|
351
|
+
|
|
352
|
+
Create these commits? [y/N] > y
|
|
353
|
+
✓ 1/3 refactor(auth): move JWT validation into middleware
|
|
354
|
+
✓ 2/3 test(auth): cover middleware token validation
|
|
355
|
+
✓ 3/3 docs: document the new auth flow
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
AI providers propose the grouping from the diff; the response is strictly
|
|
359
|
+
validated (every staged file in exactly one group) and falls back to
|
|
360
|
+
deterministic grouping otherwise — `--no-ai` uses it directly. Splitting is
|
|
361
|
+
file-level, so a single file's hunks never end up divided across commits.
|
|
362
|
+
Files with both staged *and* unstaged edits abort the split rather than
|
|
363
|
+
silently dragging unstaged work into a commit.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Explain & Changelog
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
# Plain-language explanation of the staged diff — what, why, impact, risk
|
|
371
|
+
autocommit explain
|
|
372
|
+
|
|
373
|
+
# Changelog section from conventional commits since the last tag
|
|
374
|
+
autocommit changelog
|
|
375
|
+
|
|
376
|
+
# ...or a labelled release, prepended to CHANGELOG.md
|
|
377
|
+
autocommit changelog --label v0.3.0 --write
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
`changelog` is deliberately deterministic — the same history always produces
|
|
381
|
+
the same changelog, so it needs no API key and works in CI.
|
|
382
|
+
|
|
383
|
+
`autocommit` also reads your recent commit history when generating messages,
|
|
384
|
+
so suggestions match the tone and scope conventions your repo already uses.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Custom Providers
|
|
389
|
+
|
|
390
|
+
Backends are pluggable. Anything that can complete a prompt can drive every
|
|
391
|
+
feature — subclass, register, done:
|
|
392
|
+
|
|
393
|
+
```python
|
|
394
|
+
from autocommit.providers import LLMProvider, register
|
|
395
|
+
|
|
396
|
+
class GroqProvider(LLMProvider):
|
|
397
|
+
name = "groq"
|
|
398
|
+
|
|
399
|
+
def complete(self, prompt, config, max_tokens=1024):
|
|
400
|
+
... # call any API you like
|
|
401
|
+
|
|
402
|
+
register(GroqProvider())
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Commands
|
|
408
|
+
|
|
409
|
+
| Command | Description |
|
|
410
|
+
|---|---|
|
|
411
|
+
| `autocommit` | Generate from staged diff (interactive) |
|
|
412
|
+
| `autocommit -a` | Stage all changes, then generate |
|
|
413
|
+
| `autocommit -y` | Auto-accept first suggestion |
|
|
414
|
+
| `autocommit --no-ai` | Generate offline, no API key needed |
|
|
415
|
+
| `autocommit scan` | Scan staged changes for secrets (exits 1 on findings) |
|
|
416
|
+
| `autocommit review` | Review the staged diff for bugs and issues |
|
|
417
|
+
| `autocommit pr` | Draft a PR title and description for the branch |
|
|
418
|
+
| `autocommit split` | Split staged changes into a series of atomic commits |
|
|
419
|
+
| `autocommit explain` | Explain the staged diff: what, why, impact, risk |
|
|
420
|
+
| `autocommit changelog` | Generate a changelog from conventional commit history |
|
|
421
|
+
| `autocommit configure` | Interactive setup |
|
|
422
|
+
| `autocommit install-hook` | Install as git hook in current repo |
|
|
423
|
+
| `autocommit version` | Show version |
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## License
|
|
428
|
+
|
|
429
|
+
MIT
|