Three changes to one repo. None of them touching.
Run Claude Code, Codex and opencode in parallel on one repo. Each gets its own workspace, so they cannot touch each other's work, or yours.
$ npm install -g @viraatdas/rudder@latest
Everything on one screen.
Every agent, what it is doing, and what it changed.
workspace .rudder-workspaces/rate-limit ● Read src/server/middleware.ts ● Edit src/server/rate-limit.ts +64 ● Bash npm test · 41 passed ▌ writing the burst-window test…
▌ also cap it per API key, not just per IP Understood. Keying the bucket on the API key when one is present, falling back to IP for anonymous requests. ● Edit src/server/rate-limit.ts +18 −4
jj diff · .rudder-workspaces/settings-form src/settings/Form.tsx - const [state, setState] = useState(initial) + const form = useForm({ defaultValues: initial }) + const { isDirty } = form.formState src/settings/index.tsx + import { Form } from "./Form"
ship billing v2 ✓ n0 schema migration merged ▌ n1 stripe client running │ └─ hard dep: n0 ○ n2 webhook handler waiting │ └─ hard dep: n1 ○ n3 billing settings screen waiting └─ hard dep: n0 n3 is independent of n1 and n2, so it runs as soon as n0 lands.
workspace .rudder-workspaces/rate-limit ● Edit src/server/rate-limit.ts +64 ● Bash npm test · 41 passed RUDDER_GAM_REPLY_START The bucket is keyed per API key by design. You are right that nothing covers the burst window. Writing that test now. RUDDER_GAM_REPLY_END ▌ writing the burst-window test…
read-only · cannot edit any file ● Read src/server/rate-limit.ts ● Bash npm test -- burst · 0 matched 41 passing tests do not touch the branch this task exists for. No test drives the window to its edge. RUDDER_GAM_VERDICT_START {"verdict":"revise", "message":"…"} RUDDER_GAM_VERDICT_END
Four things you can type.
What you type decides where the work lands.
| you type | what happens | where it works |
|---|---|---|
| fix the login redirect | One isolated agent Never touches your checkout. | its own workspace |
| /plan ship billing v2 | An orchestrator A task graph you can edit before it runs. Several plans can run side by side. | one workspace per node |
| /gam rewrite the retry logic | A Generative Adversarial Model pair One implements. A second one, from the other provider, reviews it and cannot edit anything. | one workspace, split pane |
| /main tag the release | An agent in your checkout For jobs that are about your tree. Nothing to merge. | your real checkout |
A model reviewing its own work agrees with itself.
So /gam runs two of them, and only one
is allowed to type.
GAM is a Generative Adversarial Model: one model generates, a second is adversarial to it, and the pressure between them is the point. The reviewer is not a gate at the end. It reads the diff after every turn, while the work is still moving, and what it sends back becomes the generator's next instruction.
What carries over is the part that matters: a critic that is genuinely separate from the thing it is criticising, and that gains nothing by being agreeable. The reviewer comes from the other provider by default, so it has nothing to be loyal to. The two never share a conversation. It is handed the original task, the diff, and whatever the generator wrote back to it, and never the reasoning that produced any of it, because a model that has read its own argument is no longer a second opinion.
| half | what it does | permission |
|---|---|---|
| generator | Implements the task Your model and provider. It answers each objection directly, and is told to say why it disagrees rather than silently comply. | writes the code |
| adversarial reviewer | Tries to refute it Reads the diff, runs the checks itself rather than trusting the transcript, and returns accept, revise or escalate. | cannot edit a file |
Every round is anchored on the task you typed, never on the last thing the reviewer happened to ask for, so a long argument cannot drift away from what you wanted. There is no round limit: it runs for as long as the argument is getting somewhere, and stops when the reviewer accepts, when it asks for you, or when the generator hands back the same diff and the same answer as the round before. Both panes stay open and Rudder tells you which it was.
The failures worth catching are the quiet ones: a subset delivered as the whole thing, a check described as run, a refusal dressed up as a completion. All three read identically to a summary, and all three are caught by reading the diff. A pair argues them out before they reach you. How it works.
Set once. The next agent picks it up.
/model sets these and remembers them. A
running agent keeps what it launched with.
Put four things in flight.
Type four tasks. Watch four workspaces fill up.
$ npm install -g @viraatdas/rudder@latest