Clarittydevbay

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 | sh
Seconds to your first bayLocal only no telemetryYou approve every command
$
Isolation

Two 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=alpha host=127.0.0.1:40160
cookie=session=alpha-session
logged in here
bay=beta host=127.0.0.1:41540
cookie=session=alpha-session
logged in as alpha, without asking

Bay beta received bay alpha's session. Nothing about either application is wrong and nothing appears in either log.

BayStateURL
add-search*hothttp://add-search.taskboard.localhost
fix-loginwarmhttp://fix-login.taskboard.localhost
bump-depswarmhttp://bump-deps.taskboard.localhost
retry-webhookwarmhttp://retry-webhook.taskboard.localhost
audit-logcoldhttp://audit-log.taskboard.localhost

5 bays, 20 containers, 289 MiB in total. Measured inside the VM.

$ devbay run add-search unit
pass unit in 412ms (37 passed, 0 failed, 1 skipped)
Velocity

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.

Certainty

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.

Before you agree
$ devbay new add-search
error bay: 1 command(s) in devbay.yaml have not been approved:
R2 services/web/start
./bin/dev
Read them, then run:
devbay approve
After
$ devbay approve
R2 services/web/start
./bin/dev
this runs inside the bay, with the bay’s environment and secrets
approve? [y/N] y
ok approved 1 of 1
A failing test
fail unit in 214ms (1 passed, 1 failed, 0 skipped)
test_subtraction
suite.py:42
assert 5 - 3 == 1
A bay with one broken service
add-dashboards dash mixed add-dashboards
services
grafana running http://127.0.0.1:43480
prometheus restarting http://127.0.0.1:43481
level=ERROR msg="Error loading config" file=/etc/prometheus/prometheus.yml err="expected Alertmanager api version to be one of [v2] but got v1"
Observability

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.

Zero config

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.

docker-compose.yml, yours
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
devbay.yaml, written for you
# 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.

Agents

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 environment
  • bay_listList environments
  • bay_run_taskRun a declared task
  • bay_logsRead service logs
  • bay_urlGet a service URL
  • bay_statusInspect one environment
  • bay_destroyDestroy an environment
bay_run_task, what the agent receives
{
  "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"
    }
  ]
}
Evidence

Checked against repositories nobody wrote it for.

29 of 35
real compose stacks devbay serves

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.

289
tests across 20 packages

Run under the race detector on every push. The integration packages talk to real Docker rather than a fake.

21
acceptance scenarios

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.

It is not a daemon.

Every command is a short-lived process. Nothing watches your machine between them.

It does not run your code anywhere but here.

No cloud, no remote environments, no state syncing, no telemetry. That is a decision, not a roadmap item.

It does not deploy anything.

No staging, no preview environments, no CI runner. A bay dies when you are done with it.

It does not hide the manifest.

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 | sh
Source on GitHubApache-2.0macOS and Linuxv0.4.0

Then run devbay doctor to check the machine, and devbay init in a repository to see what it proposes.