mirror of
https://github.com/prdlk/gh-commit.git
synced 2026-09-16 23:16:25 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ab62dd347 | ||
|
|
d81fc02693 | ||
|
|
0acee0a694 | ||
|
|
3086dac5d6 | ||
|
|
f1302fd1ec | ||
|
|
ae36a7052d | ||
|
|
9647c854c9 |
@@ -1,2 +1 @@
|
|||||||
/.omc
|
|
||||||
/__pycache__
|
/__pycache__
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Prad
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
# gh-commit
|
# gh-commit
|
||||||
|
|
||||||
AI-powered scoped git commits. Groups changes by project area, generates commit messages with `crush run`, and pushes — all in one command.
|
AI-powered scoped git commits as a GitHub CLI extension, driven by the
|
||||||
|
[Crush](https://github.com/charmbracelet/crush) CLI. Scopes map Conventional
|
||||||
|
Commit scope names to path prefixes. They are generated from the repository
|
||||||
|
file tree, stored in a local DuckDB database, and auto-regenerate whenever
|
||||||
|
`.gitignore` changes. Changed files are grouped by scope and committed one
|
||||||
|
scope at a time with generated `type(scope): message` subjects.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -14,61 +19,31 @@ gh extension install prdlk/gh-commit
|
|||||||
- [Crush](https://github.com/charmbracelet/crush) — non-interactive AI runner
|
- [Crush](https://github.com/charmbracelet/crush) — non-interactive AI runner
|
||||||
- `GROQ_API_KEY` — authenticates the default Groq model
|
- `GROQ_API_KEY` — authenticates the default Groq model
|
||||||
|
|
||||||
By default, gh-commit uses Groq's `openai/gpt-oss-120b`. Override the model with `GH_COMMIT_CRUSH_MODEL`.
|
By default, gh-commit uses Groq's `openai/gpt-oss-120b` via the bundled `crush-provider` config. Override the model with `GH_COMMIT_CRUSH_MODEL`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Initialize scopes for your repo (uses Crush to analyze structure)
|
cd your-repo
|
||||||
gh commit init
|
gh commit init # generate scopes for this repo
|
||||||
|
gh commit # commit changes grouped by scope
|
||||||
# Commit changes grouped by scope
|
|
||||||
gh commit
|
|
||||||
|
|
||||||
# Auto-confirm + auto-push
|
|
||||||
gh commit --auto --push
|
|
||||||
|
|
||||||
# Manually refresh scopes after structural changes
|
|
||||||
gh commit refresh
|
|
||||||
|
|
||||||
# Sync scopes as GitHub labels
|
|
||||||
gh commit sync
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## How it works
|
|
||||||
|
|
||||||
1. **`gh commit init`** — `crush run` analyzes your repo structure and generates scope definitions (e.g., `core → src/`, `docs → docs/, README.md`, `ci → .github/workflows/`)
|
|
||||||
2. **`gh commit`** — Groups dirty files by scope, sends each staged diff to `crush run`, and commits each group separately
|
|
||||||
3. **Auto-refresh** — Whenever your `.gitignore` changes, scopes are automatically regenerated before committing (a content hash of `.gitignore` is tracked per repo)
|
|
||||||
4. Remaining unscoped files are handled in a final pass
|
|
||||||
5. Unpushed commits are offered for push
|
|
||||||
|
|
||||||
Scopes are stored in a local DuckDB database (`~/.local/share/gh-commit/gh-commit.db`) — no config files in your repo.
|
|
||||||
|
|
||||||
### Why Crush?
|
|
||||||
|
|
||||||
The former Mods roles now live directly in `smartcommit.py`, so gh-commit no longer depends on Mods configuration. Each generation invokes Crush's supported non-interactive mode with a self-contained prompt.
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Behavior |
|
||||||
|---------|-------------|
|
|---|---|
|
||||||
| `gh commit` | Commit changes grouped by scope |
|
| `gh commit` | Full scoped-commit flow: group changed files by scope, generate a message per group, confirm, commit, offer to push |
|
||||||
| `gh commit init` | Generate scopes for current repo |
|
| `gh commit init` | Generate scopes from the file tree via Crush; migrates legacy configs; confirms overwrite |
|
||||||
| `gh commit refresh` | Update scopes from current structure |
|
| `gh commit refresh` | Show current scopes, regenerate with existing scopes as context, confirm apply |
|
||||||
| `gh commit sync` | Sync scopes → GitHub labels |
|
| `gh commit sync` | Create/update GitHub labels from scopes (color = first 6 hex chars of MD5 of the scope name) |
|
||||||
| `gh commit list` | List all configured repositories |
|
| `gh commit list` | Table of configured repositories: name, path, scope count |
|
||||||
| `gh commit remove` | Remove current repo from database |
|
| `gh commit remove` | Delete the current repo from the database after confirmation |
|
||||||
| `gh commit db-path` | Print database file path |
|
| `gh commit db-path` | Print the database file path |
|
||||||
| `gh commit version` | Print version |
|
| `gh commit version` | Print `gh-commit <version>` |
|
||||||
| `gh commit help` | Show help |
|
| `gh commit help` | Help, including the DB path and environment variable docs |
|
||||||
|
|
||||||
## Flags
|
Flags: `--auto` (skip confirmations), `--push` (auto-push).
|
||||||
|
|
||||||
| Flag | Description |
|
|
||||||
|------|-------------|
|
|
||||||
| `--auto` | Skip all confirmation prompts |
|
|
||||||
| `--push` | Auto-push after committing |
|
|
||||||
|
|
||||||
## Environment
|
## Environment
|
||||||
|
|
||||||
@@ -82,10 +57,35 @@ The former Mods roles now live directly in `smartcommit.py`, so gh-commit no lon
|
|||||||
| `GH_COMMIT_CRUSH_TIMEOUT` | Per-prompt timeout in seconds (default `120`) |
|
| `GH_COMMIT_CRUSH_TIMEOUT` | Per-prompt timeout in seconds (default `120`) |
|
||||||
| `GH_COMMIT_DEBUG=1` | Show scope-response parse diagnostics |
|
| `GH_COMMIT_DEBUG=1` | Show scope-response parse diagnostics |
|
||||||
|
|
||||||
## Migration
|
## Storage
|
||||||
|
|
||||||
Existing `.github/Repo.toml` or `.github/scopes.json` files are automatically detected and migrated to DuckDB on first run.
|
Scopes live in `${XDG_DATA_HOME:-~/.local/share}/gh-commit/gh-commit.db`
|
||||||
|
(DuckDB). Legacy `.github/Repo.toml` and `.github/scopes.json` files are
|
||||||
|
migrated automatically on first run (the source file is archived as
|
||||||
|
`*.migrated.<timestamp>`).
|
||||||
|
|
||||||
## License
|
## Manual acceptance
|
||||||
|
|
||||||
MIT
|
```sh
|
||||||
|
mkdir /tmp/accept && cd /tmp/accept && git init
|
||||||
|
mkdir -p src docs
|
||||||
|
echo 'package app' > src/app.go
|
||||||
|
echo '# Docs' > docs/README.md
|
||||||
|
gh commit init # scopes generated and saved
|
||||||
|
echo '// change' >> src/app.go
|
||||||
|
echo 'More docs' >> docs/README.md
|
||||||
|
gh commit # one commit per scope
|
||||||
|
git log --format='%s' # verify type(scope): message subjects
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
The extension is a bash launcher (`gh-commit`) that runs `smartcommit.py`
|
||||||
|
with `uv run --script`; uv resolves the inline dependencies (duckdb, rich,
|
||||||
|
questionary) automatically.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python -m py_compile smartcommit.py # syntax check
|
||||||
|
bash -n gh-commit # launcher check
|
||||||
|
./gh-commit version # smoke test
|
||||||
|
```
|
||||||
|
|||||||
Binary file not shown.
@@ -1,23 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# gh-commit launcher — runs the bundled Python implementation via uv.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# gh-commit: AI-powered scoped git commits (Crush for scopes and messages)
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
# Install: gh extension install prdlk/gh-commit
|
|
||||||
# Requires: uv (https://docs.astral.sh/uv) and the Crush CLI
|
|
||||||
# (https://github.com/charmbracelet/crush)
|
|
||||||
|
|
||||||
EXTENSION_DIR="$(cd "$(dirname "$0")" && pwd)"
|
if ! command -v uv >/dev/null 2>&1; then
|
||||||
SCRIPT="${EXTENSION_DIR}/smartcommit.py"
|
echo "gh-commit: 'uv' is required (https://docs.astral.sh/uv)" >&2
|
||||||
|
|
||||||
if ! command -v uv &>/dev/null; then
|
|
||||||
echo "error: 'uv' is required but not installed"
|
|
||||||
echo "install: curl -LsSf https://astral.sh/uv/install.sh | sh"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "${GH_COMMIT_CRUSH_CMD:-}" ]] && ! command -v crush &>/dev/null; then
|
exec uv run --script "$DIR/smartcommit.py" "$@"
|
||||||
echo "warning: 'crush' not found — gh-commit uses 'crush run' for scopes and commit messages."
|
|
||||||
echo "install Crush (https://github.com/charmbracelet/crush), or set GH_COMMIT_CRUSH_CMD."
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec uv run --script "${SCRIPT}" "$@"
|
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -54,7 +54,7 @@ AUTO_PUSH = os.environ.get("GH_COMMIT_PUSH", "0") == "1"
|
|||||||
NO_AUTO_REFRESH = os.environ.get("GH_COMMIT_NO_AUTO_REFRESH", "0") == "1"
|
NO_AUTO_REFRESH = os.environ.get("GH_COMMIT_NO_AUTO_REFRESH", "0") == "1"
|
||||||
DEBUG = os.environ.get("GH_COMMIT_DEBUG", "0") == "1"
|
DEBUG = os.environ.get("GH_COMMIT_DEBUG", "0") == "1"
|
||||||
|
|
||||||
VERSION = "2.0.0"
|
VERSION = "5.0.1"
|
||||||
|
|
||||||
|
|
||||||
# ── Helpers ───────────────────────────────────────────────────────────────────
|
# ── Helpers ───────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user