Free seats
Every linked Mac that has no dedicated seat to carry runs on a free seat. It gets short jobs after random waits of {{freeGapMin}}–{{freeGapMax}} seconds, mines at a weight of {{freeWeight}}, and all free seats together take at most {{freeShare}} of each hour's release.
Who is on a free seat
A Mac is on a free seat when it is linked to a wallet and carries none of that wallet's dedicated seats: the wallet holds none, or it has more Macs than seats. Starter seats (Nano, Lite) count as dedicated. Seats go to the wallet's Macs that are online, biggest seat on the biggest Mac, the Mac linked first breaking a tie (carryOrder in lib/compute/seats.ts). The check is made on every job request (carriesSeat in lib/compute/rewards.ts): a Mac that carries a seat gets full jobs, every other Mac gets free-seat jobs. Once the wallet buys another seat, the next Mac's request gets full jobs.
A Mac that is not linked to a wallet gets no work at all.
The throttle
A free seat gets short jobs on a random rhythm. After each job is handed out, the Mac waits a random 1 to 9 seconds before it can have the next (COMPUTE_FREE_JOB_GAP_MIN_S, COMPUTE_FREE_JOB_GAP_MAX_S in lib/chain/curve.ts).
The wait is random but fixed per Mac and hand-out, so every server instance computes the same one (freeJobGapMs in lib/compute/seats.ts):
u = FNV-1a("<device pk>:<time of the last free hand-out, ms>") / 0xffffffff (0 … 1)
wait = round((min + u · (max − min)) · 1000) ms (min = 1 s, max = 9 s)The time of the last free hand-out is kept in wk:free:last:<pk>. When the Mac asks for a job:
- If the wait is still long, the server answers at once with
{ job: null, retryIn, throttled: true, seat: "free" }and a reason that starts with "Free seat".retryInis in seconds. - Otherwise the server holds the request for the rest of the wait, rounded up to whole seconds, and then hands out the job. Holding instead of refusing keeps older apps, which back off for a long time on an empty reply, on the same rhythm.
The same hold also covers the hand-out pacing that applies to every Mac (200 ms between hand-outs). The longer of the two is used, never both.
Short jobs
A free seat gets the short edition of the job stream: ids qwen05-2f<i>, with 32 tokens to generate (FREE_JOB_TOKENS in lib/worker/jobs.ts). Dedicated seats get the full edition, qwen05-2s<i>, with 160 tokens, back to back. Both editions use the same model and the same kind of prompt. The two editions are numbered and shared separately, so a short answer is only ever compared with other short answers to the same index. See Jobs and checks.
If a Mac changes edition while it holds a job (its wallet bought a seat, say), it is not given the old job again. It gets one from its new edition.
Delivery on a free seat
Delivery T is measured against one short job per 12 seconds (FREE_CYCLE_S in lib/compute/seats.ts): the longest wait plus a few seconds of work. A free Mac that takes every job it is offered reaches T = 1, so the throttle itself never lowers a free seat's score. See Compute rewards.
What counts as available
Availability A counts the minutes in which a Mac was eligible to work. eligible(state, reason) in lib/compute/rewards.ts decides it from the heartbeat:
state | Eligible |
|---|---|
working | yes |
calibrating | yes |
downloading | yes |
idle-waiting | only if waitingCounts(reason) |
paused | no |
off | no |
waitingCounts(reason) in lib/compute/seats.ts is true for three reasons:
Ready: the owner's limits are all met and the Mac is waiting for its next job;- any reason starting with
Free seat: it is waiting out the throttle; No work right now: the pause older apps take after the server said "not yet".
Any other waiting reason ("Waiting for power", "Outside your hours", and so on) is not eligible. A job hand-out or a result also marks its minute, even if a heartbeat was missed.
How free seats are paid
- Every Mac mines. Since 29 Oct 2026 each linked Mac without a seat to carry earns on its own free seat, so a second Mac adds its own free-seat rate to the wallet. Before, a wallet without a seat scored by its best Mac only, and Macs beyond a wallet's seats earned nothing.
- Weight 0.125 per Mac. That is its weight in the hourly split (
COMPUTE_FREE_WEIGHT), and its cap: 1 MLX a day, 0.0417 an hour. - 5 per network. In each hour at most 5 free-seat Macs on one network earn, the best scores; the others' work that hour earns nothing. The network is a one-way hash of the IP address each heartbeat came from (
cr:net:<hour>). See Fair use. - 10% cap. If free rows together would get more than 10% of the hour's release, they are all scaled down by the same factor (
COMPUTE_FREE_SHARE). - 30-day lock. MLX mined on a free seat unlocks 30 days after the day it was earned (
COMPUTE_FREE_LOCK_DAYS). See Lock-ins.
A device key costs nothing to make. It could even be a software key pretending to be a Mac. So rewards follow seats, which cost dollars. Free seats share a bounded slice of each release, no number of free Macs can take more than that slice, and many keys on one machine share one network's 5 places.
What the Mac is told
The heartbeat reply's earning says whether this Mac is on a free seat (seat: "free", throttled: true), what it can mine (perDayCap, freePerDay), and what each seat would earn on it (offers, best, maxTimes). See The worker protocol. MLX Node shows "Free seat · Throttled" and an upgrade button from these fields.