CLI that turns LLM input into well-formatted Conventional Commits
0

Configure Feed

Select the types of activity you want to include in your feed.

docs(agents): updoot

Amolith (Oct 21, 2025, 7:36 PM -0600) ae2e2e11 07346ae6

+44 -15
+44 -15
AGENTS.md
··· 10 10 11 11 ## Development Commands 12 12 13 + - **Default workflow**: `just` (runs fmt, lint, staticcheck, test, vuln, reuse) 13 14 - **Build**: `just build` (outputs binary as `formatted-commit`) 14 15 - **Run during development**: `just run [flags]` 15 - - **Format code**: `just fmt` 16 + - **Format code**: `just fmt` (uses gofumpt) 17 + - **Lint**: `just lint` (uses golangci-lint) 18 + - **Static analysis**: `just staticcheck` 19 + - **Vulnerability check**: `just vuln` (uses govulncheck) 20 + - **License compliance**: `just reuse` (REUSE specification) 21 + - **Test**: `just test` or `go test ./...` 22 + - **Single test**: `go test -v -run TestName ./...` (no tests exist yet) 16 23 - **Update dependencies**: `go mod tidy` 17 - - **Test**: `go test ./...` 18 24 19 25 Example usage: 20 26 ··· 27 33 This is a CLI tool that formats git commit messages according to Conventional Commits specification and pipes them directly to `git commit -F -`. It enforces: 28 34 29 35 1. Subject length: max 50 characters in format `type(scope): message` 30 - 2. Body wrapping: strictly 72 columns using Markdown formatter 36 + 2. Body wrapping: strictly 72 columns with hanging indents for bullets/numbered lists 31 37 3. Trailer validation: follows git's trailer specification 32 38 33 39 ## Architecture 34 40 35 - Single-file CLI application (`main.go`) using: 41 + Multi-file CLI application split by concern: 42 + 43 + - **main.go**: Cobra CLI setup, flag definitions, subject validation, orchestration, git command execution 44 + - **trailers.go**: Trailer validation and block building following git's RFC 822 folding specification 45 + - **wrapBody.go**: Body text sanitization and custom word-wrapping with hanging indent support 46 + 47 + Dependencies: 36 48 37 49 - **cobra**: CLI framework for flags and commands 38 - - **fang**: Charmbracelet's execution wrapper (provides version handling, etc.) 39 - - Future: Will need a Markdown formatter for body text (likely from Charmbracelet ecosystem based on dependencies) 50 + - **fang**: Charmbracelet's execution wrapper (version handling, etc.) 51 + - **bluemonday**: HTML/Markdown sanitization using UGCPolicy 52 + - **Custom word wrapping**: Pure-Go implementation for 72-column wrapping with hanging indents 40 53 41 54 ## Critical Implementation Details 42 55 ··· 48 61 49 62 ### Body Formatting 50 63 51 - The body (`-b` flag) must be: 64 + The body (`-b` flag) processing pipeline: 65 + 66 + 1. **Sanitization**: `bluemonday.UGCPolicy()` strips dangerous HTML/scripts while preserving basic formatting 67 + 2. **Line-by-line processing**: Each line is processed based on its type: 68 + - **Bullets** (`- ` or `* `): Wrapped with 2-space hanging indent for continuation lines 69 + - **Numbered lists** (`^\d+\.\s`): Wrapped with hanging indent matching the marker length (e.g., `1. `, `10. `) 70 + - **Plain text**: Standard word-wrap at 72 columns 71 + - **Blank lines**: Preserved as-is 72 + 3. **Word wrapping algorithm**: Greedy wrapping splits on word boundaries, never mid-word 73 + 4. **Hanging indent logic**: For bullets/numbered lists, first line gets the marker, continuation lines get spaces equal to marker width 74 + 5. **Spacing**: Body separated from subject by one blank line, from trailers by one blank line 52 75 53 - 1. Sanitised because it should only be basic text and bullets 54 - 2. Formatted as Markdown, properly wrapping bullets with hanging indents on 55 - following lines like this 56 - 3. Strictly wrapped to 72 columns using a pure-Go formatter 57 - 4. Separated from subject by one blank line 58 - 5. Separated from trailers by one blank line 76 + Example wrapped bullet: 77 + 78 + ``` 79 + - This is a long bullet point that exceeds 72 characters and will 80 + be wrapped with proper hanging indent alignment on continuation 81 + lines. 82 + ``` 59 83 60 84 ### Trailer Formatting (Critical) 61 85 ··· 79 103 80 104 ### Flag Nuance 81 105 106 + - `-t` / `--type`: Commit type (required) - e.g., `feat`, `fix`, `refactor` 107 + - `-m` / `--message`: Commit message (required) - the description after the colon 108 + - `-s` / `--scope`: Commit scope (optional) - goes in parentheses after type 82 109 - `-B` / `--breaking`: Boolean flag for breaking changes (adds `!` to subject) 83 - - `-b` / `--body`: String flag for commit body text 84 - - `-T` / `--trailer`: Repeatable flag for trailers 110 + - `-b` / `--body`: String flag for commit body text (can use heredoc for multiline) 111 + - `-T` / `--trailer`: Repeatable flag accepting full trailer strings in `Key: value` format (not separate key/value args) 112 + 113 + Trailer format detail: Each `-T` flag takes a complete trailer string like `-T "Co-authored-by: Name <email>"`, NOT separate key and value arguments. 85 114 86 115 ### Final Output 87 116