Analyze the current git diff, group files into logical changes, then produce concise conventional-commit messages and commit each group separately.
Steps
-
Check for changes
git status --porcelainIf there are no changes, tell the user "Nothing to commit" and stop.
-
Analyze changed files before staging
Collect changed paths (modified, staged, untracked) and inspect them:
git status --porcelain git diff --name-only git diff --cached --name-onlyBuild file groups before staging anything.
Grouping priority (in order):
- Feature/change groups: files under
openspec/changes/<change-name>/and related code/docs that clearly implement that same feature - Shared infra/support groups: cross-cutting files (build/config/tooling/logging helpers) that don't belong cleanly to one feature
- Skill/docs groups: skill files, agent config, docs-only updates
Prefer one commit per change group. If there is only one clear group, use one commit.
Important: If a single file contains unrelated edits for multiple groups and cannot be split cleanly at file-level, ask the user before proceeding (or keep it in one group and explain the tradeoff).
- Feature/change groups: files under
-
Draft a commit plan (group-by-group)
For each group:
- list files in the group
- summarize intent
- draft a conventional commit message using the format below
-
Present the plan and ask for confirmation
Show:
- proposed groups (with files)
- proposed commit message for each group
Ask for confirmation before staging/committing.
-
Stage and commit each group individually
For each confirmed group, in order:
a. Stage only that group's files
git add -- <file1> <file2> ...b. Review the staged summary
git diff --cached --stat git diff --cached --name-onlyc. Commit using the group's message
git commit -m "<message>"For multi-line messages, use multiple
-mflags.d. Continue to the next group (index should be clean after commit)
-
Confirm all commits
Show recent commits created in this run:
git log --oneline -<N>Confirm each planned group was committed.
Commit Message Format
Use this format for each group commit:
feat(<scope>): concise description of what changed
Rules:
- scope = the logical area affected. Use short names like:
connector,db,api,engine,frontend,docs,config,infra. - If a change maps to a known feature (check
openspec/changes/*/), use that feature name as the scope. For example:feat(mvp-full-sync): add Klaviyo connector. - Each line should be ≤ 72 characters.
- Use
featfor new features,fixfor bug fixes,refactorfor restructuring,docsfor documentation,chorefor config/build changes. - If all changes are part of one logical unit, a single line is fine.
Examples:
Single-line:
feat(connector): add Klaviyo connector with cursor pagination
Multi-line (when spanning multiple areas):
feat(connector): add Klaviyo connector with cursor pagination
feat(api): expose embedded PG URL via /api/config endpoint
fix(db): clean up stale postmaster.pid on startup
chore(docs): add project README
Guidelines
- Be concise. Each line should tell the reader what changed, not how.
- Prefer action verbs: add, fix, remove, update, refactor, extract.
- Don't list every file in commit messages — summarize by intent.
- If there are 10+ files changed across 3+ areas, still aim for ≤ 5 commit message lines.
- When in doubt, fewer lines is better.
- Prefer multiple small commits over one mixed commit when changes map to different features.
- Group by change first, then by layer (api/frontend/docs) within that change.