--- name: commit description: Analyse working tree changes, group them into logical atomic commits, and create well-structured conventional commits with module scopes. user_invocable: true --- # Commit Changes Analyse the current working tree, group changes into logical atomic commits, and create them using conventional commit format. ## Steps ### 1. Gather context Run these commands to understand the full picture: ```bash # Staged changes git diff --cached --stat git diff --cached # Unstaged changes git diff --stat git diff # Untracked files git status -u # Recent commits for style reference git log --oneline -10 ``` If there are no changes at all (nothing staged, unstaged, or untracked), tell the user and stop. ### 2. Review changes and decide inclusion Review **all** changes (staged, unstaged, and untracked). **Be autonomous — commit everything that looks intentional without asking.** The bias is toward getting things committed, not toward caution-prompting. **Include without asking:** - All staged changes — the user explicitly staged these - All unstaged changes to tracked files — these are work in progress that should be captured - Untracked files that clearly relate to the other changes (new source files, tests, resources, configs for the feature being worked on) - Deleted files — if a file is deleted in the working tree, the deletion is intentional - Files outside the apparent scope — include them in their own commit rather than leaving them uncommitted - CLAUDE.md changes — always include these **Only stop and ask if you encounter a genuine red flag:** - **Sensitive files** (credentials, keys, tokens, `.env` with secrets) — warn and **never** commit these - **Files that are almost certainly not meant for version control** (e.g., `.DS_Store`, `*.log`, editor swap files, `node_modules/`) If everything looks clean (which is the common case), proceed directly to grouping and committing — no confirmation prompt needed. ### 3. Classify changes by component Determine which component each changed file belongs to: - **app** — files under `android/app/` - **playback** — files under `android/playback/` - **mediaprovider** — files under `android/mediaprovider/` (any provider) - **domain** — files under `android/domain/` - **core**, **networking**, **imageloader**, **trial** — the corresponding `android//` - **root** — top-level files (CI, docs, scripts, Gradle config) For root files, choose the most relevant scope: - CI/CD workflows for a specific module → use that module's scope - Cross-cutting or build-wide changes → omit the scope ### 4. Group into logical commits Split changes into atomic commits. Each commit should represent **one logical change** that leaves the codebase in a working state. **Group by:** - Same feature or purpose across related files - Same type of change (e.g., all test updates for a feature go together) - Dependencies — if change B only makes sense with change A, they belong together **Split when:** - Changes serve different purposes (feature vs refactor vs test vs docs) - Unrelated files happen to be modified together - A rename/refactor is mixed with behaviour changes - Test additions are standalone (not tied to a specific feature change) **Ordering:** Commit foundational changes first (e.g., new module before feature using it, refactor before feature built on it). When in doubt, **fewer well-grouped commits are better than many tiny ones.** Don't split for the sake of splitting — only split when commits genuinely represent distinct logical changes. ### 5. Determine commit message for each group Follow the conventional commit format from this project: ``` type(scope): description [optional body] [optional footer] ``` #### Type Choose the most accurate type: - `feat` — new feature or capability - `fix` — bug fix - `refactor` — code restructuring without behaviour change - `test` — adding or updating tests - `docs` — documentation changes - `style` — formatting, linting (no logic change) - `chore` — maintenance, dependencies, config - `build` — build system or dependency changes - `ci` — CI/CD pipeline changes - `perf` — performance improvement #### Scope The module the change lives in (see the list above). Optional for cross-cutting or build-wide changes. If a commit touches several modules, use the primary one (where the meaningful change is) or split into separate commits. #### Subject line - **Imperative mood**: "add", "fix", "update" — not "added", "adds", "adding" - **Lowercase** after the colon - **No period** at the end - **Max 50 characters** for the description (after `type(scope): `). Stretch to 72 max if absolutely necessary - **Explain the "why" or "what changed"**, not the mechanical "how" Good: `feat(playback): add queue reordering via drag and drop` Bad: `feat(playback): updated QueueScreen.kt and QueueViewModel.kt` #### Body Include a body when: - The "why" isn't obvious from the subject line alone - There are side effects, trade-offs, or context worth capturing - Multiple files changed and the connection isn't obvious Body rules: - Blank line between subject and body - Wrap at 72 characters - Explain **why**, not what (the diff shows what) - Use bullet points for multiple points Skip the body for self-explanatory changes (typo fixes, simple renames, obvious additions). #### Changelog upkeep For `feat`/`fix`/`perf` commits, the `.githooks/commit-msg` hook requires one of: - **Stage a new `android/changelog.d/-.json` fragment together with the code** — when the commit changes what a user sees or experiences - **Add a `Changelog: none` trailer** to the message — when the change is internal (tests, refactors, tooling, CI, DI plumbing) Which rule decides is in `.claude/rules/changelog.md`: a change iterating on an unreleased fragment edits that fragment rather than adding a new one, and internal changes take the trailer. ### 6. Stage and commit each group For each logical commit group, stage the relevant files and commit: ```bash # Stage specific files for this commit git add ... # Use git add -p to stage partial file changes when needed # (when a single file contains changes belonging to different commits) # Commit with heredoc for proper formatting git commit -m "$(cat <<'EOF' type(scope): subject line here Optional body here explaining why this change was made. Wrap at 72 characters. EOF )" ``` **Important:** - Stage specific files by name — never use `git add -A` or `git add .` - Use `git add -p ` when a file has changes belonging to different logical commits - Verify each commit with `git status` before moving to the next group - If a pre-commit hook fails, fix the issue and create a **new** commit (never `--amend` unless the user explicitly asks) ### 7. Summary After all commits are created, show a brief summary: ``` Created N commit(s): abc1234 type(scope): first commit subject def5678 type(scope): second commit subject ``` ## Examples ### Single-component change ``` feat(android): add offline download support for episodes Introduce DownloadManager and background worker to cache episodes locally. Downloads persist across app restarts and respect user's network preferences. ``` ### Multi-commit from mixed changes Given changes to Android UI, Android tests, and a backend endpoint: 1. `feat(android): add episode search filter by duration` 2. `test(android): add search filter unit tests` 3. `feat(backend): add duration parameter to episode search endpoint`