One isolated world per worktree.
Binky gives every git worktree its own ports, environment, database and URLs — so ten agents (or ten of you) can run the whole stack in parallel on one machine and never collide.
A local control plane for parallel branches.
Git worktrees already give you N checkouts of one repo. What they don't give you is
N running stacks. Every branch still wants port 3000, still wants the
same database, still writes to the same .env. So you serialise: one branch
at a time.
Binky removes that. It reads a single binky.toml at the
root of your repo and, for each worktree, allocates a free port block, provisions an
isolated database, renders the environment, starts and supervises your services, and
fronts them behind stable per-worktree URLs.
It runs as an always-alive local daemon with a SQLite registry, so state survives your terminal closing. It restarts what crashes, reaps what dies, and admits new worktrees only while the machine has RAM to spare. No Docker required — your processes run natively, exactly as they do today.
[project]
name = "acme"
https = true # https://web.<wt>.acme.localhost
[services.db]
adapter = "postgres"
admin_url = "${env.PG_ADMIN_URL}"
migrate = "pnpm prisma migrate deploy"
seed = "pnpm seed"
clone_from = "golden" # built once → cloned per worktree
[services.api]
cmd = "uv run api --port ${self.port}"
url = true # and so it gets a port
depends_on = ["db"]
health = "http://localhost:${self.port}/healthz"
[services.web]
cmd = "pnpm dev --port ${self.port}"
url = true
watch = ["web/**"]
[agents]
expose = ["web", "api", "db"]
verify = ["pnpm test", "pnpm lint"]
Every verb you'll use, and nothing to learn twice.
Commit binky.toml once. From then on every branch — yours or an agent's —
gets a full stack with a single command, and gives it all back with another.
binky initWrite a starting binky.toml from your docker-compose.yml.binky checkValidate the config and flag footguns before anything runs.binky up <wt>Create the worktree, allocate ports, provision the DB, start services.binky reload <wt>Restart in place — same ports, same data.binky down <wt>Stop the processes, keep the files, ports and data.binky remove <wt>Tear it all down — worktree, database, ports, logs.binky statusEvery worktree on the machine, live: state, services, ports.binky env <wt>Print the live coordinates as JSON or .env.binky verify <wt>Run the project's checks; records pass/fail on the worktree.binky logs <wt>Captured stdout/stderr per service, kept until you remove the worktree.binky dashboardLive TUI over the whole binky.binky doctorDiagnose the install and daemon; non-zero when something's wrong.binky curl <wt> <svc>Hit a service through the proxy with the Host header filled in.binky metricsPoint-in-time daemon metrics as JSON.binky gcSweep orphaned adapter slices a crash left half-provisioned.binky configShow the machine-global settings — RAM/disk reserves, proxy ports.binky reserveSet how much RAM and disk Binky permanently keeps free.binky portSet the proxy and HTTPS ports.binky mcpExpose the same verbs as MCP tools, for agents.binky daemonManage the background daemon: start, stop, status.Stop rebasing to review
Bring up the PR branch next to your feature branch, both fully running, and switch by opening a different URL.
Parallel without collisions
binky env hands each agent its own ports and database URL; binky verify is the gate its work has to pass.
One file, every machine
The stack definition lives in the repo. New hire clones, runs binky up, and is running in minutes — Linux or Windows.
Install to a running worktree, one step at a time.
The short version of the docs — six steps, at your own pace. Click through, or use the arrow keys.
$ uv tool install binky
# binky is now on your PATH
$ binky --version
0.0.1
[project]
name = "acme"
https = true
[services.db]
adapter = "postgres"
admin_url = "${env.PG_ADMIN_URL}"
clone_from = "golden" # built once → cloned per worktree
[services.api]
cmd = "uv run api --port ${self.port}"
url = true
[services.web]
cmd = "pnpm dev --port ${self.port}"
url = true
[agents]
expose = ["web", "api", "db"]
$ binky check
✓ binky.toml is valid — project 'acme', 3 service(s)
$ binky up <your-branch-name>
db pid 48213
api pid 48217 :41003
web pid 48219 :41005
✓ up: <your-branch-name> (3 service(s))
$ binky up <another-branch-name> # a second branch, in parallel
✓ up: <another-branch-name> (3 service(s))
$ binky status
acme
<another-branch-name> [running]
api :41013
web :41015
<your-branch-name> [running]
api :41003
web :41005
$ binky env <your-branch-name>
{"web": "http://web.<your-branch-name>.acme.localhost",
"api": "http://localhost:41003",
"db": "postgresql://…/acme_<your-branch-name>"}
Boring machinery, on purpose.
Resolve, then launch
A machine-global allocator reserves a block per worktree and only hands it out after confirming nothing else holds it. No EADDRINUSE roulette.
Golden template, cloned
Your own migrate+seed builds a golden database once. Each worktree gets a copy in milliseconds, and a hash marker rebuilds it when migrations change.
Supervised, not just spawned
Exits are reaped live, restarts follow a policy with exponential backoff and a give-up cap, and health probes run continuously.
Stable URLs
An embedded reverse proxy maps <service>.<worktree>.<project>.localhost to whatever port the service got — optionally over HTTPS via a local CA.
Your laptop survives
New worktrees queue FIFO against real available RAM instead of thrashing the machine into swap.
Answerable questions
A JSON-lines event log, point-in-time metrics, and a doctor that tells you what's broken instead of what's fine.
Whatever your stack already runs.
An adapter teaches Binky how to provision, resolve and tear down one kind of resource. First-party adapters ship in the repo and are tested in CI; anything else can be a standalone executable in any language, speaking a small JSON protocol.
each backend family is tested against a real server in CI — protocol-compatible forks share one implementation