Sidecar docs
Install
Sidecar is a Claude Code plugin built on the mods API. Add the marketplace and install it from inside any Claude Code session, then run /reload-plugins:
/plugin marketplace add sidecarlol/sidecar/plugin install sidecar@sidecarOr install from a terminal with one line, then run /reload-plugins in your session:
claude plugin marketplace add sidecarlol/sidecar && claude plugin install sidecar@sidecarOnce loaded, the mod registers an anonymous device and starts earning. No account is needed until you want to be paid. The video pane opens when you send a prompt, at any width: above the prompt, or docked beside the transcript in fullscreen at 110 columns or wider. The spinner line works at any width.
To remove it, run /plugin uninstall sidecar@sidecar. Earnings already credited stay with the device.
Commands
/sidecar- Opens the Sponsored pane beside the transcript.
/sidecar pause- Stops ads and earnings until you resume. The current ad ends unpaid.
/sidecar resume- Turns ads back on from the next turn.
/sidecar link- Prints this machine's claim URL so you can attach it to your account.
/sidecar wallet- Prints today, pending and lifetime earnings, and the claim URL if not linked.
/sidecar pixels- Plays video in full pixels where the terminal supports it (Ghostty, kitty). /sidecar blocks switches back.
The pane has a Pause ads button. Closing the pane with its ✕ stops video ads for the session; the spinner line carries on.
What counts as an impression
Each turn serves one ad. The video pane's auction runs first when the pane can show, then the spinner line's, and the first paid winner is served. While a video plays, its line also runs in the spinner. You are paid once per ad. When no advertiser wins either, a Sidecar house ad fills the pane or the spinner instead. The pane marks it “House ad, not paid”; it charges no one and pays no one.
- Spinner line
- Shown for 9.5s of a running turn. A line on screen when the turn ends is settled then.
- Video pane
- Played for its full length or 15s, whichever is shorter, while the pane is drawn and Claude is working. Videos are trimmed to 30s and can finish over more than one turn. An image ad shows for 10s and counts once shown that long; up to 3 images share that time as a slideshow.
Played time only accrues while a turn runs and you are at the keyboard. An idle session, a hidden pane, a paused mod, or an ad playing to an empty chair earns nothing. The server, not the client, decides whether an impression qualified.
Views only count while you're at the keyboard. Typing in the prompt, sending a prompt or a command (yours, not a scheduled one), and pressing, scrolling or focusing the ad pane all count as activity. The prompt that starts a turn counts, so every turn starts present. After 90s without activity the video pauses, played time stops, no new ad is requested, and the pane shows “Paused while you're away”. Any activity resumes it. Each heartbeat reports how long ago your last activity was, and the server credits and charges only the part of each stretch within 90s of it.
The split
You get 50% of the clearing price of every qualified impression. It is one constant in the code, applied to the gross price the advertiser pays, before any of our costs. Example: an impression that clears at an $8.20 CPM costs the advertiser $0.0082, and $0.0041 of it is credited to you.
Unqualified impressions cost the advertiser nothing and pay nothing.
Caps
Paid impressions and installs are limited to:
- Spacing
- One paid impression per placement every 10s
- Hourly
- 120 paid impressions
- Daily
- 600 paid impressions in any 24 hours
- Devices per account
- 5 claimed devices
- Installs per network
- 10 new installs per day from one network
Over a cap, ads still serve but are not paid, and your dashboard shows the reason. Advertisers also set their own hourly frequency cap per device.
Payouts
- Pending
- Every credit is held 14 days for fraud review, then becomes available.
- Threshold
- Request a payout once $10.00 is available. The whole available balance is paid.
- Method
- Stripe Connect Express. Payouts transfer to your connected account after admin approval.
- Account
- Payouts need a signed-in account with the device claimed. Run /sidecar link and open the link to claim.
- Reversals
- Credits found to be fraudulent can be reversed. A reversal is a new negative ledger row; nothing is deleted.
Privacy: exactly what the mod sends
The mod's network calls are all in hooks/register.tsx. This is the complete list of what it sends:
- On first run
- The client name (
claude-code) and your Claude Code version. - On every request
- The device token, as a bearer header.
- At start, after each turn and every 20 minutes
- Two requests with no body: your earnings (
GET /me) and the list of video ads to download ahead of time (GET /creatives/live). The ads themselves download without your token. - When a turn starts
- Which placements it can show:
spinner, pluspaneunless you hid the pane or turned video off, and the time since your last activity. - Every 5s during an ad
- Milliseconds played, whether the ad is being watched (on screen while a turn runs), and how many milliseconds since your last activity: a key in the prompt, a prompt or command you sent, or a press in the pane. Only the time, never what you typed.
- When an ad ends
- Milliseconds played, why it ended (complete, turn ended, skipped), and the time since your last activity.
Never sent: prompts, responses, code, file names or paths, the transcript, your working directory, tool calls, environment variables, or anything about your account with Anthropic.
The server sees your IP address as any web request does. It keeps only the country Cloudflare derives from it, for advertiser country targeting, and does not store the IP. To cap new installs per network it keeps a keyed fingerprint of the address that changes daily and is deleted when the day ends. A click on an ad goes through /c/:impression to count the click, then on to the advertiser.
The auction, for advertisers
Advertisers bid CPM per placement in a self-serve, second-price auction. Ad rank is bid times a quality score (smoothed click-through rate against the platform average, clamped to 0.5 to 1.5). The winner pays the larger of the reserve and just enough to beat the runner-up ($0.0100 CPM over), never more than its own bid. A campaign with a video or image runs on both placements: it enters the video pane auction at its pane bid and the spinner line auction at its spinner bid, each held to its own reserve, and both draw on one daily and one total budget. Text-only campaigns run on the spinner line. A request returns one ad.
- Reserves
- Spinner line $1.00 CPM · Video pane $6.00 CPM
- Billing
- Prepaid balance. Only qualified impressions are charged, at the clearing price.
- Controls
- Daily and total budgets, even or as-fast-as-possible pacing, hourly frequency cap per device, country targeting.
- Reporting
- Bids, wins, win rate, impressions, clicks, spend and average clearing price per campaign.
Mod API reference
Published for transparency: these are the only endpoints the mod calls. Authenticated calls send authorization: Bearer <device token>. Money is in integer micro-dollars (1,000,000 = $1).
POST/api/v1/devicesNo token
Registers a fresh install on first session start. The token is stored in the plugin's own store on your machine; only its SHA-256 hash is kept on the server.
{ "client": "claude-code", "version": "2.1.287" }{ "deviceId": "dev_…", "token": "sdc_…", "claimCode": "K7QM-2XPD" }POST/api/v1/ads/request
Asks for an ad when a turn starts. Runs the video pane's auction when the pane can show, then the spinner line's, serves the first paid winner, and only when neither fills serves a Sidecar house ad. Mints the impression with the server's clock. idleMs is the time since your last activity; past 90s there is no auction and the answer is no ad.
{ "placements": ["spinner", "pane"], "idleMs": 1200 }{ "ad": {
"impressionId": "imp_…", "creativeId": "…", "format": "video",
"advertiser": "Acme", "headline": "…", "body": "…", "spinnerText": "…",
"ctaLabel": "Learn more", "clickUrl": "https://…/c/imp_…",
"framesUrl": "https://…/api/v1/creatives/…/frames",
"durationMs": 15000, "viewerMicros": 4100, "posterColor": 1710618
} } // or { "ad": null }POST/api/v1/impressions/:id/beat
Every 5 seconds while an ad runs. The server accepts played time only up to the wall-clock time since the last beat plus 1.5s, only while the ad is being watched (a turn running and, for video, the pane drawn), and only for the part of the stretch within 90s of your last activity (idleMs). A client that reports no idleMs is never credited.
{ "playedMs": 7200, "isWatching": true, "idleMs": 4000 }{ "playedMs": 7200, "requiredMs": 15000 }POST/api/v1/impressions/:id/complete
When the ad finishes, the turn ends, or you pause. Settles the impression once: qualified (advertiser charged, you credited) or not, with a reason. Impressions whose client goes quiet are settled from their last beat after a minute.
{ "playedMs": 15000, "reason": "complete", "idleMs": 9000 }{ "isCredited": true, "creditedMicros": 4100, "reason": null,
"wallet": { "todayMicros": …, "pendingMicros": …, "lifetimeMicros": …,
"isClaimed": false, "claimUrl": "https://…/earn/claim?code=K7QM-2XPD" } }GET/api/v1/me
The wallet the pane and footer hint show. Also what /sidecar link and /sidecar wallet print.
{ "wallet": { "todayMicros": 310000, "pendingMicros": 4120000,
"lifetimeMicros": 18400000, "isClaimed": true, "claimUrl": "…" } }GET/api/v1/creatives/:id/framesNo token
The video as a terminal frame pack the mod draws as a raster. Public and cacheable; it carries nothing about you.
{ "width": 64, "height": 36, "fps": 10, "count": 150, "rgb": "<base64 RGB frames>" }