You got in the zone. Three hours later there are forty changed files, or worse, a chain of commits named wip, more stuff, and asdf that you would rather nobody ever saw. The work is good. The history is not.

preen fixes that. It is a Claude Code skill that reads everything you changed, groups it into atomic commits, writes a real message for each, orders them so the history bisects, and shows you the plan before anything moves. Think git add -p plus git rebase -i, with the judgment part done for you.

The absorb move

The feature I use most is not the split. It is what happens when you already committed the mess.

If your bad commits are unpushed, preen absorbs them: it soft-resets to the last pushed commit, which pours every change back into the working tree without losing a byte, then regroups all of it into clean commits. You do not unstage anything, you do not count how many commits to rewind, you do not touch the reflog. You run /preen, look at the plan, and approve it.

If the mess is already pushed, preen will still fix it, but only when you explicitly ask, only after showing the exact force-push it will run, and never with a bare git push --force. It uses --force-with-lease and it refuses shared branches unless you confirm the branch is yours alone.

Guardrails first

History rewriting tools earn trust with what they refuse to do. Before preen touches anything it saves a backup branch, so the worst case is always one git reset --keep away. It stops cleanly mid-rebase or mid-merge. It will not flatten a merge commit hiding in the range. It regenerates diffs after every commit because pre-commit hooks reformat files behind your back. Binary files stay whole. Empty stages stop the run instead of producing empty commits.

None of that is glamorous. All of it is the difference between a demo and a tool.

Fixup mode

Sometimes you do not want new commits at all. You have three clean commits and some follow-up fixes sitting dirty in the tree, and each fix belongs inside a commit you already made. preen --fixup finds the unpushed commit that introduced the lines each change touches, folds the change into it, and autosquashes. Like git absorb, except it can reason about the change when line history alone is ambiguous.

Honest limits

preen is a skill, not a compiled program. Its flags are conventions the agent follows and then verifies against its own output, not a parser. The repo ships an eval harness that runs the skill headless against fixture repos and asserts on the resulting git state, which is how prompt regressions get caught, but “enforced by instruction” is a real category difference from “enforced by code” and I would rather say so than have you find out.

Splitting one file’s hunks across several commits is the hardest move, and on a gnarly diff it degrades to whole-file grouping. The backup ref means even the failure mode is boring.

Try it

/plugin marketplace add dcadolph/preen
/plugin install preen@preen

Then make a mess and run /preen.