Left: the app running. Right: the can over
dietclaude watch.
A Diet Coke can that drains as you use your Claude limits.
It lives in your terminal, in the Claude Code status line, and in a floating macOS
window that sits above everything.
This is an unofficial command line port of Diet Claude, a Chrome extension (Chrome Web Store). The idea, the name, and the draining soda can are the work of its authors. All credit for the concept goes to them.
This repository shares no code and no artwork with that extension. Every pixel here is drawn from scratch: terminal cells in Python, Core Graphics in Swift. The data comes from a different place too, the Claude Code status line, not the claude.ai web page.
This project is not affiliated with, endorsed by, or connected to the Diet Claude authors, Anthropic, or The Coca-Cola Company. "Diet Coke" and the can design are trademarks of The Coca-Cola Company. "Claude" is a trademark of Anthropic. The can here is a hand drawn homage.
| Part | What it does |
|---|---|
| Status line | One line under your Claude Code prompt: a small can, the percentage left, and the refill time |
dietclaude watch |
A full can in the terminal. It drains while you work |
| Mac overlay | A borderless window that floats above your terminal and draws the can at 60 frames per second |
| Notifications | One macOS notification when usage crosses 70% and 90% |
Claude Code gives a JSON object to any statusLine command. That object holds:
rate_limits.five_hour.used_percentageand.resets_atrate_limits.seven_day.used_percentageand.resets_atcontext_window.used_percentage,cost.total_cost_usd,model.display_name
dietclaude statusline reads that JSON, prints one line, and saves the reading to
~/.dietclaude/state.json. Every other part reads that file. The tool reads no
credentials and makes no network calls.
rate_limits appears only for Claude.ai Pro, Max, and Team accounts, and only after the
first API response in a session. Before that, the can shows ?.
Because the status line is the only writer, the can drains while a Claude Code session runs. With no session open, the can holds the last reading and says how old it is.
- macOS
python3(the one Apple ships is enough). No third-party packages- Claude Code 2.x, on a Claude.ai subscription
- Xcode command line tools, for the Mac app only
git clone git@github.com:RO-29/dietclaudecli.git
cd dietclaudecli
./install.sh # link the CLI, add the can to the status line
./install.sh --with-app # the same, and build and start the Mac app
./install.sh --no-statusline # only link the CLIinstall.sh links dietclaude into ~/bin. Set DIETCLAUDE_BIN to pick another
directory.
Adding the can to the status line copies ~/.claude/settings.json to
settings.json.dietclaude-bak first. If you already have a statusLine command, it is
kept: install saves it as chain and runs it before the can, on its own row.
ln -sf "$PWD/dietclaude" ~/bin/dietclaude
dietclaude install # the status line
mac/build.sh # the app, into ~/Applications
dietclaude overlay startdietclaude overlay stop
dietclaude uninstall # puts your old status line back
rm ~/bin/dietclaude
rm -rf ~/.dietclaude "$HOME/Applications/Diet Claude.app"dietclaude # both cans, once
dietclaude watch # live cans, they drain while you work
dietclaude watch --demo # animate a full drain
dietclaude watch --only five_hour --fps 12
dietclaude can --mini # the one-line form
dietclaude can --used 88 # preview any level
dietclaude json # the saved reading
dietclaude overlay # start the floating Mac can
dietclaude overlay stop|restart|status|buildThe app is ~/Applications/Diet Claude.app. It has no Dock icon and never takes the
keyboard, so your terminal keeps focus. It puts a 🥤 item in the menu bar with the
percentage, and that menu holds every setting:
Click the can to pour a fresh one. It drops to empty, fills back up to your real
reading, and the slurp plays while it rises. A drag still moves the can; a click that moves
it nowhere counts as a click. The slurp is synthesised, not sampled — tools/make_slurp.py
builds mac/Resources/slurp.wav from noise, a swept filter, and a few bubble pops.
| Menu item | Result |
|---|---|
| Pour a fresh one | The same as clicking the can |
| Slurp sound | Play the slurp on a pour. On by default |
| Show the weekly limit | Swap the can between the 5-hour and the 7-day window |
| Click through the can (stops dragging) | Mouse events pass to the window below |
| Grey panel behind the can | Draw a translucent card behind the can. Off by default |
| Size | Tiny, Small, Medium, or Large. Small by default |
| Move to the bottom right | Put the can back in the corner |
| Quit Diet Claude | Stop the app |
Drag the can to move it. The app saves the position and every setting in UserDefaults
under com.rohit.dietclaude.
Click-through removes the only drag handle. With it on, the app ignores every mouse event, so you cannot drag the can and you cannot open its menu. Turn it off from the menu bar item, or run:
defaults write com.rohit.dietclaude clickThrough -bool falseThe can refills on the clock. state.json changes only while a Claude Code session paints
its status line, so at the limit the last reading freezes. The app compares resets_at
with the clock and rolls the window forward, and the footer then reads Refilled.
The app also remembers the last reading that had numbers in it. A fresh Claude Code
session reports no rate_limits until its first API reply, so without that memory the can
goes blank every time you restart. The footer says idle when nothing has written for ten
minutes. Check what the app would show, without a screen — source says whether the
numbers came from the file or from memory:
"$HOME/Applications/Diet Claude.app/Contents/MacOS/DietClaude" --checkThe app can draw itself without a screen. One frame to a PNG:
"$HOME/Applications/Diet Claude.app/Contents/MacOS/DietClaude" \
--snapshot /tmp/can.png --level 42 --frames 120 --no-panel --dark --scale 0.76--scale draws the can at one of the menu sizes. The whole view is laid out in fractions
of its own width, so the can, the type, the hairlines, and the readout scale together.
--no-panel draws the can alone on a clear background, the way the app now floats it.
--dark picks the dark system appearance, so the readout comes out light.
A whole animation, one numbered PNG per step, which is how docs/overlay.gif is made:
"$HOME/Applications/Diet Claude.app/Contents/MacOS/DietClaude" \
--sequence /tmp/frames --from 100 --to 4 --count 56 --fps 20 --no-panel --darkstatusline sends one macOS notification each time usage crosses 70%, then 90%, and says
the same line out loud with say. It alerts once per threshold per limit window.
dietclaude config --set voice=false # keep the notification, drop the voice
dietclaude config --set notify=false # drop both
dietclaude config --set thresholds='[50,80,95]'~/.dietclaude/config.json:
| Key | Default | Result |
|---|---|---|
notify |
true |
Send macOS notifications |
voice |
true |
Say the alert out loud with say. notify: false silences it too |
sound |
false |
Play a sound in watch |
thresholds |
[70, 90] |
Used percentages that send a notification |
chain |
null |
Status line command to run before the can |
fizz |
true |
Draw bubbles in the liquid |
mini_width |
10 |
Can width in the one-line form |
mini_both |
false |
Draw the weekly can in the one-line form |
The liquid is Claude orange above 25% left, amber from 25% to 10%, and dark red below
10%. The terminal can uses 24-bit colour when COLORTERM is truecolor, 256 colours
otherwise, and plain text when NO_COLOR is set.
| Path | Holds |
|---|---|
dietclaude |
The CLI |
_render.py |
The terminal can |
mac/main.swift |
The floating Mac app, one file |
mac/build.sh, mac/Info.plist |
The app build |
tools/make_demo_gif.py |
Rebuilds docs/demo.gif from real terminal output |
tools/make_overlay_gif.py |
Draws docs/overlay.gif; the app renders every frame |
tools/make_overlay_webp.py |
Draws docs/overlay-light.webp and -dark.webp, both with a clear background |
tools/make_slurp.py |
Synthesises mac/Resources/slurp.wav, the pour sound |
tools/record_overlay.py |
Records docs/overlay.gif from the running app instead |
tools/make_hero_gif.py |
Rebuilds docs/hero.gif, the can over the terminal |
tools/make_social_preview.py |
Rebuilds docs/social-preview.png, the GitHub share card |
install.sh |
Local install |
~/.dietclaude/state.json |
The last reading |
~/.dietclaude/config.json |
Your settings |
MIT. See LICENSE.
