@geraldimanuel/smelt
v1.2.0
Published
Install the smelt skill for your coding harness — reshape noisy commit history into clean atomic commits without changing any code.
Maintainers
Readme
smelt 🔥
smelt reshapes the messy commit history on a feature branch into clean atomic commits — and proves it changed no code while doing it.
Quickstart
Give smelt to your agent: Claude Code, Codex CLI, Cursor, OpenCode.
Then, once a feature is done and the branch is noisy, just say:
smelt the branch before I open the PR
How it works
Iterative work leaves a trail: wip, fix typo, gofmt, address review,
patch the patch. You like atomic commits — you just don't want to hand-squash
that mess every time.
smelt reads the commits between your branch base and HEAD, groups the noise
into the logical commits it belongs to, and pours the branch back out as a small
set of readable atomic commits. It drives git non-interactively (soft-reset +
regroup, or rebase --autosquash for --fixup commits), so it works in
headless and agent environments where rebase -i isn't available.
The part that makes it safe to trust: git stores each commit's content as a
tree object. If the tree hash at HEAD is byte-identical before and after the
rewrite, then only the shape of history changed — every byte of every file is
the same. smelt records that hash up front and checks it at the end. If it
drifts, smelt restores your original HEAD and refuses. History changes;
content never does. That check is mandatory, not optional.
Example
A branch after a few hours of iteration:
$ git log --oneline main..HEAD
9f3a1c2 wip
7b2e004 address review comments
c14dd90 fix typo in error message
a90f7e1 gofmt
5e6b8aa oops forgot the test
2d4c119 feat: add rate limiter
b83f0a7 more wip
1c07e6d feat: parse config filesmelt proposes folding the noise into the real work, and waits for your OK:
Current (8): Proposed (2):
1c07e6d feat: parse config feat: parse config file
b83f0a7 more wip → feat: add rate limiter
2d4c119 feat: add limiter (wip / typo / gofmt / review / test
5e6b8aa oops forgot test fixups folded into their targets)
a90f7e1 gofmt
c14dd90 fix typo
7b2e004 address review
9f3a1c2 wipAfter you approve:
$ git log --oneline main..HEAD
e2a9f10 feat: add rate limiter
44b1c8d feat: parse config file
# tree hash identical before/after — not one line of code changed.Installation
Installation differs by harness. If you use more than one, install smelt
separately for each. Every harness invokes it the same way: /smelt, or just
ask to "smelt the branch".
Claude Code
This repo is its own plugin marketplace:
/plugin marketplace add geraldimanuel/smelt
/plugin install smelt@smeltOr clone it as a plain skill — Claude Code discovers SKILL.md automatically:
git clone https://github.com/geraldimanuel/smelt ~/.claude/skills/smeltFor a project (shared with your team via the repo), clone into
<repo>/.claude/skills/smelt instead.
The three non-Claude harnesses install with one command via npm — or copy the pointer file yourself.
Codex CLI
npx @geraldimanuel/smelt install codex
# manual: cp integrations/codex/smelt.md ~/.codex/prompts/smelt.mdInvoke with /smelt.
Cursor
npx @geraldimanuel/smelt install cursor
# manual: cp integrations/cursor/smelt.md ~/.cursor/commands/smelt.mdInvoke by typing / in the Agent input and selecting smelt.
OpenCode
npx @geraldimanuel/smelt install opencode
# manual: cp integrations/opencode/smelt.md ~/.config/opencode/commands/smelt.mdInvoke with /smelt. (Install everything at once with npx @geraldimanuel/smelt install all.)
How the non-Claude pointers work
Claude Code loads SKILL.md as a global skill, so it's available in any repo.
The other harnesses just inject a command file's text as a prompt — so smelt
ships a tiny pointer for each (integrations/<tool>/smelt.md). The pointer
tells the agent to read the canonical SKILL.md and follow it, sourcing it
from either:
- a local smelt clone (
~/.claude/skills/smelt/SKILL.mdby default — adjust the path if you cloned elsewhere), or - the copy on GitHub, fetched over the network, as a fallback.
Either way there's one source of truth: the root SKILL.md. Nothing is
duplicated, and it works offline once smelt is cloned locally.
The workflow
When you run smelt, it:
- Finds the base —
git merge-baseagainstmain/master, or asks you. - Refuses unsafe rewrites — stops if the noisy commits are already pushed/shared, unless you say the branch is yours alone.
- Records safety anchors — the current
HEADand its tree hash. - Proposes a clean shape — shows current → proposed with the final commit messages, and waits for your approval.
- Reshapes — soft-reset + regroup, or
rebase --autosquash, driven non-interactively. - Verifies the invariant — the final tree hash must equal the original,
or it restores
HEADand refuses. - Reports — the new log, and a reminder that pushing now needs
--force-with-lease(only if you ask).
What's inside
smelt/
├── .claude-plugin/
│ ├── plugin.json # plugin manifest
│ └── marketplace.json # self-marketplace (add this repo directly)
├── integrations/ # thin pointer files for other harnesses
│ ├── codex/smelt.md
│ ├── opencode/smelt.md
│ └── cursor/smelt.md
├── bin/smelt.js # npx installer (copies a pointer per harness)
├── test/install.test.js # self-check for the installer
├── package.json # npm package: @geraldimanuel/smelt
├── SKILL.md # the skill — the one source of truth
└── README.mdThe root SKILL.md is the single source of truth: it serves the Claude Code
plugin and plain-clone installs directly, and every integrations/ pointer
reads it too. No duplicated procedure.
Philosophy
- Content is sacred — reshaping history must never alter the working result.
- Prove it, don't claim it — the tree-identity check is the whole safety story, so it's mandatory.
- Never surprise a shared branch — don't rewrite pushed commits, and never
force-push unless explicitly asked (then
--force-with-lease). - You approve the shape — smelt proposes; you decide before anything is rewritten.
License
MIT — see LICENSE. It rewrites git history; it guards itself with the tree-identity check, but review the proposed shape before approving.
