Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

smelt 🔥

npm

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.

For every harness except Claude Code, one command installs it from npm:

npx @geraldimanuel/smelt install <cursor | codex | opencode | all>

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 file

smelt 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 wip

After 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@smelt

Or clone it as a plain skill — Claude Code discovers SKILL.md automatically:

git clone https://github.com/geraldimanuel/smelt ~/.claude/skills/smelt

For 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 the npm package @geraldimanuel/smelt — or copy the pointer file yourself. No local checkout needed for the npx route.

Codex CLI

npx @geraldimanuel/smelt install codex
# manual: cp integrations/codex/smelt.md ~/.codex/prompts/smelt.md

Invoke with /smelt.

Cursor

npx @geraldimanuel/smelt install cursor
# manual: cp integrations/cursor/smelt.md ~/.cursor/commands/smelt.md

Invoke 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.md

Invoke 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:

  1. a local smelt clone (~/.claude/skills/smelt/SKILL.md by default — adjust the path if you cloned elsewhere), or
  2. 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:

  1. Finds the basegit merge-base against main/master, or asks you.
  2. Refuses unsafe rewrites — stops if the noisy commits are already pushed/shared, unless you say the branch is yours alone.
  3. Records safety anchors — the current HEAD and its tree hash.
  4. Proposes a clean shape — shows current → proposed with the final commit messages, and waits for your approval.
  5. Reshapes — soft-reset + regroup, or rebase --autosquash, driven non-interactively.
  6. Verifies the invariant — the final tree hash must equal the original, or it restores HEAD and refuses.
  7. 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.md

The 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.

About

Agent skill: smelt fixup/patch/wip commit noise into clean atomic commits, verified by a byte-identical tree check.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages