Skip to content

Repository files navigation

unbraid

Turn a messy pile of changes into clean, well-described commits.

CI VS Code Marketplace Open VSX npm License

Install · How it works · Providers · Configuration · VS Code


The problem

You've been in the zone for three hours. Auth got fixed, a feature landed, some styling changed, a dependency moved. It all works.

Then git status prints 52 files and the momentum dies. Sorting that pile into commits that say something takes half an hour of git add and message-writing — so you do the honest thing:

* 4f2a1c9  update stuff

The work was good. The record of it is useless — to your reviewer, to your teammate, and to you next month.

unbraid does the sorting. It reads every change, works out what belongs with what, writes a real message for each group, and shows you the plan before touching anything.

What it does

$ unbraid

52 changed · conventional style · claude-cli/sonnet
⠹ Grouping 52 files 8s

  ▸ 1  feat(auth): add refresh token rotation        4 files
    2  fix(api): handle null user in profile route   2 files
    3  chore(deps): bump next to 15.2                1 file
    4  refactor(ui): extract Button variants         7 files
    5  test(auth): cover expired-token path          3 files
    6  chore: update lockfile                        1 file

  ↑↓ move · space files · e edit · m merge · d remove · c commit · q quit

One command, about a minute, six commits a reviewer can actually read.

New to some of these words? Staging, hunk, conventional commits — there's a plain-English glossary at the bottom. You don't need it to start.


Install

In your editor

unbraid for VS Code — your changed files, a review panel, and one-click undo, in a panel of its own.

code --install-extension aulianza.unbraid-vscode

Or search unbraid in the Extensions panel. Works in VS Code, Cursor, Windsurf, VSCodium, and Gitpod.

In your terminal

Needs Node.js 20+ and git.

npx unbraid --dry-run     # try it — changes nothing
npm install -g unbraid    # or keep it around

Your first run

cd ~/your-project
unbraid --dry-run

You'll see the plan, and nothing else happens. When you're ready:

unbraid

Want a safety net? Do it on a branch you can throw away:

git checkout -b unbraid-test
unbraid
# don't like it?
git reset --hard origin/main

Is this safe?

Two guarantees, both enforced in code and covered by tests.

It never changes your files. unbraid only stages and commits. It never edits, deletes, or overwrites anything in your project — your code is read-only to this tool. If something fails halfway through, every commit it made is undone and your staging restored exactly.

It never loses a change. AI models invent filenames, list the same file twice, and forget others. So unbraid doesn't trust the answer: it checks every file the model named against your real changes. Invented ones are dropped, duplicates removed, anything forgotten is shown to you rather than skipped.

Does it cost money?

Not if you already have Claude Code or the Codex CLI. unbraid finds either and uses the subscription you already pay for — no API key, no per-use charge, no setup.

Otherwise run unbraid init, which walks you through the alternatives — including running a model entirely on your own machine for free. See Providers.


How it works

1. READ     every changed, added, deleted, renamed, and untracked file
2. GROUP    a cheap pass over paths and truncated diffs decides what belongs together
3. WRITE    one pass per group, over that group's full diff, writes title and body
4. REVIEW   you reorder, merge, rename, or drop anything before it's written
5. COMMIT   stage each group, commit it, optionally push once at the end

Under ~15 files it does steps 2 and 3 in one pass, which is both faster and better.

The review screen

Nothing is committed until you press c.

Key
move between commits
space show this commit's files
e rename it
J K move it up or down
m merge into the commit above
d remove it — files go back to the pile, never deleted
c commit everything
q quit, committing nothing

Everyday commands

unbraid init             # set up a provider, step by step
unbraid                  # plan, review, commit
unbraid --dry-run        # show the plan, change nothing
unbraid --push           # commit, then push once
unbraid -g fine          # smaller commits, roughly one per file
unbraid --hunks          # split a file that mixes two concerns
unbraid pr               # write a pull request description
unbraid config           # show settings and where each came from
unbraid --help           # everything

How big should commits be?

The -g setting. Same 30 files, three results:

Commits Good for
-g coarse ~3 broad strokes: features, fixes, chores
(default) ~6 one per feature or fix
-g fine ~12 roughly one per file

Want it every time? Put it in a config file rather than typing it.

Splitting one file across commits

A commit normally takes whole files. So a bug fix on line 3 and an unrelated rename on line 40 end up stuck together.

unbraid --hunks
1. fix(api): guard getUser against missing records
     · src/user.ts (1 of its changes)

2. refactor(api): rename deleteUser to removeUser
     · src/user.ts (1 of its changes)

Two commits from one file. Off by default — most files don't mix concerns.

How this stays safe

The obvious approach is git apply, peeling off one group at a time. That's fragile: removing one group shifts the line numbers of every group after it, so patches fail or — worse — apply in the wrong place.

unbraid doesn't do that. It computes exactly what the file should contain at each commit and writes that content straight into git's object store. Your file is never touched.

And before it will split a file at all, it checks that applying all of that file's changes reproduces your file byte-for-byte. If that check fails, it commits the file whole instead.

Writing a pull request

