A Tamagotchi for your AI coding CLI. A virtual pet that lives in your terminal and feeds on the tokens your coding agents burn β Claude Code, OpenAI Codex, Gemini CLI, Qwen Code, opencode, Charm Crush. The more you use them, the more your pet grows β and every ~1,000,000 tokens it evolves into a brand-new creature that reflects what you're currently working on.
Coding a food-production pipeline? Your pet becomes a little chef-egg. Switch to a legal contract review? It morphs into a book-monster with a gavel. The art is generated on the fly by Claude itself, then rendered as animated, transparent pixel art using Unicode half-blocks β right in your terminal, over SSH, inside tmux.
It's a joke project. It's also a completely serious one: LLM cost scales with tokens, so watching a pet fatten on your token spend is the most honest usage meter there is.
Left: the animated canvas pet in its own pane. Right: the tiny grid pet in Claude Code's statusline. Both feed off your token total β same level + progress, each its own creature.
tokengotchi is a standalone, read-only process. It does not install into any of these tools, does not touch their config or status lines, and does not use a separate API key. It just watches and reacts.
each CLI's local session logs (Claude/Codex/Gemini/...)
β read-only
βββββββββββββΌβββββββββββββ
β PROVIDERS (per tool) β tokens + topic per session
βββββββββββββ¬ββββββββββββββ
β
βββββββββββββΌβββββββββββββ
β WATCHER β sum tokens Β· find active topic
βββββββ¬ββββββββββββββ¬ββββββ
token β β every frame
milestone OR β β
topic shift β β
βββββββββββββββΌβββ ββββββββΌββββββββββββ
β SLOW CLOCK β β FAST CLOCK β
β regenerate art β β play animation β
βββββββββ¬ββββββββββ ββββββββ¬ββββββββββββ
claude -p β canvas HTML β half-block render
playwright β 12 PNGs β ~10fps, flicker-free
pixel pipeline β frames βββββββββ β your terminal pane
Two signals, deliberately separated (so multiple sessions β and multiple tools β Just Work):
- Tokens = the food. A global sum across every session in scope, across every coding CLI you use. Run Claude Code in three directories and Codex in a fourth β they all feed one pet.
- Topic = the look. Taken from the single active session β the transcript most recently written to (newest mtime = the pane you're typing in), whichever tool it belongs to. Switch panes/projects/tools and the pet re-themes.
tokengotchi reads each tool's local session logs read-only. It auto-detects which
are installed; override with --provider (repeatable) or the providers config.
| Provider | Tool | Source | Tokens |
|---|---|---|---|
claude |
Claude Code | ~/.claude/projects/**/*.jsonl |
β |
codex |
OpenAI Codex CLI | ~/.codex/sessions/**/rollout-*.jsonl |
β |
gemini |
Google Gemini CLI | ~/.gemini/tmp/*/chats/session-*.jsonl |
β |
qwen |
Qwen Code | ~/.qwen/**/chats/*.jsonl |
β |
opencode |
opencode (sst) | ~/.local/share/opencode/opencode.db (SQLite) |
β |
crush |
Charm Crush | <data-dir>/**/*.db (SQLite) |
β |
python -m tokengotchi --list-providers # show known + detected
python -m tokengotchi --provider claude --provider codex # watch just theseNot (yet) supported because they don't persist token counts locally: Cursor CLI
(server-side usage) and the Antigravity IDE (opaque protobuf + RPC). Adding a
provider is ~30 lines β see tokengotchi/providers/.
Two clocks:
- Fast clock (free, always running): replays the current creature's frames ~10Γ/sec with in-place redraw β no flicker, no clear-screen.
- Slow clock (costs tokens, rare): on a token milestone or a sharp topic shift, it asks Claude to draw a new creature and hot-swaps it in β the old pet keeps dancing until the new one is ready. Two art types depending on target: canvas (pane mode β rich, animated) or a direct 10Γ10 pixel grid (statusline β tiny, crisp; see Statusline mode).
Self-critique gate (canvas): the pixelated result is shown back to Claude (just 2 frames β cheap) to judge the creature: legible, on-topic, and genuinely multi-colored (a dull one-hue blob fails). If not, it recolors/redraws and retries (up to 2Γ). Background transparency is not the critic's job β it's stripped deterministically in code, so no tokens are spent on it.
Requires Python 3.11+, and (only for regenerating art) Node 18+ and the
claude CLI you're already logged into.
git clone https://github.com/yourname/tokengotchi
cd tokengotchi
# Python deps
pip install -r requirements.txt
# (optional, for live art generation) the headless capture toolchain
cd js && npm install && npx playwright install chromium && cd ..You can run the pet without Node/playwright/claude β it ships with a
bundled default creature and will happily animate + count tokens. The art only
regenerates when the capture toolchain and claude CLI are present.
In its own terminal (a tmux split beside your coding CLI works nicely, but isn't required β it auto-fits whatever window it's in):
python -m tokengotchi # global scope, default 1M-token evolutionsUseful flags:
python -m tokengotchi --status # print token total + topic, then exit
python -m tokengotchi --once -v # one poll tick, log what it'd do
python -m tokengotchi --regen-tokens 250000 # evolve 4Γ as often
python -m tokengotchi --scope project --project ~/.claude/projects/-home-you-myproj
python -m tokengotchi --scale 2 # bigger pet (2Γ nearest upscale)
python -m tokengotchi --config config.tomlPress Ctrl-C to quit (Claude Code is never touched).
Rendering uses 24-bit truecolor + Unicode half-blocks (β). It works in tmux
(falls back to default background for transparency). Sixel/kitty graphics are
not required β that's deliberate, so it works over plain SSH. Make sure your
terminal has truecolor (COLORTERM=truecolor).
Claude Code is the one CLI with a statusLine hook an external command can fill,
so the pet can live in its status bar (like the /buddy Easter egg). Every other
CLI uses pane mode β they have no equivalent surface.
Two art pipelines, by target (each mode generates only its own type β no wasted tokens):
- Pane mode β canvas: Claude writes an HTML canvas (vivid multi-hue creature), captured β background stripped transparent for free (flood-fill, no LLM) β downscaled to ~46px β animated. A cheap self-critique (2 frames) judges only the creature (legible + colorful); transparency is handled in code, not tokens.
- Statusline β direct pixel grid: Claude emits a tiny 10Γ10 sprite (palette + char grid) rendered straight to half-blocks β no browser, no downscale, crisp at corner size. Bright saturated edges (no dark outline β it'd vanish on the black terminal), flat distinct-hue colors, silhouette-first.
Level, mood + progress. The bar shows three things: πͺ total fed, a
mood, a level (Lv = total tokens Γ· regen_tokens β an achievement
counter that climbs with spend), and a bar to the next evolution. Mood comes
from a mechanical signal (smoothed feed-rate + idle) picking a slot
(asleepβ¦hyper); the wording of each slot is LLM-authored per creature at
regen (a dragon "hoards", a frog "ribbits") β zero per-poll cost.
These shared bits (level + progress) are derived from the token total, so the
pane and statusline show the same numbers without sharing any state file
(race-free); only the art and mood vocabulary are per-mode (each its own
creature). Pane and statusline state live under ~/.tokengotchi/{canvas,grid}/.
Caveats worth knowing first: the statusline re-runs per assistant message
(300ms debounce, or refreshInterval β₯ 1s), so the corner pet is near-static
β it changes mainly when it evolves, not frame-by-frame. Pane mode is the
animated one. It also needs the background daemon running to stay live.
Install (two ways β see INSTALL_STATUSLINE.md):
# Path A (recommended): let Claude Code edit its own config β paste the prompt
# from INSTALL_STATUSLINE.md into Claude Code; it backs up + merges + explains undo.
# Path B (deterministic): backs up settings.json, merges any existing statusline
python -m tokengotchi --install-statusline
python -m tokengotchi --daemon & # keeps tokens + art liveBy default the statusline is meter only (statusline_rows = 0). To show the
10Γ10 grid pet, set statusline_rows = 5 in your config (see config.example.toml).
Remove β one key, fully reversible:
python -m tokengotchi --uninstall-statusline # restores your previous statusline
# or just delete the "statusLine" key from ~/.claude/settings.jsonSafety: install always writes a timestamped settings.json.tokengotchi-bak-<ts>,
never discards an existing statusline (it chains yours + the pet), and the frame
command is a lightweight PIL-free entry (~45ms) that emits color codes only β no
cursor-movement codes that could corrupt the bar.
Every knob lives in config.example.toml (copy it to config.toml). Highlights:
| Key | Default | Meaning |
|---|---|---|
regen_tokens |
1_000_000 |
tokens per evolution |
scope |
global |
global / project / session |
topic_shift |
true |
also evolve when the topic changes sharply |
fps |
10.0 |
animation speed |
width |
46 |
pixel-art width (chars) |
scale |
1 |
on-screen upscale |
max_critique_retries |
2 |
art-quality retry budget (canvas) |
critique_frames |
2 |
frames the canvas self-critique reads (was all 12) |
art_mode |
auto |
auto (pane=canvas, daemon=grid) / canvas / grid |
grid_size |
10 |
statusline sprite NxN (10 β 5 rows) |
statusline_rows |
0 |
corner-pet height in rows (0 = meter only; set 5 for the 10Γ10 grid pet) |
statusline_truecolor |
true |
false = meter only on terminals that mangle 24-bit |
Everything tokengotchi generates lives in one work dir (default
~/.tokengotchi): the per-mode pets (canvas/, grid/), their frames, caches,
and state.json. Deleting it resets the pet β it just regrows from your tokens
next run. (If you set a custom work_dir, delete that path instead.)
Remove generated art + state
# macOS / Linux
rm -rf ~/.tokengotchi# Windows PowerShell
Remove-Item -Recurse -Force "$HOME\.tokengotchi":: Windows cmd
rmdir /s /q "%USERPROFILE%\.tokengotchi"Remove the statusline pet (restores your previous Claude Code statusline; a
timestamped backup sits at ~/.claude/settings.json.tokengotchi-bak-*):
python -m tokengotchi --uninstall-statusline
# delete the leftover backups too, if you want:
rm -f ~/.claude/settings.json.tokengotchi-bak-* # macOS/Linux
# PowerShell: Remove-Item "$HOME\.claude\settings.json.tokengotchi-bak-*"Remove the headless browser used for canvas capture (optional, frees a few hundred MB):
python -m playwright uninstall # or delete the cache dir:
rm -rf ~/.cache/ms-playwright # Linux
rm -rf ~/Library/Caches/ms-playwright # macOS
# Windows PowerShell: Remove-Item -Recurse -Force "$env:LOCALAPPDATA\ms-playwright"
rm -rf js/node_modules # the capture toolchainFull uninstall: stop the daemon (pkill -f "tokengotchi --daemon" / end the
process on Windows), run --uninstall-statusline, delete ~/.tokengotchi, then
pip uninstall tokengotchi if you installed it.
tokengotchi/
tokengotchi/ # the package
providers/ # one module per coding CLI (claude, codex, gemini, ...)
transcript.py # pure Claude JSONL parsing (tokens + text)
config.py # TOML + defaults
state.py # atomic persisted state
watcher.py # provider-agnostic token sum, active topic, triggers
regen.py # canvas art: prompt β claude -p β capture β pixelate β critique
gridart.py # grid art: claude -p emits a tiny 10x10 sprite, rendered direct
pipeline.py # frames β shared-palette low-res pixel art
renderer.py # PIL image β truecolor half-block ANSI
player.py # threaded flicker-free playback
statusline.py # optional Claude Code corner pet (frame cache + safe install)
vitals.py # mood (feed-rate/idle β LLM-authored expression) + evolve progress
pet.py # orchestrator + CLI
js/capture.js # playwright: canvas β transparent PNG frames
assets/ # bundled default pet
tests/ # pytest suite (143 tests) + node smoke test
pip install -r requirements.txt pytest
python -m pytest # 143 tests
node js/test_capture.mjs # capture smoke test (skips if playwright absent)
python assets/make_default.py # rebuild the bundled default pettokengotchi reads your coding CLIs' session logs locally (read-only) to count
tokens and sample the current topic. When it regenerates art it sends a short
description of your recent topic to Claude via the claude CLI. Nothing else
leaves your machine. It writes only to its own work_dir (~/.tokengotchi by
default).
MIT β see LICENSE.
