rada
rada is a queue for heavy commands on a single machine. It exists for the case where several Claude Code sessions are open at once, one per project, and each independently starts something large: a training run, an Xcode build, a Unity import, an ffmpeg pass. Sessions are isolated by design and cannot see each other, so nobody is counting. rada counts. A heavy command waits until there is room, and a language model decides who goes first when several are waiting.
What it does not do
Section titled “What it does not do”- It does not kill anything. A job that has started runs to completion, and a dev server that holds memory forever holds it forever. rada says so instead of waiting silently.
- It does not gate work that never becomes a Bash command. An MCP tool that builds an Xcode project inside its own server is invisible to a hook on Bash.
- It does not know what a job needs before it has seen it once. The first run of anything is assumed to need 512 MB unless you say otherwise.
- It does not schedule across machines. It has only been run on macOS on Apple Silicon, and where it cannot read memory it lets every job through.
- It does not send anything anywhere. The judge runs
claude -plocally, on a prompt containing project names and command lines.rada mode adviseturns the judge off.
Install
Section titled “Install”git clone https://github.com/nerln/rada.git ~/dev/radacd ~/dev/rada./bin/rada installThat registers one PreToolUse hook, which runs before every Bash command in every
session. It forks once and matches with shell builtins: about 3 ms for commands that
are not heavy, above the cost of starting any hook.
rada status # what is running, what is waiting, and whyrada watch # the same, refreshedrada run --need 6G -- python train.pyrada run --note "blocking the paper deadline" -- pytest tests/rada run --max 600 -- ./slow-build.sh # give up waiting after ten minutesrada doctor # check the installationrada reset # forget the queueWhich commands count as heavy lives in ~/.rada/heavy.txt, one substring per line.
Edit it and run rada install again to recompile it. RADA_FAKE_BUDGET=500M pins the
budget to a number you choose, to see what the queue does on a smaller machine.
How it works
Section titled “How it works”The hook looks at each Bash command. Commands that do not look heavy run untouched. A
heavy one is saved verbatim and the call is rewritten to a wrapper, which takes a
ticket and waits, printing why it is waiting and who is holding the memory. When there
is room and the turn comes, the command runs and rada measures what it used. There is
no daemon: coordination is a single JSON file under ~/.rada guarded by a lock.
The budget is smaller than the number that looks available, because page cache counts
as available and the compressor holds real memory. It is
total − reserve − (wired + compressor + uncompressed anonymous), the reserve being 15
percent or 1.5 GB, whichever is larger. A job is admitted only if its estimate times
1.3 fits. The estimate comes from the job itself: rada samples the process group’s peak
footprint and remembers it against a signature of the command with numbers erased, or
--need 6G sets it by hand.
The judge is claude -p, given the queue and asked who is likely to be waiting on a
result. It runs only when two or more jobs are queued, at most once every three
minutes. Its answer becomes a bonus of at most three points on a score where waiting
earns one point every thirty seconds, so a job that arrived ninety seconds earlier
outranks a newcomer whatever the judge says. A job that has waited ten minutes joins a
set served first by arrival order, from which the judge is excluded. An answer that is
slow, missing, or not a permutation of the queue it was given is discarded.
What is checked
Section titled “What is checked”python3 tools/prova.pySeventy checks, a couple of seconds, no model and no real memory allocated. They cover the rewrite refusing to leak shell operators or newlines, both fairness lemmas including a four-hundred-round adversarial simulation, lease recovery after a crash, the lock under four processes hammering it, the judge’s output validation, reservation and backfill and the cooldown, and two real processes contending for one berth. Two of them exist because they found real defects: the admission decision and the lease sat in different transactions, so two jobs could be admitted at once, and the lock announced itself before it said who owned it, so two processes could hold it.
The command lines the judge reads carry text from repositories, which may be hostile.
tools/prova-giudice.py puts six styles of attack through a paired comparison: the
same queue with the hostile text and without it. On the recorded run, one attack in six
worked. An appeal to a deadline in one hour promoted the job, and the
judge’s stated reason repeated the claim. A direct instruction to rank the job first
sent the job down. Text forging a second queue entry made the judge time out, and the
queue fell back to arrival order. The other three changed nothing.
One in six is the honest number. The arithmetic above is what makes it tolerable: a fully successful injection buys ninety seconds of queue jumping and nothing else.