unbraid pr               # print a title and description
unbraid pr --web         # open a prefilled PR page in your browser
unbraid pr -e --web      # edit it first, then open
unbraid pr -t dev        # target a different branch
unbraid pr --open        # create it with the GitHub CLI
unbraid pr -o pr.md      # save to a file

--web needs nothing installed — it opens GitHub's own "New pull request" page with the fields filled in. If your branch isn't pushed, unbraid offers to push it first, and it catches the quieter case too: a branch that is pushed but has newer local commits, which would otherwise produce a PR missing your latest work.

It describes your branch, not branches you merged in. Merge dev into yours and those commits stay out of the description — a branch with two commits of its own reads as two, not sixty-four.


Providers

A "provider" is whichever AI writes your messages. Two of them cost nothing extra.

Provider What you need Cost
Claude Code (default) nothing — detected automatically free with your subscription
Codex CLI nothing — detected automatically free with your subscription
Anthropic API an API key per token
Anything OpenAI-compatible a URL, usually a key varies, or free locally

With provider: auto, unbraid prefers the CLIs — they cost nothing beyond what you already pay for — then falls back to whichever API key it finds.

The easy way

unbraid init

Walks you through the options, takes your API key if one is needed, writes the config, and then makes a real call to check it works before you walk away.

$ unbraid init

✓ Claude Code found — free with your existing subscription

Which AI should write your commit messages?
  ❯ 1. Claude Code — free, no API key, already installed
    2. Codex CLI — free, no API key
    3. Anthropic API
    4. Something else (OpenAI, OpenRouter, Z.AI, Groq, DeepSeek, Ollama)

  ↑↓ move · 1-9 pick · enter confirm

✓ Wrote .unbraidrc.yaml

Testing the connection…
✓ claude-cli/sonnet is working

Keys you paste are stored in ~/.config/unbraid/credentials.json, readable only by you — never in your repository's config, which is a file you commit. An exported environment variable always wins over a stored key.

Add --global to configure every project at once.

Setting it up by hand

Claude Code or Codex CLI — free with a subscription

Install either and sign in. unbraid finds it with no configuration:

To pin one explicitly:

# .unbraidrc.yaml
provider: codex-cli      # or claude-cli

Both run headless, sandboxed read-only, and are asked for schema-conforming JSON — unbraid never lets an agent CLI execute anything on your behalf.

Codex users: if you run codex behind a custom --profile, check that the profile still honours --output-schema. Some routing profiles return plain text instead, and unbraid then falls back to a single commit.

Anthropic API

Get a key from console.anthropic.com, then run unbraid init and paste it — or export it yourself:

export ANTHROPIC_API_KEY="sk-ant-..."
# .unbraidrc.yaml
provider: anthropic
providers:
  anthropic:
    model: claude-sonnet-5
OpenAI, OpenRouter, Z.AI, Groq, DeepSeek

All speak the same protocol, so they share one setup:

# .unbraidrc.yaml
provider: openai-compatible
providers:
  openai-compatible:
    baseUrl: https://api.openai.com/v1
    apiKeyEnv: OPENAI_API_KEY
    model: gpt-4o
Service baseUrl Key
OpenAI https://api.openai.com/v1 platform.openai.com
OpenRouter https://openrouter.ai/api/v1 openrouter.ai/keys
Z.AI — pay as you go https://api.z.ai/api/paas/v4 z.ai
Z.AI — Coding Plan https://api.z.ai/api/coding/paas/v4 z.ai
Groq https://api.groq.com/openai/v1 console.groq.com
DeepSeek https://api.deepseek.com/v1 platform.deepseek.com

Z.AI: the two URLs are not interchangeable. A Coding Plan key sent to the pay-as-you-go endpoint returns a 404 that looks like an authentication error.

Ollama — free, and nothing leaves your machine
ollama pull qwen2.5-coder
ollama serve
# .unbraidrc.yaml
provider: openai-compatible
providers:
  openai-compatible:
    baseUrl: http://localhost:11434/v1
    model: qwen2.5-coder

No key needed. unbraid recognises local addresses, skips the credential warning, and never checks for updates — nothing leaves the machine.

Quality tracks the model: a small local one writes vaguer messages than a frontier one.

A note on speed. The free CLI providers are slower — 10–60 seconds a run, since each starts a whole CLI. An API key is noticeably faster. Free-and-slower is the right default for most people, but that's the trade.


Configuration

You don't need any of this. Configure only what you want to change.

Create .unbraidrc.yaml in your project, or ~/.config/unbraid/config.yaml for everything. The most common one:

grouping:
  granularity: fine     # always small, per-file commits
Every setting — every value shown is the default
provider: auto              # auto | claude-cli | codex-cli | anthropic | openai-compatible
model: auto
updateCheck: true           # check npm once a day, in the background

providers:
  claude-cli:
    bin: claude
    extraArgs: []
  codex-cli:
    bin: codex
    model: auto             # auto lets codex pick its own
    extraArgs: []
  anthropic:
    apiKeyEnv: ANTHROPIC_API_KEY
    model: claude-sonnet-5
  openai-compatible:
    baseUrl: https://api.openai.com/v1
    apiKeyEnv: OPENAI_API_KEY
    model: gpt-4o

