Skip to content

About

Use your tokens to raise, evolve, and collect Pokémon! 🥚

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

PokeTokenBar icon

PokeTokenBar

Your AI coding tokens, hatched into Pokémon — right in your menu bar.

Release macOS Swift Homebrew License Sponsor

English · 한국어 · 日本語

PokeTokenBar turns the AI coding tokens you're already burning — Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, Hermes Agent, Cursor, Grok CLI, Copilot CLI, Kiro CLI & Pi Agent — into a growing Pokémon companion in your macOS menu bar. Spend tokens, hatch an egg, evolve it through its real evolution line, graduate it into your Pokédex, and start again. Underneath the companion it's a precise usage tracker — today's spend, cost, and official 5-hour / weekly limits, read straight from your local logs.

Token usage is read directly from local Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, Hermes Agent, Cursor, Grok CLI, Copilot CLI, Kiro CLI, and Pi Agent data (totalTokens = input + output + cache, local date) — no external CLI needed. Unofficial, non-commercial Pokémon fan project — see License & disclaimer.

Why

  • The usage tracker you actually enjoy opening. Your spend raises a Pokémon that hatches, evolves, graduates, and fills a Pokédex — and every shiny is a reason to check back.
  • See today's token spend & cost at a glance — no dashboard, no browser tab.
  • Track official 5-hour / weekly limits with reset countdowns and a burn-rate forecast for when you'll hit them.
Popover home — companion, today's tokens, official limits

How it works

  1. 🥚 Code as usual. The tokens you burn in Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, Hermes Agent, Cursor, Grok CLI, Copilot CLI, Kiro CLI, or Pi Agent incubate an egg — nothing extra to run.
  2. 🐣 Hatch. Eggs hatch into Pokémon with real evolution lines from PokéAPI — any Gen 1–5 line (329 possible starts), weighted by the official capture rate: commons hatch often, a legendary is a 1-in-129 event. It appears in your Pokédex immediately while you raise it. Every hatch rolls one of 25 natures — and once in a rare while, the egg hatches ✨ Shiny.
  3. ⚡ Evolve. Keep coding and it grows through its actual evolution tree (1/2/3 stages, branching), with a little flash celebration at each step.
  4. 🎓 Graduate & collect. Final form + threshold permanently archives it in your Pokédex — rarer takes longer (≈3 days common → ≈24 days legendary at heavy use) — and a fresh egg arrives.
  5. 🍬 Max out, get a candy. Fill a 5-hour or weekly usage limit and you earn Rare Candy — spend it from the Bag to grow your current Pokémon.
  6. 🛒 Spend at the Shop. Every token you've used is spendable currency — buy Rare Candy, a Mint that re-rolls your Pokémon's nature, a Shiny Charm that permanently raises your shiny odds, or an egg to send off your current companion and start over. Eggs come in three grades: a plain Pokémon Egg, an Uncommon Egg guaranteed to hatch Uncommon or better, and a Rare Egg guaranteed to hatch Rare or better.

Tour

Floating desktop pet with a hover callout and right-click menu

🐾 Let it live on your desktop

Move your companion out of the menu bar and onto the desktop, at any size from 48 to 384px. Hover it for today's usage, click to open the popover, right-click for a menu, drag it wherever you like — and limit alerts can appear as a speech bubble above it.

In your menu bar

An animated Gen-V sprite lives next to today's total tokens (compact, e.g. 200.7M). Add today's cost ($) or official limit % — or turn everything off for a character-only bar.
Menu bar
Normal vs shiny

✨ Once in a rare while — Shiny

Shiny hatches keep their distinct colors through every evolution — menu bar, home card, evolution line. In the Pokédex a ✨ sits next to the dex number, and tapping the cell swaps in the shiny colors. A dedicated notification makes sure you don't miss the moment.

A Pokédex worth filling

The Pokédex folds every species you've owned into one cell — 24 per page in dex-number order, and a ✨ on the ones you own shiny. The Catch log keeps the individuals: newest first, each with its full evolution line, rarity, nature, and capture date.
Pokédex — one cell per species

Catch log — one row per Pokémon raised
Settings

