Claude Code does your job. You do push ups. That's the deal.
It counts the tokens Claude just burned doing your work, turns them into reps you owe, and puts the number in your status line where you can't ignore it.
Full clip with sound · vertical cut
Nothing is blocked, nothing is gated, your prompts always go through. It just watches and adds up.
Needs bash, jq and awk.
git clone https://github.com/Deorbiting/claude-pushups.git
cd claude-pushups
./install.shRestart Claude Code. Got a status line already? It's kept, and the reps get
stapled on the end of it. ./uninstall.sh puts everything back.
pu # what you owe
pu done # cleared 47. sure you did.
pu 20 # paid 20. 27 still owed.
pu skip # write it off
pu tier rat # switch tierInside Claude Code put a ! in front: ! pu done.
Debt survives turns, sessions and restarts. Only pu clears it — but it can't
run away either. You can never owe more than a day's worth (75 at the default
tier). Anything above that rots, and is logged as a lapse rather than quietly
dropped:
owed: 75 — shut up and push
lapsed: 265 left to rot (ceiling is 75)
Past a certain size a number stops being a target and becomes wallpaper, so the ceiling keeps the debt doable and moves the shame onto how much you let rot.
name tokens/rep cap/turn cap/day
fat fat fuck 4000 15 30
cuck claude cuck 2000 35 75 ← default
rat gym rat 1000 60 150
roid roid monkey 600 99 250
pu tier roidEach tier talks to you differently. Find out.
pu tone toxic # considerably worse
pu tone normal # backOff by default. Nobody but you ever sees it.
It doesn't notify every turn — that gets muted within an hour, which defeats the
whole thing. A notification fires only when you actually earned reps, and at
most once every 10 minutes, unless reps lapsed, which is worth knowing
straight away. Set PU_NOTIFY_COOLDOWN (seconds) to change it.
The message asks for a number you might actually do rather than reciting the total, since 75 gets ignored and 20 doesn't:
35 reps. I did your entire fucking job. get on the floor.
· drop and give me 20, then: pu done
It's all in talk.txt, one line each:
tier|kind|text # tier "*" hits every tier
roid|jab-mid|your delts are lying
fat|tally-low|{n} reps. that is one advert break, fatty.
jab-low/jab-mid/jab-high/jab-max— status bar, at debt ≤20, ≤50, ≤100, 100+. Keep under 28 characters or the line wraps.tally-zero/tally-low/tally-mid/tally-high— turn-end notification, at 0, ≤10, ≤30, 30+ reps.{n}is the number.
Drop your own talk.txt into ~/.claude/pushups/ and it overrides the shipped
one. Hermes uses $HERMES_HOME/pushups/talk.txt instead (normally
~/.hermes/pushups/talk.txt). git pull won't touch either file.
pu anim # list them
pu anim jack # switch
pu anim none # offflex ᕦ(ò_óˇ)ᕤ ᕦ(ò_ó )ᕤ dots ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏
jack \o/ )o( /o\ )o( bar [= ] [ = ] [ = ] [ =]
pulse ▁▃▅▇ ▃▅▇▅ ▅▇▅▃ ▇▅▃▁ beat ♥♡ ♥♥ ♡♥ ♡♡
Two of them use a second row:
press \o/ _o_ /o\ spin ▛▀ ▀▜ ▄▟ ▙▄
‾‾‾ ‾‾‾ ‾‾‾ ▙▄ ▄▟ ▀▜ ▛▀
It reacts to what's happening. Each set defines up to three states, and a set
that only defines work falls back to it:
| state | when |
|---|---|
work |
a turn is running and reps are climbing |
capped |
this turn hit the per-turn cap |
owed |
turn over, debt outstanding |
Add your own to anim.txt — name|state|frame|frame|..., splitting rows on ^:
worm|work|~- |-~- | -~|-~-
worm|owed|_-_
tower|work|▄ ^▀ |▄▄^▀▀| ▄^ ▀
Two rules, both enforced by test.sh: every frame in a set needs the same
number of rows, and corresponding rows need the same number of characters,
or the status line shunts sideways on every tick. A trailing | makes an empty
frame and will fail.
The status line is event-driven, so install.sh sets "refreshInterval": 1 in
your settings. Without it the animation and the live counter freeze during a
long tool call. If you installed before this existed, add it by hand:
"statusLine": { "type": "command", "command": "...", "refreshInterval": 1 }This project also supports Hermes Agent without changing Hermes core files. It
uses profile-local plugin hooks to count output tokens across every API call in
a turn and adds the existing +5 rep subagent bonus. In Hermes' modern TUI it
publishes debt through the existing internal notification event spine, which
puts 💪 N owed in the real status bar without modifying Hermes core files.
Classic/non-TUI sessions fall back to appending the tally to the final response.
Billing/credits warnings always take priority over push-up debt.
Install in the default/current profile only:
./install-hermes.shFor an explicitly named profile:
./install-hermes.sh profile-nameRestart Hermes after installation, then use:
/pu
/pu done
/pu 20
/pu tier rat
From a regular shell, hpu provides the same ledger commands. Hermes state is
kept under $HERMES_HOME/pushups (normally ~/.hermes/pushups), so profiles do
not share debt. ./uninstall-hermes.sh removes the plugin link but preserves
the ledger.
Reps come from output tokens, not the clock, so you don't get billed while you
read a permission prompt. Subagents are +5 each. Ledger lives at
~/.claude/pushups/ledger.
| macOS | everything |
| Linux | everything, notifications need notify-send |
| Windows, Git Bash or WSL | works, no desktop notification |
| Windows, no bash | no |
bash test.sh — 35 asserts, no framework.
No streaks, no leaderboard, and nothing checks that you actually did them.
MIT.