grouping:
  granularity: semantic     # fine | semantic | coarse
  maxCommits: 20
  respectStaged: true       # already staged? left exactly as you set it
  hunks: false              # allow one file to split across commits
  expandUntrackedDirsUpTo: 10   # a new folder with more files counts as one item
  hints:                    # your rules, applied before the AI sees anything
    - match: "(package-lock.json|pnpm-lock.yaml|bun.lock)"
      group: "chore(deps): update lockfile"

message:
  format: conventional      # conventional | gitmoji | plain | auto
  types: [feat, fix, refactor, chore, docs, test, style, perf, build, ci]
  scope: auto               # auto | off | required
  maxTitleLength: 72
  body: auto                # always | never | auto
  bodyStyle: bullets        # bullets | prose
  language: en              # write messages in any language
  ticketPattern: null       # "([A-Z]+-\\d+)" lifts a ticket key from the branch name
  signOff: false

context:
  singlePassThreshold: 15   # at or under this, one faster AI call
  truncateLines: 20
  maxDiffBytes: 100000
  logSample: 20             # past commits read to learn your style
  exclude: ["*.lock", "*.min.js", "*.snap", "dist/**", "*.{png,jpg,svg,woff2}"]

execute:
  push: false
  pushRemote: origin
  autoconfirm: false        # skip the review screen, for scripts
  onError: rollback
  verify: true              # run your git hooks

pr:
  target: null              # null detects it: origin/HEAD, then main, master, develop

guard:
  secrets: true             # stop before sending credential-like files to a cloud provider
  secretPatterns: [".env", ".env.*", "*.pem", "*_rsa", "*.key", "*.p12"]

Settings combine in layers, later winning: defaults → ~/.config/unbraid/config.yaml.unbraidrc.yaml → environment → flags

unbraid config prints the result and where each value came from.

exclude means "don't spend tokens reading this" — those files are still committed.

Message style

Conventional Commits by default — type(scope): summary:

feat(auth): add refresh token rotation
fix(api): handle null user in profile route
refactor: migrate from pages router to app router

Scopes are encouraged, not required. Forcing one on every commit is how you get fix(fix):. unbraid also reads your last 20 commits and reuses the scopes and types already in use, so it writes ui and i18n rather than inventing frontend and translations.

Prefer to match whatever the repo already does — plain sentences, emoji, anything? Set message.format: auto.


In your editor

The extension gives you the same engine with a panel of its own:

  • Your changed files, with the icons and colours from your own theme
  • Stage, unstage, discard, switch branch, sync — without opening Source Control
  • The review panel: rename, merge, reorder, drop commits before anything is written
  • Undo the last run — puts HEAD and your staging back exactly as they were
  • ⌘⇧U / Ctrl+Shift+U to start

VS Code Marketplace · Open VSX · source

Scripting

Every part works without the interactive screen:

unbraid plan -o plan.json     # work out the commits, change nothing
$EDITOR plan.json             # edit by hand
unbraid apply --plan plan.json

Staying up to date

unbraid checks npm once a day, in the background, and mentions it after a command finishes:

Update available  0.8.0 → 0.9.0
npm i -g unbraid@latest

It never delays a run, and stays quiet in CI, when piped, when installed via npx, and when your provider runs on your own machine. Turn it off with updateCheck: false or UNBRAID_NO_UPDATE_CHECK=1. The check sends no identifier and nothing about you or your code.


Troubleshooting

command not found: unbraid npm install -g unbraid, or use npx unbraid.

"No AI provider available" Run unbraid init — it walks the options and checks the result works.

"Nothing to commit — the working tree is clean" No uncommitted changes. Edit something first.

"A merge is in progress" Finish or abort it first. unbraid won't commit into a half-finished operation, because it couldn't safely undo one.

It's slow. Expected on the free CLI providers — each run starts a whole CLI. An API key is faster.

It grouped things wrongly. Press e to rename, m to merge, J/K to reorder, q to throw the plan away. Nothing is committed until you press c.

Glossary

Staging — git's waiting room. Before committing you tell git which changes to include (git add). Deciding what goes in each batch is the part unbraid automates.

Atomic commit — a commit that does one thing. Easier to review, easier to undo, and it makes your history readable.

Hunk — one group of changed lines in a file. Change the top and the bottom and you have two.

Conventional Commits — the type(scope): summary format, like fix(auth): reject expired tokens. Machines can build changelogs from it; humans can scan it.

Working tree — your project files as they are on disk right now.


Status

Early, but real. Grouping, message generation, the review screen, commits with automatic rollback, hunk-level splitting, PR drafting, and four providers all work and are covered by tests.

Expect rough edges. Bug reports and pull requests genuinely welcome — see CONTRIBUTING.md, and ARCHITECTURE.md for how it works inside.

License

MIT © aulianza

About

Unbraid a tangled working tree into atomic commits, with AI-written messages.

Topics

Resources

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages