The pulse of your AI coding subscriptions, right in your macOS menu bar.
AIPulse is a tiny SwiftBar plugin that shows live 5-hour and weekly quota usage for Claude Code and Codex β so you never burn through your limit mid-session again.
π΄ β¦ 100% (1h13m) Β· 19% π’ π€ 3% Β· 34%
δΈζζζ‘£ Β· Report a bug Β· Author: Kami (@kamiwang777)
Current version: v1.1.0
- Zero-config β auto-detects Claude Code and Codex from your local data
- Dual-window tracking β 5-hour rolling window + weekly window, side by side
- Independent status lights β Claude and Codex each show their own title status instead of sharing one color
- Claude reset countdown β when Claude's 5h window is exhausted, the title shows how long until it resets
- Official data sources β Codex reads the actual
rate_limitsyour CLI receives from OpenAI; Claude Code prefers the local officialusagecache and falls back toccusagefor token accounting - Projection β see where your 5h window will end at current burn rate
- Context usage β for Codex, see how full your current conversation's context window is
- i18n β English and Chinese (
AIPULSE_LANG=en|zh) - Themeable β cyberpunk (default) or mono
- Graceful degradation β works if only one of the two tools is installed
- Privacy β 100% local, no data ever leaves your Mac
- macOS 11+
- SwiftBar (installer handles this)
nodeβ₯ 18 (brew install node)- At least one of: Claude Code (
~/.claude/projects/) or Codex (~/.codex/sessions/)
curl -fsSL https://raw.githubusercontent.com/kami/aipulse/main/install.sh | bashOr manually:
git clone https://github.com/kamiwang777/aipulse.git
cd aipulse
./install.shEdit ~/.config/aipulse/config.sh (created on first install):
| Variable | Default | Description |
|---|---|---|
AIPULSE_LANG |
en |
Language: en | zh |
AIPULSE_THEME |
cyberpunk |
Colors: cyberpunk | mono |
AIPULSE_HIDE_CLAUDE |
0 |
Set 1 to hide Claude section |
AIPULSE_HIDE_CODEX |
0 |
Set 1 to hide Codex section |
AIPULSE_CC_5H_LIMIT |
max |
Claude fallback baseline for ccusage-derived token estimates |
AIPULSE_CC_WEEK_LIMIT |
max |
Same as above, weekly fallback |
AIPULSE_THRESH_INFO |
50 |
% threshold to switch green β cyan |
AIPULSE_THRESH_WARN |
70 |
% threshold to switch to yellow |
AIPULSE_THRESH_DANGER |
90 |
% threshold to switch to red |
AIPULSE_SHOW_COST |
1 |
Show $ figures in dropdown |
After editing, click Refresh in the SwiftBar menu (or wait a minute).
cd aipulse
git pull
./install.shThis keeps your existing ~/.config/aipulse/config.sh intact and refreshes the SwiftBar plugin file in ~/.swiftbar-plugins/.
After upgrading:
- Click
Refreshin the AIPulse menu, or restart SwiftBar - Confirm the footer shows
Version v1.1.0
- The current release number lives in
VERSION - The SwiftBar plugin metadata mirrors that version in
aipulse.1m.sh - User-facing release notes live in
CHANGELOG.md
For future releases, bump these three places together:
VERSIONaipulse.1m.shbitbar.versionandAIPULSE_VERSIONCHANGELOG.md
For Claude Code, AIPulse now prefers the local official usage cache written by the Claude desktop app. That gives us the same five_hour and seven_day utilization percentages the app itself shows, plus official reset timestamps.
ccusage is still used locally for token totals, burn rate, projection, and cost estimates in the dropdown. If the official cache is unavailable, AIPulse falls back to the older ccusage baseline model.
AIPULSE_CC_5H_LIMIT and AIPULSE_CC_WEEK_LIMIT still matter for that fallback path and for local estimate math. max means "use the highest historical window/week from your local ccusage data". If you know your plan's approximate ceiling, you can set a fixed token count instead.
When the Claude 5h window reaches 100%, the title appends a reset countdown like (1h13m). AIPulse prefers the official cached reset time and falls back to the active ccusage block end time when needed.
The Claude dropdown Price also defaults to a local mapping from AIPULSE_CLAUDE_SUBSCRIPTION:
Pro->$20/moMax (5x)->$100/moMax (20x)->$200/mo
If pricing changes later, set AIPULSE_CLAUDE_PRICE to override it manually.
Codex CLI sessions are stored as JSONL at ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl. Every API response includes a rate_limits block from OpenAI showing primary (5h) and secondary (weekly) percentages directly. AIPulse reads the latest entry β this is literally what Codex's internal usage tracker uses.
If the resets_at timestamp has passed, the window is marked with β³ last X% (we show 0% until Codex reports fresh data).
The Codex dropdown Price defaults to a local mapping from the detected plan, and only uses AIPULSE_CODEX_PRICE when you explicitly override it.
Q: Does this work with Cursor / Aider / Gemini CLI? Not yet. AIPulse is designed to be extended β PRs welcome.
Q: Why might Claude still drift occasionally?
The percentage now comes from Claude's local official cache when available, which is much closer to the app UI. The dropdown token and cost numbers are still local ccusage estimates, so those lines are intentionally labeled as local estimates.
Q: Why does the title use separate red/green lights for Claude and Codex? SwiftBar only supports one text color for the whole title line. AIPulse uses per-tool emoji lights so each provider can show its own state without making the other one look critical.
Q: My Codex shows unknown plan.
The latest session didn't include plan_type. Open Codex, ask one question, refresh.
Q: Can I change the refresh interval?
Rename the plugin file: aipulse.30s.sh (30 sec), aipulse.5m.sh (5 min), etc.
Q: Does it affect battery?
Negligibly. Each refresh parses local files and local app caches only, with no network calls. One npx ccusage invocation caches itself after first run.
AIPulse does not:
- Send any data anywhere
- Require an API key
- Require login
- Write analytics
It only reads local files that your CLI tools already write.
PRs welcome! Particularly:
- Support for other AI coding tools (Cursor, Aider, Gemini CLI, Windsurf, etc.)
- Additional themes
- More languages
Architecture: each tool is a fetch_* bash function returning a JSON blob. Add one, plug it into the dropdown renderer, ship.
MIT Β© Kami (@kamiwang777)
