Five Requests in Fifteen Seconds From One Status Bar Item A developer built ds_usage, a free MIT-licensed VS Code extension that displays Claude Code usage limits in the status bar, showing 5-hour and 7-day percentages with amber and red warnings at 75% and 90%. After an initial version triggered HTTP 429 rate limits from five requests in fifteen seconds across multiple VS Code windows, the developer reworked it to share cached results and fetch claims through VS Code's global storage folder, add randomized timer jitter, and enforce server-driven backoff that clicks cannot override. Claude Code knows how much of your usage limits you have left, but it shows you in a panel you have to go and open. The number belongs where you are already looking, so it went into the VS Code status bar: Claude 5h 12% · 7d 39% Hover for every limit and when each one resets; the item turns amber at 75% and red at 90%. The first version worked. The second, released the same evening, had the usage endpoint answering 429: five requests in fifteen seconds, and every one of them extended the wait. The mistake was thinking of the extension as one program. It isn't. Each VS Code window runs its own copy, with its own timers and its own event handlers, and nothing is shared between them unless you share it. So the real schedule was never "one request every five minutes". It was: Move between a few windows, click the item because the number looks stale, and you get what happened here: five requests in fifteen seconds, each one making the block longer. VS Code gives every extension a global storage folder, context.globalStorageUri , and it is the same folder in every window. That makes it the simplest place to keep a result that all of them can read. A window no longer asks the server just because it woke up. It reads the file first, and only fetches if the numbers there are older than the refresh interval: js // Fresh enough? Then this is just a render — no request. const age = last ? Date.now - last.at : Infinity; if age < manual ? CLAIM MS : s.minutes 60 000 { render ; return; } Two windows can still find the same stale file at the same moment, so the one that fetches writes a claim first, and any window that sees a claim younger than 30 seconds stays out of it: // Another window is already fetching. if cache.fetchingAt && Date.now - cache.fetchingAt < CLAIM MS return; The timers also carry up to 20 seconds of random jitter, so windows opened together don't wake together. Focusing a window now costs nothing: it re-renders what is already in the file. The worst part of the old version was the click. The item looked stuck, so it got clicked, and each click was another request to a server that had just said stop. Now a 429 sets a block, written to the same shared file so every window obeys it. Its length is whichever is longer: the server's own retry-after , or 5 minutes doubling on each repeat up to 30. js function nextBlock strikeCount, retryAfterMs { const curve = Math.min BLOCK MAX, BLOCK MIN 2 Math.max 0, strikeCount - 1 ; return Math.max curve, retryAfterMs || 0 ; } And a click cannot override it. That felt wrong to write, because a button that does nothing looks broken. So the tooltip says when the next check is due, which turns "why won't it refresh" into an answer. The very first version had the opposite problem: it treated one failure as news. The extension reads the login Claude Code already keeps: the macOS Keychain entry Claude Code-credentials , or ~/.claude/.credentials.json elsewhere. Claude Code rewrites that entry whenever it renews its login, and a read that lands in that moment comes back without a token. The status bar showed a warning where the numbers should have been, until the next poll five minutes later. Now a failure keeps the last numbers on screen, falls back to the token already held, and retries after 20 seconds, then 60, then 120. The warning appears only after three failures in a row, and the tooltip always names the last one. Nothing is hidden; it just stops shouting. Anything that reads a login should say plainly what it does with it: api.anthropic.com , shared by every window. The endpoint deserves the same honesty. It is the one Claude Code's own usage panel reads, not a published API, so a Claude Code update could change or remove it. If that happens, the extension shows a warning instead of numbers. ds usage is free and MIT licensed, on the VS Code Marketplace https://marketplace.visualstudio.com/items?itemName=devShakib.ds-usage , with the source on GitHub https://github.com/devShakib015/ds usage . Originally published at devshakib.jumyn.com https://devshakib.jumyn.com/blog/five-requests-in-fifteen-seconds-from-one-status-bar-item . I write about Flutter, Dart and the parts of shipping that are genuinely awkward — and publish the packages that came out of them at pub.dev/publishers/jumyn.com https://pub.dev/publishers/jumyn.com/packages .