Install · How it works · Providers · Configuration · VS Code
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.
$ 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 quitOne 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.
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-vscodeOr search unbraid in the Extensions panel. Works in VS Code, Cursor, Windsurf, VSCodium, and Gitpod.
Needs Node.js 20+ and git.
npx unbraid --dry-run # try it — changes nothing
npm install -g unbraid # or keep it aroundcd ~/your-project
unbraid --dry-runYou'll see the plan, and nothing else happens. When you're ready:
unbraidWant 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/mainTwo 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.
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.
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.
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 |
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 # everythingThe -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.
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 --hunks1. 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.
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.
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.
unbraid initWalks 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 workingKeys 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.
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-cliBoth 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-5OpenAI, 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
404that 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-coderNo 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.
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 commitsEvery 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.
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.
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+Uto start
VS Code Marketplace · Open VSX · source
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.jsonunbraid 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.
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.
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.
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.