Tune it your way

Menu-bar items, refresh interval (1–15 min or manual), launch at login, a Keychain opt-out that just hides the limits section, limit alerts with warning/critical thresholds, and companion event notifications. Full KO / EN / JA / ES / FR / PT UI and Pokémon names.

🍬 Fill a limit, earn a Rare Candy

Max out a 5-hour or weekly usage limit and you're handed a Rare Candy — one per 5-hour cap, five per weekly. Spend it from the new Bag tab to grow your current Pokémon: the moment you're rate-limited becomes the moment you level up.
Rare Candy and Mint in the Bag
Token Shop — Mint, Rare Candy, Pokémon Egg, Uncommon Egg, Shiny Charm, Rare Egg

🛒 A shop that runs on your usage

The tokens you've already used are your currency. Spend them in the new Shop tab on Rare Candy to grow your current Pokémon, a Mint to re-roll its nature, a Shiny Charm that permanently raises your shiny hatch odds, or an egg to send off your companion and start over. Eggs come in three grades — a plain Pokémon Egg, an Uncommon Egg that always hatches Uncommon or better, and a Rare Egg that always hatches Rare or better. Legendaries stay in the pool for both graded eggs, so a guaranteed hatch can still surprise you.

📊 Official limits, now for Antigravity too

Antigravity 2.0 and the IDE report real quota, not an estimate. Gemini models and Claude & GPT models each get their own 5-hour and weekly buckets with reset countdowns, alongside Claude Code and Codex. Read quietly in the background — no Keychain prompt, and the session refreshes itself.
Antigravity official limits — 5-hour and weekly buckets per model group
Additional scan folders in Settings → Advanced

📁 Logs somewhere unusual? Point at them

If a tool keeps its sessions outside the built-in paths, add your own roots under Settings → Advanced — comma or newline separated, * wildcards, with a live count of how many extra folders currently match. Every provider keeps its own list, so one tool's folders are never handed to another tool's parser, and your custom roots are added to the built-in ones rather than replacing them.

⚔️ Moves, learnsets and TMs

Every Pokémon carries up to four moves with type, category and PP. Its level-up learnset sits underneath, so you can teach a move as soon as it's unlocked, and TMs from the shop teach more. With all four slots full, you pick one to replace.
PC detail: four moves and the level-up learnset
Battle window: picking a team of up to six

Trade window: browse, start or join a trade

🤝 Battle and trade with friends

Pick up to six of your party and battle 1v1 in its own window, or trade Pokémon and tokens. Start from the open lobby or share an invite link, and anyone can watch a live battle. Both are off by default: nothing leaves your machine until you set a server in Settings.

🏅 Earn every gym badge

Beat an opponent whose team matches a real gym leader, Elite Four member or Champion from Gens 1 to 5, and the badge is yours. Collection → Badges tracks all 65, region by region.
Badges: gym leaders, Elite Four and Champion by region
Pokédex with Show all on: every species, unmet ones greyed out

📖 The whole Pokédex, with battle info

Switch on Show all to see all 649 species, the ones you haven't met greyed out. Every species page has a battle section: an S–F tier, its role, a suggested build of moves it can actually learn here, and better options that share a type. Tap any move for its power, accuracy, PP and in-game description.

⚔️ Suggested builds and move details

Builds come from Smogon's Black/White sets, adjusted to what this app can teach: egg, tutor and older-game moves are all learnable, and TMs still come from the shop.
Battle info: tier, role, suggested build and better options

Move detail: power, accuracy, PP and description

🏟️ Play as a gym leader

Pick any gym leader, Elite Four member or Champion your party can field a team for, and your roster fills with their team. Badges at stake shows what a win against your team would hand out, and what one more pick would add. Search your party by name or type.
Battle roster picker: playing as Falkner, with the Zephyr Badge at stake
Pokédex with search, sort and a forms count on each species

🔎 Search the Pokédex, collect every form

Search the Pokédex and catch log by name in any language, sort them, or show shinies only. Species with alternate forms show how many you have, such as Unown 10/28.

🔤 Pick the look you like

