Skip to content

One binary, every branch

Stop switching branches. Run all of them.

daft gives every branch its own directory — a plain git worktree with its own dependencies, build, and dev server — and keeps the whole set coherent across repos, for you and for the agents you run.

$ brew install avihut/tap/daft

MIT or Apache-2.0 · All install methods · Quick start

$ daft clone git@github.com:acme/web.git
cloned web · worktree main/ ready
dev server → :3000
$ daft start checkout
worktree checkout/ created
✓ pnpm install ✓ .envrc ✓ build cache
dev server → :3001
$ daft start bugfix/cart-total
ready → :3002
$ daft start spike/faster-cart
ready → :3003
$ daft list
main :3000 clean
checkout :3001 agent · building
bugfix/cart-total :3002 agent · testing
spike/faster-cart :3003 you
$ daft start orders checkout
orders: worktree checkout/ ready
dev server → :4001
$ daft start payments checkout
payments: worktree checkout/ ready
dev server → :5001
$ daft exec --related -- pnpm test
✓ web ✓ orders ✓ payments
$ daft exec --related -- git push
checkout → origin in web, orders, payments
# PRs reviewed → merged on the forge
$ daft remove spike/faster-cart
removed spike/faster-cart · :3003 released
$ daft sync
updated 3 mains · bases refreshed
pruned checkout in web, orders, payments
Clone

A daft session replayed live — not a video. Click any command to jump to it; the graph is what those commands did to the project.

Every branch gets its own directory.

daft start checkout creates the branch and checks it out into a directory of its own, then runs the hooks you wrote for a new worktree — install, env, build cache — so it is ready to work in before you arrive.

Start as many as you need. Each keeps its own dependencies, its own build, and its own dev server port.

Worktrees →
$ daft clone git@github.com:acme/web.git
cloned web · worktree main/ ready
dev server → :3000
$ daft start checkout
worktree checkout/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3001
$ daft start bugfix/cart-total
worktree bugfix/cart-total/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3002
$ daft go checkout
→ ~/web/checkout/
Clone web

Switching costs nothing.

Another branch is another directory, so there is nothing to stash and nothing to rebuild. daft go feature-b moves your shell there; what you installed and built is still warm.

Come back with daft go - and your editor, your server, and your uncommitted changes are exactly where you left them.

Why daft →

Before

git stash
git checkout feature-b
npm install   # wait…
npm run build # wait…
# IDE state gone. Where was I?

After

daft go feature-b
already installed · already built
daft go -
right where you left it

One feature across many repos — still one thing.

When a change crosses repos, daft start orders checkout opens the same branch in the related repo and links the two worktrees. daft exec --related -- pnpm test then runs across every worktree the feature touches, and daft sync keeps all of them current.

The repo graph — daft's catalog of where your repos live and how they relate — is what makes that one command instead of four.

The repo graph →
$ daft clone git@github.com:acme/web.git
cloned web · worktree main/ ready
dev server → :3000
$ daft start checkout
worktree checkout/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3001
$ daft start orders checkout
orders: worktree checkout/ ready
dev server → :4001
$ daft exec --related -- pnpm test
✓ web ✓ orders
Clone web

Agents work in parallel, each in its own worktree.

Give every coding agent a worktree and they stop stepping on each other: separate directories, separate ports, separate branches, one repo. The daft agent skill teaches them the verbs, so an agent starts its own worktree the way you would.

daft list shows who is where.

The agent skill →
$ daft clone git@github.com:acme/web.git
cloned web · worktree main/ ready
dev server → :3000
$ daft start checkout
worktree checkout/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3001
$ daft start bugfix/cart-total
worktree bugfix/cart-total/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3002
# agent picks up web:checkout
# agent picks up web:bugfix/cart-total
$ daft list
main :3000 clean
checkout :3001 agent · building
bugfix/cart-total :3002 agent · testing
Clone web

Ship and clean up from anywhere.

daft merge checkout runs from whichever directory you are standing in: your pre-merge hooks gate it — fmt, clippy, tests, whatever you wire up — the merge lands in main's worktree, and with -r the source worktree comes down. No checkout, no losing your place.

When the forge merges the rest, daft sync refreshes every base and prunes the branches that already landed.

Merging →
$ daft clone git@github.com:acme/web.git
cloned web · worktree main/ ready
dev server → :3000
$ daft start checkout
worktree checkout/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3001
$ daft start bugfix/cart-total
worktree bugfix/cart-total/ created
✓ install ✓ .envrc ✓ build cache
dev server → :3002
$ daft merge checkout
✓ fmt ✓ clippy ✓ tests
merged into main · worktree removed
$ daft push bugfix/cart-total
web: bugfix/cart-total → origin · upstream set
# forge: bugfix/cart-total approved → merged in web
$ daft sync
updated 1 main · bases refreshed
pruned bugfix/cart-total in web
Clone web

Give every branch a home.

Plain git underneath: every worktree daft makes is a git worktree, every verb doubles as a git subcommand, and removing daft leaves your repo exactly as it is. One binary, and nothing else about your setup changes.

$ brew install avihut/tap/daft

Released under MIT or Apache-2.0.