# semantic-commit
## Overview
`semantic-commit` is the agent-facing commit helper for staged-change
workflows. It validates Semantic Commit messages, creates and amends commits,
emits staged context for message generation, and supports machine-readable
commit results for automation.
The CLI is intentionally not a generic `git` wrapper. It owns commit-message
validation and commit mutation. Callers still own staging decisions, task
scope, branch policy, push/PR delivery, and any higher-level workflow checks.
## Commands
```text
Usage: semantic-commit [COMMAND]
Commands:
staged-context Print staged change context for commit message generation
commit Commit staged changes with a prepared commit message
fixup Create a fixup! commit for staged changes
squash Create a squash! commit for staged changes
completion Export shell completion script
help Display help message
```
Top-level options:
- `-h`, `--help` - print help
- `-V`, `--version` - print version
Use `semantic-commit <command> --help` for command-specific help.
## `staged-context`
Print staged change context for commit message generation.
```text
semantic-commit staged-context [--format <bundle|json|patch>] [--repo <path>]
```
Options:
- `--format <bundle|json|patch>` - output format; default is `bundle`
- `--json` - equivalent to `--format json`
- `--repo <path>` - run git commands against a repository path
Formats:
- `bundle`: prints `commit-context.json` and `staged.patch` sections.
- `json`: prints only the JSON context payload.
- `patch`: prints only `git diff --cached`.
## `commit`
Create a new commit or amend `HEAD` using a validated Semantic Commit message.
```text
semantic-commit commit [--message <text>|--message-file <path>] [options]
```
Message sources are mutually exclusive:
- `-m`, `--message <text>` - inline commit message
- `-F`, `--message-file <path>` - read commit message from a file
- stdin - used when no message flag is supplied and stdin is non-TTY
- structured fields - `--type`, optional `--scope`, `--subject`, and
repeatable `--body-bullet`
Commit operation options:
- `--amend` - amend `HEAD` instead of creating a new commit
- `--no-edit` - with `--amend`, reuse and validate the `HEAD` message
- `--message-only` - with `--amend`, update only the `HEAD` message and
require no staged changes
- `--allow-empty` - allow a commit operation without staged changes
- `--dry-run` - validate message and staged-state checks without committing
- `--validate-only` - validate only the message; does not require a git repo
Output and recovery options:
- `--format <text|json>` - output mode; default is `text`
- `--json` - equivalent to `--format json`
- `--message-out <path>` - write the resolved message before mutation
- `--summary <git-scope|git-show|none>` - summary mode; default is
`git-scope` with fallback to `git-show`
- `--no-summary` - equivalent to `--summary none`
- `--no-progress` - disable the progress spinner
- `--quiet` - suppress progress and text summary output
Safety options:
- `--repo <path>` - run git commands against a repository path
- `--require-clean` - require no unstaged or untracked changes
- `--no-unstaged` - alias for `--require-clean`
- `--expect-head <rev>` - require `HEAD` to match a revision before mutation
- `--automation`, `--non-interactive` - disallow stdin message fallback
Message-construction options:
- `--auto-fix` - normalize body wrapping, bullet capitalization, header
type/scope case, and the blank separator before validation
- `--max-header-width <N>` - override the active header width; default is
`100`, with `SEMANTIC_COMMIT_HEADER_WIDTH` as an environment default
- `--signoff` - pass `--signoff` to `git commit`
- `--trailer <token: value>` - add a git trailer; repeatable
- `--type <type>` - structured message type
- `--scope <scope>` - structured message scope
- `--subject <subject>` - structured message subject
- `--body-bullet <text>` - structured message body bullet; repeatable
Examples:
```bash
semantic-commit staged-context
semantic-commit commit \
--message "feat(cli): add commit result json"
semantic-commit commit \
--amend \
--no-edit \
--expect-head HEAD \
--require-clean
semantic-commit commit \
--amend \
--message-only \
--message "fix(cli): clarify amend help"
semantic-commit commit \
--type feat \
--scope semantic-commit \
--subject "support amend flow" \
--body-bullet "Add no-edit amend support." \
--body-bullet "Return JSON commit metadata." \
--json
semantic-commit commit \
--message "fix(cli): link tracker" \
--trailer "Refs: #573" \
--signoff
```
## `fixup` and `squash`
Create review-cleanup commits without bypassing the `semantic-commit` staged
checks and machine-readable output contract.
```text
semantic-commit fixup --target <rev> [options]
semantic-commit squash --target <rev> [options]
```
These subcommands call git's cleanup-commit modes and intentionally do not
validate the generated `fixup!` / `squash!` subject as a Semantic Commit
header.
Options:
- `--target <rev>` - target commit revision; required
- `--dry-run` - validate target and staged checks without committing
- `--format <text|json>`, `--json` - output mode
- `--summary <git-scope|git-show|none>`, `--no-summary` - text summary
- `--allow-empty` - allow a cleanup commit without staged changes
- `--require-clean`, `--no-unstaged` - require no unstaged or untracked
changes
- `--expect-head <rev>` - require `HEAD` to match a revision before mutation
- `--repo <path>` - run git commands against a repository path
- `--no-progress`, `--quiet` - progress and summary controls
Examples:
```bash
semantic-commit fixup --target HEAD~1
semantic-commit squash --target abc123 --json --dry-run
```
## JSON Output
`semantic-commit commit --json`, `semantic-commit fixup --json`, and
`semantic-commit squash --json` emit a single JSON record on success:
```json
{
"schema_version": "cli.semantic-commit.commit.v1",
"ok": true,
"operation": "commit",
"validate_only": false,
"dry_run": false,
"commit": {
"sha": "012345...",
"subject": "feat(cli): add commit result json"
},
"target": null,
"staged": {
"file_count": 1,
"files": [
{
"status": "M",
"path": "crates/semantic-commit/src/commit.rs",
"old_path": null
}
]
}
}
```
For `fixup` and `squash`, the record also includes the resolved target commit
and generated subject.
## Commit Message Validation
Semantic Commit validation applies to `semantic-commit commit` message input:
- Header format is `type(scope): subject` or `type: subject`.
- Header type must be lowercase and start with an ASCII lowercase letter.
- Scope, when present, may contain lowercase letters, digits, `.`, `_`, and
`-`.
- Header length must not exceed the active header width.
- Body lines must be bullet lines that start with `-` plus a space followed by an
uppercase ASCII letter, or continuation lines that start with two spaces.
- Body and trailer lines must be at most `100` characters.
- Git trailers may appear after the header or after a blank separator
following bullet body lines.
- Blocked message rules reject known unwanted agent attribution text, including
`Co-Authored-By: Claude ...` trailers from either message input or
`--trailer`.
`fixup` and `squash` do not use this header validation because git generates
subjects prefixed with `fixup!` or `squash!`.
## Exit Codes
- `0`: success and help output.
- `1`: usage errors or operational errors.
- `2`: no staged changes.
- `3`: commit message missing or empty.
- `4`: commit message validation failed.
- `5`: required dependency missing, such as `git`.
## Dependencies
- `git` is required.
- `git-scope` is optional. When unavailable, text summaries fall back to
`git show -1`.
## Non-Goals
`semantic-commit` does not push, force-push, rebase, create PRs, choose branch
names, or stage files implicitly. Those decisions belong to the surrounding
agent workflow.
## Docs
- [Docs index](docs/README.md)