Unown letters, Burmy cloaks, Rotom appliances, Arceus types and the other Gen 1 to 5 forms hatch at random. On the species page, choose any form you have collected and pin it to the menu bar.
Unown's page: choose one of the collected letters and pin it
Day Care: Eevee and Pikachu incubating an egg

🥚 Breed at the Day Care

Leave two compatible Pokémon in PC → Day Care and their egg grows from your normal usage while training carries on. The baby inherits IVs, nature, its hidden ability and egg moves.

📊 Look back at any month

The usage recap steps back through any week, month or year: total, daily meters, the change on the previous period, best day, best streak and the Pokémon that graduated. Sample data shown.
Usage recap for August: total, daily meters, best day and graduations

Also in the box

  • 1v1 online battles: create or join a battle from a shared link or the open lobby, field up to six of your party, and play a turn-based match in its own window. The server resolves turn order, so both players see the same fight in the same order.
  • Moves and TMs: companions learn up to four moves as they level, and TMs from the shop teach more. With all four slots full, you pick one to replace. Learnsets and the TM catalog come from PokéAPI.
  • Animation quality — pick how smoothly the menu bar sprite and the floating pet animate (Power saver / Balanced / Smooth). Both always-visible surfaces share the setting. Power saver is the default and keeps the frame rate the app used before this setting existed; Balanced and Smooth trade battery for smoothness (measured idle CPU ~1.8% and ~5.1%).
  • Interactive floating pet — hover for today's usage, click to open the main window, right-click for a menu, and show limit alerts as speech bubbles.
  • Per-service tabs — when two or more of Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, Hermes Agent, Cursor, Grok CLI, Copilot CLI, Kiro CLI, and Pi Agent are detected, compact tabs switch between them; today's total stays combined.
  • Official limits — Claude, Codex & Antigravity 5-hour / weekly utilization with reset countdowns, right under today's numbers.
  • Additional scan folders — per-provider extra scan roots for logs kept outside the built-in paths (Settings → Advanced).
  • Burn-rate forecast — projects when the current 5h window hits 100%.
  • In-app updates — one-click update check; current version shown in Settings.
  • Usage recap — a Pokédex-style recap of any week, month or year you step back to (total, meters, comparison with the previous period, day for day while it is still running, best day, best streak, graduations). History is kept locally for this year and the last.
  • Daily trend: this month's usage day by day, stacked by service, with today highlighted.
  • Pace colours: limit bars and menu-bar percentages turn orange or red when you are using a window faster than it resets, with a marker for where an even pace would be.
  • Automatic backups: local save snapshots every 12 hours (up to 10), restorable from Settings, with automatic recovery if the save file is damaged.
  • Pokédex search: search the Pokédex and catch log by name in any language, sort them, and show shinies only.
  • Alternate forms: Unown letters, Burmy cloaks, Rotom appliances, Arceus types and the other Gen 1 to 5 forms hatch at random and are collected one by one. Pick any collected form on the species page and pin it to the menu bar.

Works with

Tool Tracked Official limits
Claude Code today · 5h block · week · month ✅ 5h / weekly
Codex today · week · month ✅ 5h / weekly
Gemini CLI today · week · month —
Antigravity today · 5h block · week · month ✅ 5h / weekly
OpenCode today · 5h block · week · month —
Hermes Agent today · 5h block · week · month —
Cursor today · 5h block · week · month —
Grok CLI today · 5h block · week · month —
Copilot CLI today · 5h block · week · month —
Kiro CLI today · 5h block · week · month — (estimated)
Pi Agent today · 5h block · week · month —

All read locally — no external usage CLI required. Adding a tool is one provider file (see CONTRIBUTING.md).

Install

Requirements

macOS 14+ (Apple Silicon or Intel). That's it — token usage is read directly from local Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, Hermes Agent, Cursor, Grok CLI, Copilot CLI, Kiro CLI, and Pi Agent data, with no external usage CLI required.

This is a security-hardened fork. It is built from source rather than downloaded, and three defaults differ from upstream. Full instructions: INSTALL.md. What changed and why: SECURITY.md and docs/reference/fork-hardening.md.

Build from source

