···10101111## Development Commands
12121313+- **Default workflow**: `just` (runs fmt, lint, staticcheck, test, vuln, reuse)
1314- **Build**: `just build` (outputs binary as `formatted-commit`)
1415- **Run during development**: `just run [flags]`
1515-- **Format code**: `just fmt`
1616+- **Format code**: `just fmt` (uses gofumpt)
1717+- **Lint**: `just lint` (uses golangci-lint)
1818+- **Static analysis**: `just staticcheck`
1919+- **Vulnerability check**: `just vuln` (uses govulncheck)
2020+- **License compliance**: `just reuse` (REUSE specification)
2121+- **Test**: `just test` or `go test ./...`
2222+- **Single test**: `go test -v -run TestName ./...` (no tests exist yet)
1623- **Update dependencies**: `go mod tidy`
1717-- **Test**: `go test ./...`
18241925Example usage:
2026···2733This is a CLI tool that formats git commit messages according to Conventional Commits specification and pipes them directly to `git commit -F -`. It enforces:
283429351. Subject length: max 50 characters in format `type(scope): message`
3030-2. Body wrapping: strictly 72 columns using Markdown formatter
3636+2. Body wrapping: strictly 72 columns with hanging indents for bullets/numbered lists
31373. Trailer validation: follows git's trailer specification
32383339## Architecture
34403535-Single-file CLI application (`main.go`) using:
4141+Multi-file CLI application split by concern:
4242+4343+- **main.go**: Cobra CLI setup, flag definitions, subject validation, orchestration, git command execution
4444+- **trailers.go**: Trailer validation and block building following git's RFC 822 folding specification
4545+- **wrapBody.go**: Body text sanitization and custom word-wrapping with hanging indent support
4646+4747+Dependencies:
36483749- **cobra**: CLI framework for flags and commands
3838-- **fang**: Charmbracelet's execution wrapper (provides version handling, etc.)
3939-- Future: Will need a Markdown formatter for body text (likely from Charmbracelet ecosystem based on dependencies)
5050+- **fang**: Charmbracelet's execution wrapper (version handling, etc.)
5151+- **bluemonday**: HTML/Markdown sanitization using UGCPolicy
5252+- **Custom word wrapping**: Pure-Go implementation for 72-column wrapping with hanging indents
40534154## Critical Implementation Details
4255···48614962### Body Formatting
50635151-The body (`-b` flag) must be:
6464+The body (`-b` flag) processing pipeline:
6565+6666+1. **Sanitization**: `bluemonday.UGCPolicy()` strips dangerous HTML/scripts while preserving basic formatting
6767+2. **Line-by-line processing**: Each line is processed based on its type:
6868+ - **Bullets** (`- ` or `* `): Wrapped with 2-space hanging indent for continuation lines
6969+ - **Numbered lists** (`^\d+\.\s`): Wrapped with hanging indent matching the marker length (e.g., `1. `, `10. `)
7070+ - **Plain text**: Standard word-wrap at 72 columns
7171+ - **Blank lines**: Preserved as-is
7272+3. **Word wrapping algorithm**: Greedy wrapping splits on word boundaries, never mid-word
7373+4. **Hanging indent logic**: For bullets/numbered lists, first line gets the marker, continuation lines get spaces equal to marker width
7474+5. **Spacing**: Body separated from subject by one blank line, from trailers by one blank line
52755353-1. Sanitised because it should only be basic text and bullets
5454-2. Formatted as Markdown, properly wrapping bullets with hanging indents on
5555- following lines like this
5656-3. Strictly wrapped to 72 columns using a pure-Go formatter
5757-4. Separated from subject by one blank line
5858-5. Separated from trailers by one blank line
7676+Example wrapped bullet:
7777+7878+```
7979+- This is a long bullet point that exceeds 72 characters and will
8080+ be wrapped with proper hanging indent alignment on continuation
8181+ lines.
8282+```
59836084### Trailer Formatting (Critical)
6185···7910380104### Flag Nuance
81105106106+- `-t` / `--type`: Commit type (required) - e.g., `feat`, `fix`, `refactor`
107107+- `-m` / `--message`: Commit message (required) - the description after the colon
108108+- `-s` / `--scope`: Commit scope (optional) - goes in parentheses after type
82109- `-B` / `--breaking`: Boolean flag for breaking changes (adds `!` to subject)
8383-- `-b` / `--body`: String flag for commit body text
8484-- `-T` / `--trailer`: Repeatable flag for trailers
110110+- `-b` / `--body`: String flag for commit body text (can use heredoc for multiline)
111111+- `-T` / `--trailer`: Repeatable flag accepting full trailer strings in `Key: value` format (not separate key/value args)
112112+113113+Trailer format detail: Each `-T` flag takes a complete trailer string like `-T "Co-authored-by: Name <email>"`, NOT separate key and value arguments.
8511486115### Final Output
87116