Run modes
The three run modes — mock, direct, and broker — all serve the same frontend against the same RevuApi contract.
revu ships one frontend and one API contract. What changes between run modes is
only where the GitHub token comes from and how identity is stamped on the way
out — everything else is shared. The React app reads and writes through exactly
one interface, RevuApi; a run mode is just a pair of injected strategies
(a token source and a write decorator) plugged in around a single shared core of
sync engine, snapshot store, draft store, and re-anchor logic. The core never
forks per mode.
The three modes
| Mode | Status | What it is |
|---|---|---|
| Mock | Shipped | In-browser fixtures shaped exactly like GitHub REST/GraphQL. The permanent demo mode and semantics oracle — forced with ?mock=1, always available in any build, never deleted. |
| Direct | Shipped | revud --direct (or REVU_MODE=direct). Talks to real GitHub authenticated as the gh user; drafts, snapshots, and viewed state persist to a local SQLite store. The general-purpose, local-first tool. |
| Broker | Reserved | The shared-identity deployment for teams in disposable workspaces: a host injects a short-lived GitHub App token, writes are stamped and journaled per human. Designed and documented — not yet a shipped boot option. |
Broker mode is reserved
Broker mode is planned, not runnable. Only mock and direct modes boot today.
The design is written up on the broker page and in the
operator runbook, but there is no REVU_MODE=broker boot you can rely on
shipping yet.
Local reviews are not a fourth mode
A local review — two branches in your workspace compared with no pull
request behind them — is a capability inside a mode, not a mode of its own,
which is why the table above has three rows and not four. REVU_MODE is a
credential-custody and bind axis: it decides where the GitHub token comes from
and what the daemon listens on. Where a review's content came from is a
different question, and one the shared core is already indifferent to — it sees
a snapshot, not a provenance. Mock mode carries a local review as a fixture, so
the flow is demonstrable with no daemon at all.
Every mode that runs the real engine serves them, and serves the same one: the daemon discovers the repository it sits in at boot and builds one local-review surface over it, whichever mode is booting. So a workspace reviewing a branch pair behaves identically whether its GitHub calls authenticate as you or as a shared bot — and in neither case does anything about the local review reach GitHub.
One behavioural difference is deliberate and worth stating plainly: a local
review's merge base is computed against the live tip of the base branch, so
its compare key can move with zero new commits on
the head. A pull request's base SHA only refreshes when GitHub records a
synchronize event. The two paths genuinely disagree about what changed, and
the local one is chosen on purpose.
See Reviewing a local branch for the whole flow.
How the mode is selected
The daemon, revud, reads its mode from the REVU_MODE environment variable.
REVU_MODE defaults to mock. Direct mode also has an equivalent --direct
flag:
# Direct mode — env var or flag, both equivalent
REVU_MODE=direct bun run revud
bun run revud --directThe frontend on its own — bun run dev — always runs against the in-browser
mock adapter; no daemon and no GitHub token are involved. Appending ?mock=1 to
any URL forces mock mode regardless of how the rest of the environment is
configured, which is what makes the mock a reliable demo and a reliable test
oracle in any build.
One contract, one core
All three modes serve the same built frontend and answer the same RevuApi
methods. Inside revud, the shared core is wrapped by two injected strategies:
- a token source — where the GitHub token comes from (in-process fixtures
for mock, the
ghcredential chain for direct, a host-injected credential file for broker), and - a write decorator — how identity is stamped and journaled on the way out, if at all (a passthrough in direct mode, since GitHub authenticates the human for real; stamping plus an append-only audit journal in broker mode).
Because the core is shared, a cross-transport conformance suite holds every
adapter — mock, direct, and broker — to identical RevuApi semantics. The mock
is not a stub that gets deleted once the real transports land; it stays the
oracle the other adapters are checked against.
Where to go next
- Mock mode — the fixtures,
?mock=1, and the oracle role. - Direct mode — the
gh-user identity, local SQLite drafts, approve gating, and the full environment-variable reference. - Broker mode — the reserved shared-identity design.