git clone https://github.com/CallumAcorn/PokeTokenBar.git
cd PokeTokenBar
./scripts/verify-hardening.sh
./scripts/build-app.sh

Needs Xcode 16+ for the Swift 6 toolchain. build-app.sh signs with the hardened runtime and installs to /Applications.

There is deliberately no release download and no Homebrew cask for this fork. A downloaded build would be self-signed and un-notarised, so Gatekeeper would block it and you would have to strip the quarantine attribute by hand. That bypass is one of the things this fork removed from the upstream cask, so it is not offered here. A binary you compile locally carries no quarantine attribute and simply runs.

Upstream's own releases and cask are at chattymin/PokeTokenBar. They install upstream's build, not this one, without the hardening described here.

Developing on it

swift build                  # debug
swift test                   # unit tests
./scripts/build-app.sh       # release → PokeTokenBar.app → /Applications

Data sources

Source Used for Notes
~/.claude/projects/**/*.jsonl Claude Code daily/blocks/weekly/monthly read directly; deduped by message id; cached incrementally
~/.gemini/tmp/**/chats/*.json(l) Gemini CLI daily/monthly session records (tokens per message); weekly = daily sum
~/.gemini/antigravity/conversations/*.db
~/.gemini/antigravity-cli/conversations/*.db
~/.gemini/antigravity-ide/conversations/*.db
Antigravity daily/blocks/weekly/monthly SQLite read-only; per-call usage from the Cascade protobuf blob; supports Antigravity 2.0/Core, CLI & IDE; its own provider, not folded into Gemini; a subscription, so no cost is estimated
~/.codex/sessions/**/*.jsonl Codex daily/monthly token_count events; weekly = daily sum
~/.local/share/opencode/opencode.db OpenCode daily/blocks/weekly/monthly SQLite read-only; legacy storage/message JSON is also supported
~/.hermes/state.db Hermes Agent daily/blocks/weekly/monthly SQLite read-only; session token totals and persisted cost
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb Cursor daily/blocks/weekly/monthly SQLite read-only; cursorDiskKV bubble entries with tokenCount
~/.grok/sessions/**/updates.jsonl Grok CLI daily/blocks/weekly/monthly turn_completed records (per-turn usage, server-reported cost); honours $GROK_HOME; subagent sessions are skipped because their tokens are already folded into the parent turn
~/.copilot/session-store.db Copilot CLI daily/blocks/weekly/monthly SQLite read-only; one assistant_usage_events row per API call; honours $COPILOT_HOME; input_tokens already contains the cached prompt, so cache reads/writes are subtracted; premium-request billing, so no cost is estimated
~/Library/Application Support/kiro-cli/data.sqlite3 Kiro CLI daily/blocks/weekly/monthly SQLite read-only; conversation history JSON (conversations/conversations_v2); Kiro's local database never records real token counts, and there is no server-side session, so input is a bytes÷4 estimate of the accumulated conversation text resent on every turn (output likewise from the real streamed response size); a /cleard or compacted conversation's already-counted tokens stay counted until the app restarts; no cost is estimated
~/.pi/agent/sessions/**/*.jsonl Pi Agent daily/blocks/weekly/monthly Direct persisted usage from all projects; $PI_CODING_AGENT_DIR and $PI_CODING_AGENT_SESSION_DIR overrides supported; output already includes reasoning (not counted twice); forked history deduplicated by entry ID; no cost is reported
Keychain / ~/.claude/.credentials.json → api.anthropic.com Claude official 5h/weekly % unofficial endpoint; the Keychain is read only when you press refresh — auto-polling never reads it
codex app-server Codex official 5h/weekly % local child process; account snapshot only, no model turn
PokéAPI: pokeapi.co, graphql.pokeapi.co Pokémon species, evolution & moves runtime fetch; cached locally, never bundled
raw.githubusercontent.com/PokeAPI/sprites Pokémon & item sprites runtime fetch; cached under Application Support, never bundled
Bundled competitive-gen5.json Battle tiers, roles and suggested builds, keyed by Dex number only generated from Smogon's Gen 5 sets (data.pkmn.cc) and @pkmn/dex; no Pokémon names or art, those stay runtime fetches
~/Library/Application Support/Claude/buddy-tokens.json Claude desktop's daily chat token count read locally, only when crediting non-CLI Claude use is on; never sent anywhere
status.claude.com, status.openai.com provider incident banner statuspage summary; display only — turn it off in Settings
api.github.com update check latest release tag; on launch and when the popover opens

