README.md

  1<!--
  2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  3
  4SPDX-License-Identifier: CC0-1.0
  5-->
  6
  7# formatted-commit
  8
  9[![REUSE status](https://api.reuse.software/badge/git.secluded.site/formatted-commit)](https://api.reuse.software/info/git.secluded.site/formatted-commit)
 10[![Go Report Card](https://goreportcard.com/badge/git.secluded.site/formatted-commit)](https://goreportcard.com/report/git.secluded.site/formatted-commit)
 11
 12CLI tool that produces commits following the Conventional Commits specification
 13through flags, made for LLMs and not really their operators (but I guess you can
 14use this directly if you want). Operators would likely prefer, as the author
 15does, [meteor](https://github.com/stefanlogue/meteor).
 16
 17I've found that LLMs consistently fail to
 18
 19- Format trailers correctly: they add too many newlines between trailers, which
 20  breaks tools like `git interpret-trailers`
 21- Include proper scope notation
 22- Follow the loose 50/72 subject/body standard held by projects like the Linux
 23  kernel. I try to stick to it, but LLMs writing badly-formatted commit messages
 24  means rewording work for me once they're done.
 25
 26`formatted-commit` enforces all of this. Where possible, we "correct" the
 27model's input. Where that's less possible, we error. For example, instead of
 28requiring the model wrap body text at 72 columns, we let it write whatever body
 29it wants and wrap it ourselves. We can't really fix the subject, so
 30`formatted-commit` emits an error when the subject is too long with clear
 31indication of where the 50-character cut-off is.
 32
 33## Installation
 34
 35As this is mostly meant for agentic coding tools, you'll need one. I like [Crush
 36💘](https://github.com/charmbracelet/crush) (and maintain [a
 37fork](https://git.secluded.site/crush)) or [OpenCode](https://opencode.ai/) as
 38the best more-open options and [Amp](https://ampcode.com/) as the overall best
 39option if you don't mind completely proprietary and paying for 100% of your API
 40usage.
 41
 42You need both the binary and the prompt. If you don't have the binary
 43when the model tries to use it, it's instructed to ask you to install
 44it using the appropriate command.
 45
 46### The binary
 47
 48- Using [bin](https://github.com/marcosnils/bin) (highly recommended
 49  because it's one tool to manage and update myriad CLI tools
 50  distributed as statically-linked binaries, like _formatted-commit_)
 51  ```bash
 52  bin install goinstall://git.secluded.site/formatted-commit@latest
 53  ```
 54- Using the [go toolchain](https://go.dev/dl) (requires tracking updates
 55  manually, though you can check with `formatted-commit upgrade` and
 56  apply with `formatted-commit upgrade -a`)
 57  ```bash
 58  go install git.secluded.site/formatted-commit@latest
 59  ```
 60
 61### The prompt
 62
 63Copy/paste this into wherever you tell your models how to write commits. For
 64Crush, that might be `~/.config/crush/CRUSH.md` or `./CRUSH.md` in a repo. For
 65[my Crush fork](https://git.secluded.site/crush) and Amp, that's
 66`~/.config/AGENTS.md`. Look up where your tool checks for rules files and put
 67this in a section like `## Creating git commits` or something.
 68
 69<details>
 70<summary>Using <code>bin</code></summary>
 71
 72```markdown
 73Create/amend commits exclusively using `formatted-commit`. Try to use it normally, but if it's not in my PATH, ask me to `bin install goinstall://git.secluded.site/formatted-commit@latest`. It has no sub-commands and the following options:
 74<formatted-commit_flags>
 75-t --type Commit type (required)
 76-s --scope Commit scope (optional)
 77-B --breaking Mark as breaking change (optional)
 78-m --message Commit message (required)
 79-b --body Commit body (optional)
 80-T --trailer Trailer in 'Sentence-case-key: value' format (optional, repeatable)
 81-a --add Stage all modified files before committing (optional)
 82--amend Amend the previous commit (optional)
 83-h --help
 84</formatted-commit_flags>
 85<formatted-commit_example>
 86formatted-commit -t feat -s "web/git-bug" -m "do a fancy new thing" -T "Assisted-by: GLM 4.6 via Crush" -b "$(cat <<'EOF'
 87Multi-line
 88
 89- Body
 90- Here
 91
 92EOF
 93)"
 94</formatted-commit_example>
 95```
 96
 97</details>
 98
 99<details>
100<summary>Using <code>go install</code></summary>
101
102```markdown
103Create/amend commits exclusively using `formatted-commit`. Try to use it normally, but if it's not in my PATH, ask me to `go install git.secluded.site/formatted-commit@latest`. It has no sub-commands and the following options:
104<formatted-commit_flags>
105-t --type Commit type (required)
106-s --scope Commit scope (optional)
107-B --breaking Mark as breaking change (optional)
108-m --message Commit message (required)
109-b --body Commit body (optional)
110-T --trailer Trailer in 'Sentence-case-key: value' format (optional, repeatable)
111-a --add Stage all modified files before committing (optional)
112--amend Amend the previous commit (optional)
113-h --help
114</formatted-commit_flags>
115<formatted-commit_example>
116formatted-commit -t feat -s "web/git-bug" -m "do a fancy new thing" -T "Assisted-by: GLM 4.6 via Crush" -b "$(cat <<'EOF'
117Multi-line
118
119- Body
120- Here
121
122EOF
123)"
124</formatted-commit_example>
125```
126
127</details>
128
129## Contributions
130
131Patch requests are in [amolith/llm-projects] on [pr.pico.sh]. You don't need a
132new account to contribute, you don't need to fork this repo, you don't need to
133fiddle with `git send-email`, you don't need to faff with your email client to
134get `git request-pull` working...
135
136You just need:
137
138- Git
139- SSH
140- An SSH key
141
142```sh
143# Clone this repo, make your changes, and commit them
144# Create a new patch request with
145git format-patch origin/main --stdout | ssh pr.pico.sh pr create amolith/llm-projects
146# After potential feedback, submit a revision to an existing patch request with
147git format-patch origin/main --stdout | ssh pr.pico.sh pr add {prID}
148# List patch requests
149ssh pr.pico.sh pr ls amolith/llm-projects
150```
151
152See "How do Patch Requests work?" on [pr.pico.sh]'s home page for a more
153complete example workflow.
154
155[amolith/llm-projects]: https://pr.pico.sh/r/amolith/llm-projects
156[pr.pico.sh]: https://pr.pico.sh
157
158## Usage
159
160```text
161$ formatted-commit -h
162
163  formatted-commit helps you create well-formatted Git commits that follow
164  the Conventional Commits specification with proper subject length validation,
165  body wrapping, and trailer formatting.
166
167  USAGE
168
169    formatted-commit [command] [--flags]
170
171  EXAMPLES
172
173    # With Assisted-by
174    formatted-commit -t feat -m "do a thing" -T "Assisted-by: GLM 4.6 via Crush"
175
176    # Breaking change with longer body
177    formatted-commit -t feat -m "do a thing that borks a thing" -B -b "$(cat <<'EOF'
178    Multi-line
179    - Body
180    - Here
181
182    This is what borked because of new shiny, this is how migrate
183    EOF
184    )"
185
186    # Including scope for more precise changes
187    formatted-commit -t refactor -s "web/git-bug" -m "fancy shmancy" \
188      -b "Had to do a weird thing because..."
189
190    # Check for upgrades
191    formatted-commit upgrade
192
193    # Then apply
194    formatted-commit upgrade -a
195
196  COMMANDS
197
198    help [command]     Help about any command
199    upgrade [--flags]  Check for and apply updates
200
201  FLAGS
202
203    -a --add           Stage all modified files before committing (optional)
204       --amend         Amend the previous commit (optional)
205    -b --body          Commit body (optional)
206    -B --breaking      Mark as breaking change (optional)
207    -h --help          Help for formatted-commit
208    -m --message       Commit message (required)
209    -s --scope         Commit scope (optional)
210    -T --trailer       Trailer in 'Sentence-case-key: value' format (optional, repeatable)
211    -t --type          Commit type (required)
212    -v --version       Version for formatted-commit
213```