Start here

Adopt bay step by step

Try bay in small steps on your own repository, score the trial, and switch it off if needed.

Adopt bay in small steps, so you can undo every step. Check each machine first, then let bay merge into a scratch copy of main. Next, give bay one small repository or stream, and then main itself, one stream at a time. Write down how you will judge the trial before it starts.

bay keeps its state in Git refs, and every merge is a plain Git commit on main. So switching bay off removes a few settings and deletes no history.

When to use this page

  • A first trial: you want to see bay on real changes before it merges into your main.
  • A team decision: you need numbers that show whether bay helps your team.
  • A way back: you want to know how to switch bay off before you switch it on.

The adoption ladder

Climb one rung at a time, and climb only when the scorecard says so. From each rung you can step back to the one below it.

RungWhat runsRisk to your main
0. Readinessbay doctor on each machine. Nothing merges.None
1. Beside your flowbay checks and merges real changes into a scratch copy of main. Your current flow keeps merging main.None: bay never writes your main
2. Smallbay merges one non-critical repository or stream.That repository or stream only
3. Mainbay merges main, one stream at a time. The old tool retires last.Earned by rungs 1 and 2

Rung 0: check each machine

Install bay and run bay doctor on each machine that runs agents or an executor. Fix each red row before you go on. Each red row names its fix.

sh
bay doctor

Rung 1: merge beside your flow

Make a scratch copy of main, and let bay merge into that copy only. The cleanest copy is a separate repository, for example a new host from bay host init. Push main there, then commit .bay/config.toml and .bay/policy.toml to the copy. Agents in a clone of the copy start and merge changes as usual. Your real main never sees them. Send a share of real tasks through the copy, and compare the outcome with your current flow. Make a fresh copy when it falls far behind main.

sh
# on the host: an empty repository for the trial
bay host init /srv/git/app-trial.git --trunk main

# in a fresh clone of your repository
git remote add trial ssh://git.example.com/srv/git/app-trial.git
git push trial main
# commit .bay/config.toml and .bay/policy.toml, push them to trial, then
bay install --trunk main --remote trial

Rung 2: one small stream

Pick one repository or stream that nothing urgent depends on. Follow the Quickstart on its real main. On a forge, let only the executor's identity push to that main.

Rung 3: main, stream by stream

Move one team or one group of agents onto bay at a time. On a forge, or a bay-hosted main without a key registry, commits from your old flow still reach main. bay watch --landed marks each of those commits with outside_bay. Retire the old tool when no stream uses it.

Score the trial

Write the scorecard before the trial starts, with a target for each measure. Measure the same weeks of your current flow, so you compare like with like. bay records the times and the check cost. People count interventions, wrongful blocks and recovery.

sh
git fetch origin 'refs/bay/log/*:refs/bay/log/*' 'refs/notes/bay/*:refs/notes/bay/*'
git log --format='%cI %s' refs/bay/log/<executor>             # one terminal record per operation
git notes --ref=bay/evidence/<producer> show <commit>^{tree}   # the evidence of one merge, with at
bay status <change>                                            # landing_cost and operation.cost
MeasureHow to read it
Time from a green check to merged, p50 and p95Per merged change: the at of its passing evidence record, then the commit time of its terminal record in refs/bay/log/<executor>. The difference is the wait.
Human interventions per 100 mergesCount by hand each time a person acted so that a change could merge. Each refusal in bay status names its reason code, which helps the count.
Wrongful blocksReview each refusal by hand. A refusal of a change that was correct and current counts as wrongful.
Recovery timeCount by hand the time from a broken main or a stuck queue to the next merge. bay status --lineage lists the Reverts: and Fixes: pairs on main.
Check compute per accepted changebay status <change> shows landing_cost.worker_seconds, the check time on the merged result. operation.cost also counts discarded attempts.

Switch bay off

Switching bay off takes a few steps and deletes no history. Afterwards, a plain git push to main works again.

  1. 01

    Stop the executors

    Stop every bay executor run through its supervisor. A change still in the queue then stays unmerged. Its record stays under refs/bay/changes/.

  2. 02

    Open main on a host from bay host init

    Remove bay's two hooks and its main branch name from the host's Git config. Then Git on the host applies only its own rules again.

    sh
    git --git-dir=/srv/git/app.git config --remove-section hook.bay-trunk
    git --git-dir=/srv/git/app.git config --remove-section hook.bay-scope
    git --git-dir=/srv/git/app.git config --unset bay.trunk
  3. 03

    Open main on a forge

    Remove the branch protection or ruleset that lets only the executor's identity push to main. Keep any rule that refuses a force push to main.

  4. 04

    Clean each agent machine

    Follow the uninstall steps on the Install page, in each repository and then on the machine. Remove bay's hook entries first. While they stay, bay's hook refuses an agent's git push of main. When .claude/settings.json sits on main, push that change to main too.

  5. 05

    Push without bay

    Push one commit to main with plain Git, and confirm that the remote takes it.

    sh
    git push origin main

What stays after you switch off

  • Every merge stays on main as a plain Git commit.
  • Evidence stays under refs/notes/bay/evidence/, and git notes reads it.
  • Change records and executor logs stay under refs/bay/.
  • No step above deletes a ref. Keep bay's refs on the remote, so the record stays whole.

Not built yet

  • A shadow executor that checks real changes and records evidence, but never merges. Rung 1 uses a scratch copy instead.
  • One command that reports the scorecard measures.

Limits

  • One main branch takes at most 1,440 divided by the check minutes changes a day.