From nickcrew-claude-ctx-plugin
Splits a dirty working tree into a clean sequence of atomic commits optimized for git bisect, ensuring each commit is the smallest buildable and deployable unit.
How this skill is triggered — by the user, by Claude, or both
Slash command
/nickcrew-claude-ctx-plugin:atomic-commitsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Take a dirty working tree of uncertain provenance and produce a clean, linear sequence of atomic commits where every commit builds, every commit could be reverted in isolation, and `git bisect` will land on a meaningful unit when chasing a regression. The agent does not assume it remembers what changed — it investigates, classifies, groups, then commits.
Take a dirty working tree of uncertain provenance and produce a clean, linear sequence of atomic commits where every commit builds, every commit could be reverted in isolation, and git bisect will land on a meaningful unit when chasing a regression. The agent does not assume it remembers what changed — it investigates, classifies, groups, then commits.
Every commit must satisfy this test:
If
git bisectlands on this commit alone, can the project still build, run its test suite, and be deployed? And does the commit's title accurately describe a single coherent change?
This produces two rules that govern every grouping decision:
auth.py should be two commits — bisect cannot tell which one introduced a regression if they ship together.When the two pull in different directions, prefer the smaller commit and add the minimum scaffolding (e.g., a stub, a no-op default) needed to keep the tree green.
Before classifying anything, get a complete picture of the working tree.
git status --short
git diff --stat
git diff # unstaged
git diff --cached # staged (rare in this workflow but check)
git log -10 --oneline # recent history for tone/style of messages
If there are staged changes already, decide whether to keep them as-is (commit first) or unstage to reclassify (git reset HEAD) — but never use destructive resets. When unsure, ask the user.
Treat the diff as code written by someone else. For each modified file:
git diff -- path/to/file), not just the hunks summary.tests/ exercise a new function in src/?Write a brief mental (or scratch) inventory: a list of logical changes, each tagged with the files and hunks it spans. This inventory is what gets converted into commits.
Map the inventory of logical changes onto a commit sequence:
If a single file contains hunks belonging to multiple logical changes, plan to use cortex git patch (Phase 4 — hunk-level path).
Use the right tool for the shape of the commit.
cortex git commitWhen every hunk in each named file belongs to the same logical change, commit the files whole:
cortex git commit "feat(auth): add OAuth2 device flow support" \
src/auth/oauth_device.py tests/auth/test_oauth_device.py
This stages the named files in full from the working tree and commits atomically. Use this whenever possible — it's the simplest and safest path.
cortex git patch --diffWhen a file contains hunks that belong to different logical changes, isolate the hunks for one commit via a diff fed through --diff. The files positional is an allowlist — the command will refuse to commit if the diff stages anything outside that list, so name only the files this particular commit should touch.
Two practical ways to produce the diff:
Option A — interactive split via temp file. Generate the file's full diff, edit it down to only the hunks for this commit, then apply:
git diff -- src/auth/oauth_device.py > /tmp/commit-1.diff
# edit /tmp/commit-1.diff in place: delete hunks that don't belong in this commit
cortex git patch "fix(auth): reject device codes after expiry" \
--diff /tmp/commit-1.diff src/auth/oauth_device.py
Option B — stdin pipe. Build the targeted diff with git diff flags or by piping through filters, and feed via -:
git diff -- src/auth/oauth_device.py \
| filter-hunks-script \
| cortex git patch "fix(auth): reject device codes after expiry" \
--diff - src/auth/oauth_device.py
After each hunk-level commit, the remaining hunks for that file stay in the working tree, ready to be committed (whole or split again) by the next call.
Strongly prefer hunk-level commits over bundling unrelated changes. Two bug fixes in the same file should not share a commit. The hunk-level path is the right tool, not a last resort.
Recent history in most Cortex/Nick projects uses Conventional Commits with lowercase types:
feat(scope): summary — new behaviorfix(scope): summary — bug fixrefactor(scope): summary — behavior-preserving changedocs(scope): summary — docs onlytest(scope): summary — tests onlychore(scope): summary — tooling, deps, buildbuild(scope): summary — packaging, lockfilesAlways check git log -10 --oneline first and match the project's actual style.
After the last commit, confirm the result:
git status # working tree should be clean (or only contain
# changes you explicitly chose not to commit)
git log -N --oneline # N = number of commits you just made
git diff HEAD~N..HEAD --stat
Spot-check that:
If a commit looks wrong, do not rewrite history with destructive operations. Either continue with a follow-up fix: commit or escalate to the user before any rebase.
When uncertain about a grouping call, use these defaults:
| Situation | Default |
|---|---|
| Bug fix + its regression test | One commit |
| New feature + its unit tests | One commit |
| New feature + integration tests + docs | One commit if tightly coupled; split docs only if substantial |
| Two unrelated bug fixes, same file | Two commits via cortex git patch |
| Refactor that enables a feature | Two commits: refactor first, then feature |
| Lockfile change | Bundled with the dependency edit that caused it |
| Generated file (codegen, schema, types) | Bundled with the source change that regenerates it |
| Pure reformatting across many files | Its own commit, kept separate from logic |
| Dead code removal | Its own commit unless it's directly enabled by the change you're making |
| Config change + code that reads it | One commit |
| One commit you're unsure about | Smaller, with hunk-level patch — bisect rewards atomicity |
git status shows changes outside the scope you were asked to handle, surface them rather than sweeping them in.git add directly. It bypasses Cortex's safety checks. Use cortex git commit or cortex git patch.git reset --hard, git checkout --, or git stash drop to "clean up" — these destroy uncommitted work. If a state is confusing, investigate rather than reset.bisect lands on the fix and the test is in a later commit, the bisect tool can't validate the fix actually worked at that point.npx claudepluginhub nickcrew/claude-cortexOrganizes git workspace changes into clean, atomic commits following conventional formats. Activates after features, refactors, or explicit commit requests.
Analyzes git changes, groups into atomic logical commits, writes conventional commit messages, stages files selectively, and commits safely. Use for clean solo git history without blind adds.
Guides atomic git commits: analyzes diffs, detects mixed concerns, groups files, stages selectively, verifies tests/builds, uses conventional messages, adds issues.