If a provider's logs live outside those built-in paths, add the folder in Settings → Advanced → Additional scan folders. Pick the provider first — each folder is parsed only by that provider, so pointing a Gemini field at Claude logs would mis-attribute tokens. Extra folders are added to the built-in locations; they never replace them.

Privacy & permissions

  • On-device. Token usage is read directly from local Claude Code, Codex, Gemini CLI, Antigravity, OpenCode, Hermes Agent, Cursor, Grok CLI, Copilot CLI, Kiro CLI, and Pi Agent data. The app never uploads usage or runs model turns.
  • Outbound requests. The app is not fully offline. It talks to ten hosts: pokeapi.co and graphql.pokeapi.co (species/evolution), raw.githubusercontent.com (sprites), api.anthropic.com (Claude official limits), cloudcode-pa.googleapis.com and daily-cloudcode-pa.googleapis.com (Antigravity official limits) plus oauth2.googleapis.com (their token refresh), status.claude.com and status.openai.com (incident banner — off switch in Settings), and api.github.com (update check). None of them carry your usage, tokens, prompts, or project paths — only the request itself.
  • The grant does not survive a Claude Code token refresh. Claude Code rewrites its own Keychain item whenever it renews its OAuth token, and that rewrite clears the "Always Allow" you gave this app. Official limits then stop updating until you press refresh and allow it again. Heavy Claude Code use means more refreshes, so expect to renew it periodically. The app now says so on screen instead of just going quiet. Nothing here can prevent it: Claude Code owns that item.
  • Keychain (optional). The Claude OAuth credential is read only when you press a refresh button (Settings, or the limits row in the popover). Automatic polling never touches the Keychain, so it never raises a password prompt; when available, the credential is taken from ~/.claude/.credentials.json instead. The token is held in memory only — the app creates no Keychain item of its own. Once the token expires, limits stay visible but stale until you refresh. Turn it off in Settings — the limits section simply hides.
  • Trading and battles (off by default). No server is configured out of the box, and nothing leaves your machine until you set one in Settings. Once you do, the Pokémon you offer or field are sent to that server: for a battle, species, level, nature, ability, IVs, EVs and moves, plus your display name. Your usage figures, tokens, prompts and project paths are never part of it. An invite link can name a different server, and joining always asks you first.
  • Pokémon assets are fetched at runtime from PokéAPI and cached only under ~/Library/Application Support/PokeTokenBar/. The app binary and its release artifacts contain no Pokémon assets.

Contributors

Contributions of all sizes are welcome — see CONTRIBUTING.md for how to build, test, and open a pull request.

Contributors

License & disclaimer

MIT — see LICENSE. The MIT license covers this project's original source code only; it grants no rights to any third-party trademarks, artwork, or data accessed through the app.

PokeTokenBar is an unofficial, non-commercial fan project. It is not affiliated with, endorsed, sponsored, or approved by Nintendo, Game Freak, Creatures Inc., or The Pokémon Company. "Pokémon" and all related names, characters, and imagery are trademarks and copyrights of their respective owners. This project claims no ownership of, and asserts no rights over, any Pokémon intellectual property.

  • The app binary and its release artifacts bundle no Pokémon assets. Pokémon species data and sprites are fetched at runtime from the public PokéAPI and cached locally on the user's own device; sprite images served via PokéAPI remain the property of their respective owners.
  • Any Pokémon imagery in this repository's documentation (screenshots/GIFs) is shown solely to illustrate the app's functionality.
  • The app is provided free of charge for personal, non-commercial use only.
  • If you are a rights holder with any concern about this project, please open an issue or contact the maintainer, and we will respond promptly.

Provided "as is", without warranty of any kind. This notice is not legal advice.

About

Use your tokens to raise, evolve, and collect Pokémon! 🥚

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages