Auto-merge pull requests, behind locks

Rusuban merges a pull request on its own only when two things agree. Your rules say this kind of PR may merge without a person, and eight gates pass on the exact commit it checked. Agents never merge: the server does, or nothing does.

At a glance

Who decides a PR may merge aloneA Claude Code judge, from the rules in your repo
Who mergesRusuban's server, never an agent
What it checksCI, reviews, review threads, mergeability, the judgment, your locks, a recorded proof, the merge switch
On which commitThe head it checked, with gh pr merge --match-head-commit
How fastAt most one merge per read of the project, every 90 seconds by default
Your overrideA card's merge option merges that head once CI, threads, conflicts and the switch allow
The off switchOne switch in the dashboard's header pauses every merge

How a PR comes to merge

  1. Your rules say which PRs may merge alone. For example: "A bug fix with a test merges alone. A new dependency comes to me."
  2. A judge reads the PR against them and decides, for that head, whether it may merge without a person, and why.
  3. The server computes eight gates from live GitHub state, at every read.
  4. When all eight pass and merges are armed, it merges that head and journals the merge with its gates. A new commit sends the PR back to the judge.

A PR that does not merge shows, on its node in the dashboard, the first gate that stops it.

The eight gates

GatePasses when
CIAt least one check on the head, each one green, neutral or skipped, none pending, failed or waiting for an approval
ReviewsNo latest review of the head requests changes, and every required reviewer reviewed it
ThreadsNo review thread is open
MergeableNot a draft, no conflict, and rebaseable when the repo merges by rebase
JudgmentThe repo has rules, and the PR was judged on this head to merge alone
LocksIt touches neither .rusuban/ nor a locked path, renames no file, and stays within your size limits
EvidenceA proof is recorded on its head when it needs one
SwitchMerges are armed

The locks reference lists each gate's exact conditions.

Your locks

A repo adds its own locks in .rusuban/locks.json: paths a PR may not touch alone, size limits, required checks and reviewers, and zones that need a proof, such as a benchmark.

{
	"lockedPaths": [".github/**", "package.json"],
	"maxLines": 300,
	"requiredChecks": ["test"]
}

No text lifts a lock, not even your rules. A locks.json that does not validate stops every merge of its repo until it is fixed, so a typo never leaves a lock silently missing.

Locks that always hold

  • CI green on the exact head, with at least one check.
  • No open review thread.
  • The head unchanged since the judgment.
  • The rules never change without a person. A PR that touches .rusuban/ never merges alone.
  • No direct push to a default branch. It is denied to agents, and a commit that reaches the branch outside a PR is flagged.

Compared with GitHub's auto-merge

GitHub's auto-merge, once someone turns it on for a pull request, merges it when the branch's required reviews and status checks pass. Rusuban decides from your rules which PRs may merge at all, then checks its own gates whatever the branch requires: no open thread, the head it judged, your path and size locks. A PR merged another way, by a person or by GitHub's auto-merge, is flagged as a merge Rusuban did not make.

Get started

  1. Install Rusuban and keep merges paused at first.
  2. Write in your rules which PRs may merge alone, and put in locks.json what the server must check itself.
  3. Read the judgments for a while, then arm the switch.