Stop guessing. Run every branch for real.
Every branch gets its own containers, database, ports and browser origin. Five at once, on your machine, walled off from each other. Nothing runs without your OK.
curl -fsSL devbay.claritty.ai/install | shTwo branches, one cookie jar.
Browsers key cookies by host and ignore the port. Two branches on localhost:3000 and localhost:3001 share one session. Log in to one, and the other is already logged in as you.
Giving each bay its own origin removes the bug instead of working around it. Try the toggle.
Measured in Chrome on 2026-08-11 against examples/cookie-isolation, which ships in the repository so you can repeat it.
Bay beta received bay alpha's session. Nothing about either application is wrong and nothing appears in either log.
| Bay | State | URL |
|---|---|---|
| add-search* | hot | http://add-search.taskboard.localhost |
| fix-login | warm | http://fix-login.taskboard.localhost |
| bump-deps | warm | http://bump-deps.taskboard.localhost |
| retry-webhook | warm | http://retry-webhook.taskboard.localhost |
| audit-log | cold | http://audit-log.taskboard.localhost |
5 bays, 20 containers, 289 MiB in total. Measured inside the VM.
Five branches, running at once.
Each one boots in about a second and answers on its own hostname. Your agent can hold four experiments open while you review the fifth.
A task declares the services it needs, so devbay starts only those. A unit suite declares none and boots nothing at all, which is why it comes back in milliseconds.
Nothing runs without your OK.
A repository can ask to run ./bin/dev. devbay will not execute it until you have read the exact command and agreed to it.
The decision is remembered, and it is keyed to the whole command. Approving bin/dev does not approve bin/dev --seed-prod. An agent cannot make the decision for you: the gate checks that a person answered.
See exactly what ran.
A failure comes back as a name, a file, a line and the assertion. Nobody has to read scrollback to find out what broke.
When one service will not start, the bay stays up. The broken service is named, its container and its logs are kept, and everything else keeps serving. That is what Docker does with a stack, and a tool that deleted the evidence instead would be harder to work with, not safer.
It writes the file. You can read it.
devbay init reads the compose file, the Actions workflow and the Procfile you already have. Every line it writes says where it came from, and it lists what it could not work out rather than guessing.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: taskboard
web:
build: ./web
ports: ["3000:3000"]
depends_on: [api]
environment:
# Called from the browser, so this has
# to become a browser address.
API_URL: http://localhost:4000# Where this came from:
# compose docker-compose.yml — service "db" from
# image postgres:16-alpine
# convention health probe for "db" from the
# postgres image family
#
# STILL TO DECIDE — devbay could not work these out:
# - service "web" was given a placeholder probe
# `GET /`; point it at a real health endpoint
services:
db:
image: postgres:16-alpine
port: 5432
health: {cmd: [pg_isready, -U, postgres]}
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: taskboard
web:
build: {context: ./web}
port: 3000
primary: true
needs: [api]
env:
API_URL: ${bay.api.public_url}The literal address became a reference. A hardcoded localhost:4000 is wrong the moment a second copy exists, so devbay rewrites it to the bay asking the question. The file is committed and reviewable in a pull request.
Typed results, not stdout to scrape.
Seven stateless tools over MCP. Every one takes an explicit bay, so there is no session to lose.
An agent asks for a task and gets counts and failures with a file and a line. It can fix the test rather than parse the output. Credentials never appear in what it reads.
bay_createCreate an isolated environmentbay_listList environmentsbay_run_taskRun a declared taskbay_logsRead service logsbay_urlGet a service URLbay_statusInspect one environmentbay_destroyDestroy an environment
{
"task": "unit",
"exit_code": 1,
"duration_ms": 214,
"total": 2,
"passed": 1,
"failed": 1,
"parsed": true,
"failures": [
{
"name": "test_subtraction",
"file": "suite.py",
"line": 42,
"message": "assert 5 - 3 == 1"
}
]
}Checked against repositories nobody wrote it for.
Every stack in docker/awesome-compose, copied unmodified, each compared with what docker compose up does with the same repository on the same machine. Compose serves 23. There is no stack compose runs that devbay does not.
Run under the race detector on every push. The integration packages talk to real Docker rather than a fake.
Each drives the real binary against real containers and states what would have to be observed for its claim to be false.
The method and the per-stack results are in docs/ACCEPTANCE.md. scripts/corpus.sh runs it on your machine.
What it does not do.
Worth knowing before you install it, and none of these are on a roadmap.
Every command is a short-lived process. Nothing watches your machine between them.
No cloud, no remote environments, no state syncing, no telemetry. That is a decision, not a roadmap item.
No staging, no preview environments, no CI runner. A bay dies when you are done with it.
devbay.yaml is committed and reviewable in a pull request. A generated file you cannot audit is worse than none.
Install it.
One binary. It needs git and Docker, and it tells you if either is unhappy before you create anything.
curl -fsSL devbay.claritty.ai/install | shThen run devbay doctor to check the machine, and devbay init in a repository to see what it proposes.