The only ad space you own.
Spinwait renders a single labelled line in your Claude Code status bar while you wait on the model. You can read every line of it, switch it off with one command, and keep 70 percent of whatever it earns.
- No account
- No network calls on the render path
- Off with one command
- Your status line survives
Four parts, all of them fixed.
An advertiser controls their name, their sentence and one colour. Everything that tells you it is an advertisement is hardcoded, which means no campaign can ever make itself look less like one.
- the diamond
- The advertiser’s colour, and the only thing they get to tint. It is clamped into a legible luminance band before it is stored, so a brand cannot render itself invisible on your terminal or blinding on someone else’s.
- sponsored
- Not themeable. The disclosure label, the separator and the domain are hardcoded to dim, so no creative choice can hide what the line is.
- brand · tagline
- Forty characters of name, eighty of sentence. Both are stripped of every control and zero-width character before storage, and stripped again by the renderer on the way out.
- domain ↗
- Where it goes if you click it. The line is an
OSC 8hyperlink, and attribution happens on our server through a redirect rather than being reported by anything running on your machine.
What it will never do.
You have every reason to assume this is adware. Here is the specific list of things it does not do, and the reason each one is true rather than just promised.
Never blocks your session
The status line does no network I/O at all. It reads two small local files, prints one row, and hands flushing to a detached background process. It cannot add latency to the thing you are already waiting on.
Never sees your code
What leaves your machine is a signed token, the event kind, the session’s cumulative API duration (
cost.total_api_duration_ms) and an opaque session id. Not your prompts, not your files, not your repository.Never renders to an empty room
Three minutes after the model last did work, the line disappears completely. A terminal left open through a meeting shows nothing, and bills nobody for it.
Never replaces your status line
spinwait initkeeps whatever you already had. Your command still runs, on the row above. Your settings file is backed up first, andspinwait uninstallputs it back.Never breaks your terminal
Advertiser text is stripped of escape sequences twice, once before storage and again in the renderer. Any failure at all falls through to the status line you already had and prints nothing of ours.
Never more than one line
One advertiser, one row. The visible creative rotates every eight seconds, and at most one impression in any 25 second window is billable. There is no second slot, because there is nothing to sell it to.
Three commands, then nothing to manage.
- Step 01
Install it
One command registers you and installs the status line. It backs up ~/.claude/settings.json first, and it wraps whatever status line you already had rather than replacing it.
- Step 02
Work like normal
While the model is thinking, one sponsored row renders under your own. When you stop working, it stops rendering. There is no dashboard to check and nothing to keep open.
- Step 03
Withdraw whenever
Connect a Stripe account once and pull your balance out when you feel like it. Ten dollar minimum, no schedule, no approval step.
Seven places to earn. One of them today.
The placement is the same everywhere: one labelled line, tied to the moment the model is working. Wherever you sit waiting on an AI assistant, that wait is yours to sell.
- Claude CodeTerminal status lineLive
- Claude Code mobileRenders, not yet billingIn testing
- Claude Code desktopDesktop app, prompt hookComing soon
- Claude web and ChatGPTBrowser extensionComing soon
- Gemini CLITerminal status lineComing soon
- Codex CLIOpenAI, terminal status lineComing soon
- VS Code, Cursor and CopilotEditor status barComing soon
And yes, it pays. Modestly.
We are not going to pretend this replaces an income. Here is the arithmetic with the caveat that matters most attached to it: these are active hours, not hours with a terminal open.
| Demand | Per active hour | 40 h/month | 80 h/month | 160 h/month |
|---|---|---|---|---|
| Uncontested, at the $8 floor | $0.336 | $13.44 | $26.88 | $53.76 |
| Contested at $15 CPM | $0.630 | $25.20 | $50.40 | $100.80 |
| Contested at $30 CPM | $1.260 | $50.40 | $100.80 | $201.60 |
When no advertiser has a funded campaign running, you earn nothing.
There is no house ad and no filler. An empty auction renders an empty line, so the table above is what the mechanism pays when demand exists, not what you should expect in your first month.
Every column is active hours, meaning hours the model is actually working. That is not the same as hours worked. A forty hour week is not 160 active hours a month, it is whatever part of those weeks you spend waiting on the model, which for most people is a fraction of the time the terminal is open. Read the 160 row as the ceiling for someone who runs an agent almost continuously, not as a full time salary.
Start in under a minute.
No signup form, no password, no login. init generates a key on your machine and asks for an email you can skip, kept only so a lost key can be recovered. Payouts run through Stripe’s hosted onboarding, so we never hold your bank details. Today this installs the Claude Code status line, which is the surface that is live.
/plugin marketplace add robert-botto/spinwait/plugin install spinwait@spinwait/spinwait:setupOr drive it directly. These are the only commands there are.
spinwait init # register, install the status linespinwait connect # Stripe onboarding, for payoutsspinwait status # balance and payout statespinwait payout # withdraw, $10 minimumspinwait off # stop rendering ads, keep everything elsespinwait uninstall # restore your previous status lineThe awkward ones.
Do I have to make an account?
No. There is no login anywhere in this product. spinwait init generates a key and stores it in ~/.spinwait/config.json, and that key is your whole identity. When you want to be paid, Stripe’s hosted onboarding collects your details, not us.
init does ask for an email, and you can press enter to skip it. It is not a login and there is no password attached to it. It exists because that key file is the only copy of your account: lose it to a wiped laptop and any balance you have not withdrawn goes with it. An address is the one thing that lets us give it back.
What actually leaves my machine?
A session id, the cumulative milliseconds you have spent waiting on the model, and the signed token for each ad that was displayed. That is the complete list.
None of it happens during the render. The status line writes queued events to a local file and a detached background process flushes them later, which is why it cannot slow your session down.
I already have a custom status line.
It keeps working. spinwait init records your existing command, runs it on every render, and prints the sponsored row underneath it. Your ~/.claude/settings.json is copied to .bak before anything is touched, and spinwait uninstall restores it exactly.
Can I turn it off without uninstalling?
spinwait off. Ads stop rendering immediately and your own status line carries on untouched. spinwait on brings it back. Nothing is reinstalled or re-registered in between.
What if nobody is advertising?
Then you see nothing and you earn nothing. There is no house ad, no filler and no placeholder. An empty auction renders an empty line, which is also the honest answer to how much you should expect to make early on.
Can I block advertisers I do not want?
Not today, and we would rather say so than imply otherwise. Every campaign is sanitised, length limited and colour clamped before it can serve, but there is no per publisher block list yet. If you hit something you object to, tell us and we will pull it.
Why should I trust the numbers?
Because you are not the one reporting them. The price is sealed into a signed token on our server before the ad ever reaches you, so a modified client cannot reprice an impression, and each token can be redeemed once.
That cuts both ways: it means you cannot inflate your own earnings, and it means the number you are credited is the number the advertiser was charged, minus our 30 percent.