{"id":44533641,"url":"https://github.com/kylenesium/aibattery","last_synced_at":"2026-04-08T01:01:11.764Z","repository":{"id":339910725,"uuid":"1160829276","full_name":"KyleNesium/AIBattery","owner":"KyleNesium","description":"A battery style usage meter for Claude Code. Rate limits, context health, and token usage in your macOS menu bar.","archived":false,"fork":false,"pushed_at":"2026-04-01T15:51:21.000Z","size":5350,"stargazers_count":20,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-04-02T02:45:22.643Z","etag":null,"topics":["ai","anthropic","claude-code","developer-tools","macos","menu-bar","rate-limits","swiftui"],"latest_commit_sha":null,"homepage":"https://aibattery.dev","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KyleNesium.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"KyleNesium"}},"created_at":"2026-02-18T12:24:05.000Z","updated_at":"2026-04-01T15:51:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"8253d743-253f-417c-ae36-d524fbe92e92","html_url":"https://github.com/KyleNesium/AIBattery","commit_stats":null,"previous_names":["kylenesium/aibattery"],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/KyleNesium/AIBattery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KyleNesium%2FAIBattery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KyleNesium%2FAIBattery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KyleNesium%2FAIBattery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KyleNesium%2FAIBattery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KyleNesium","download_url":"https://codeload.github.com/KyleNesium/AIBattery/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KyleNesium%2FAIBattery/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31535203,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","anthropic","claude-code","developer-tools","macos","menu-bar","rate-limits","swiftui"],"created_at":"2026-02-13T18:42:12.382Z","updated_at":"2026-04-08T01:01:11.757Z","avatar_url":"https://github.com/KyleNesium.png","language":"Swift","funding_links":["https://github.com/sponsors/KyleNesium"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"screenshots/icon.png\" width=\"128\" alt=\"AI Battery icon\" /\u003e\n\n# AI Battery\n\n**Get the most out of your Claude subscription.**\n\n[aibattery.dev](https://aibattery.dev)\n\nMonitor rate limits, context health, and token usage — always visible in your macOS menu bar.\n\n[![Swift](https://img.shields.io/badge/Swift-5.9-orange?logo=swift\u0026logoColor=white)](https://swift.org)\n[![macOS](https://img.shields.io/badge/macOS-13%2B-blue?logo=apple\u0026logoColor=white)](https://www.apple.com/macos/)\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![CI](https://github.com/KyleNesium/AIBattery/actions/workflows/ci.yml/badge.svg)](https://github.com/KyleNesium/AIBattery/actions/workflows/ci.yml)\n[![GitHub stars](https://img.shields.io/github/stars/KyleNesium/AIBattery?style=social\u0026cacheSeconds=3600)](https://github.com/KyleNesium/AIBattery/stargazers)\n[![Downloads](https://img.shields.io/github/downloads/KyleNesium/AIBattery/total?logo=github\u0026label=Downloads\u0026cacheSeconds=3600)](https://github.com/KyleNesium/AIBattery/releases)\n\n\u003cbr/\u003e\n\n\u003cimg src=\"screenshots/full-popover-v2.0.8.png\" width=\"520\" alt=\"AI Battery open in the menu bar showing 5-hour and 7-day rate limits, throttling status, context health, projects, and insights\" /\u003e\n\n\u003cp\u003e\u003cstrong\u003eLive rate limits, context health, and usage trends without leaving the menu bar.\u003c/strong\u003e\u003c/p\u003e\n\n\u003c/div\u003e\n\n## 📦 Install\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"30\"\u003e\u003cimg src=\"https://brew.sh/assets/img/homebrew.svg\" width=\"18\" /\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cstrong\u003eHomebrew\u003c/strong\u003e (recommended)\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n```bash\nbrew tap KyleNesium/tap\nbrew install --cask aibattery\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e⚡ \u003cstrong\u003eQuick install\u003c/strong\u003e — paste in Terminal\u003c/summary\u003e\n\n```bash\ncurl -sL https://github.com/KyleNesium/AIBattery/releases/latest/download/AIBattery.zip -o /tmp/AIBattery.zip \u0026\u0026 ditto -x -k /tmp/AIBattery.zip /Applications \u0026\u0026 xattr -cr /Applications/AIBattery.app \u0026\u0026 open /Applications/AIBattery.app\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e💿 \u003cstrong\u003eDMG download\u003c/strong\u003e\u003c/summary\u003e\n\nDownload from [Releases](https://github.com/KyleNesium/AIBattery/releases/latest):\n\n1. Open `AIBattery.dmg` and drag **AI Battery** to **Applications**\n2. Launch from Applications — macOS will block it on first run\n3. Open **System Settings → Privacy \u0026 Security** → scroll down → click **Open Anyway**\n\n\u003e [!TIP]\n\u003e If macOS says the app is damaged, run `xattr -cr /Applications/AIBattery.app` then relaunch.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e🛠 \u003cstrong\u003eBuild from source\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\ngit clone https://github.com/KyleNesium/AIBattery.git \u0026\u0026 cd AIBattery\n./scripts/build-app.sh\nopen .build/AIBattery.app\n```\n\n\u003c/details\u003e\n\nRequires **macOS 13+** and [Claude Code](https://docs.anthropic.com/en/docs/claude-code). See [aibattery.dev](https://aibattery.dev) for more info.\n\n---\n\n## 🔄 Update\n\nAI Battery checks for updates once per day. When available, the header arrow turns **yellow** and a banner appears.\n\n| Method | How |\n|---|---|\n| **In-app** (recommended) | Click **Install Update** — [Sparkle](https://sparkle-project.org/) downloads, verifies, replaces, and relaunches |\n| **Homebrew** | `brew upgrade --cask aibattery` |\n| **DMG** | Download from [Releases](https://github.com/KyleNesium/AIBattery/releases/latest), drag to Applications |\n\nSettings and OAuth sessions carry over automatically. Updates are user-initiated only — nothing downloads in the background.\n\n---\n\n## 🔐 Authentication\n\nOAuth 2.0 with PKCE — same protocol as Claude Code. Supports up to **3 accounts** (separate Claude orgs).\n\n| Step | Action |\n|:---:|---|\n| **1** | Launch AI Battery — the auth screen appears on first run |\n| **2** | Click **Sign In** → browser opens to Anthropic's sign-in |\n| **3** | Sign in → copy the authorization code |\n| **4** | Paste into AI Battery → done |\n\n**Multiple accounts:** Use the header dropdown to switch accounts or add new ones (up to 3). Each account has its own rate limits, tokens, and identity.\n\n\u003cdetails\u003e\n\u003csummary\u003e🔑 \u003cstrong\u003eSession details\u003c/strong\u003e\u003c/summary\u003e\n\n- Sessions auto-refresh with a 5-minute buffer to avoid clock-skew issues\n- Temporary server errors retry automatically\n- Refresh token stored in macOS Keychain per account (separate from Claude Code credentials); access token held in memory only\n- Error messages are specific — expired codes, invalid codes, server errors, and network errors each get a clear description\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e🛡 \u003cstrong\u003eWhy does macOS block the app or ask about Keychain access?\u003c/strong\u003e\u003c/summary\u003e\n\nAI Battery isn't notarized — there's no Apple Developer license behind this project, so macOS treats it as unidentified. Two prompts may appear on first launch:\n\n- **Gatekeeper block** — macOS prevents the app from opening. Fix: **System Settings → Privacy \u0026 Security → Open Anyway** (see [Install](#-install))\n- **Keychain access** — the app stores its OAuth refresh token in macOS Keychain (one item per account), Apple's encrypted credential store. Click **Always Allow**. The prompt may reappear once after an in-app update because the new binary has a different ad-hoc signature.\n\nThe Gatekeeper prompt is one-time. The Keychain prompt appears once on first launch and once after each in-app update.\n\n\u003c/details\u003e\n\n---\n\n## 📐 Metrics\n\nA minimal API fetch reads Claude Code account metadata for 5-hour and 7-day usage, with legacy header fallback when available. Local JSONL session logs provide token counts and context health — **never your message content**. Click the ✦ icon to open the dashboard.\n\nThe tab picker selects which metric drives the ✦ icon color:\n\n| Mode | Tracks | Best for |\n|---|---|---|\n| ⏱ **5-Hour** | Burst rate limit | Knowing when you'll get throttled |\n| 📅 **7-Day** | Sustained rate limit | Pacing usage across the week |\n| 🧠 **Context** | Session context fullness | Knowing when to start fresh |\n| **(A) Auto** | Highest urgency metric | Always seeing the most critical metric |\n\nSelected metric moves to the top. The other two stay visible below.\n\n\u003e [!NOTE]\n\u003e The 5-hour and 7-day bars come from Anthropic API sliding-window headers. They may differ from Claude Code `/usage`, which uses different plan-usage semantics and reset timings.\n\n**Auto mode**: click the **(A)** button next to the tabs. It glows blue when active and automatically selects whichever metric has the highest percentage — so the menu bar always shows your most critical limit. To switch back to manual, click any tab — auto mode disables and switches in one action.\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"screenshots/dashboard.png\" width=\"360\" alt=\"AI Battery dashboard showing 5-hour and 7-day rate limits with reset countdowns\" /\u003e\n\u003c/div\u003e\n\n---\n\n## 🧠 Context Health\n\nShows your **5 most recent sessions** with context health. Browse with `\u003c 1/5 \u003e` chevrons or swipe left/right. Stale sessions (idle \u003e 30 min) show an amber \"Idle\" badge.\n\nEach session displays: **project name** · **git branch** · **duration** · **last active time**.\n\nPercentages are relative to the **usable window** — 80% of the model's raw context window. At 100%, Claude Code auto-compacts and quality drops. Keep at least 20-40% free for best results.\n\n| Color | Range | Meaning |\n|---|---|---|\n| 🟢 Green | \u003c 60% | Plenty of room |\n| 🟠 Orange | 60–80% | Quality may degrade |\n| 🔴 Red | \u003e 80% | Start a fresh session |\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"screenshots/context.png\" width=\"360\" alt=\"Context health view showing session context window fullness, model, and turn count\" /\u003e\n\u003c/div\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e⚠️ \u003cstrong\u003eUnderstanding context\u003c/strong\u003e\u003c/summary\u003e\n\n**Think of context as Claude's short-term memory.** Every message, file read, tool call, and response accumulates in a 200K-token window. Nothing is discarded between turns. When it fills up, Claude Code auto-compacts — summarizing the session into a few paragraphs and clearing the rest. That summary is lossy: file contents, specific instructions, and nuanced decisions get compressed. Claude keeps working, but from a recap instead of the real conversation.\n\n**Long conversation (15+ turns)** — Nothing is discarded between turns. Your messages, Claude's responses, tool calls, and results all accumulate. After ~15 turns the window is full of old history that Claude still reads every turn — slowing responses, reducing quality, and burning through your token budget on stale context.\n\n**High input:output ratio (20:1+)** — More tokens are going in (file reads, error logs, tool results) than coming out. For example, reading 5 large files dumps thousands of tokens into context that Claude may only reference once. That data stays in the window for the rest of the session, consuming tokens on every subsequent turn and leaving less room for useful work.\n\n**Zero-output session** — Session has multiple turns but no output tokens. May indicate an error loop or stalled conversation.\n\n**Rapid token consumption** — Very short session with high token usage. Large files or long pastes may be filling the context window quickly.\n\n\u003c/details\u003e\n\n\u003e [!TIP]\n\u003e **When you hit orange or red:**\n\u003e 1. Run `/compact` to save a summary to project memory\n\u003e 2. Keep key decisions in `CLAUDE.md` — loaded automatically every session\n\u003e 3. Start a new terminal in the same directory and pick up where you left off\n\n---\n\n## ⚙️ Settings\n\nClick ⚙️ in the header to configure:\n\n| Setting | What it does |\n|---|---|\n| ➕ **Add Account** | Connect another Claude account (up to 3) |\n| ✏️ **Account names** | Custom label per account (shown in picker + menu bar) |\n| 🔁 **Auto mode** | Always show the highest metric (pulsing blue button on metric toggle) |\n| 🔄 **Refresh** | Poll interval: 10–60s · ~3 tokens per refresh |\n| ⏳ **Idle** | Hide sessions idle longer than cutoff from context health: 30m–8h or Never |\n| 🎨 **Colorblind** | Blue/cyan/amber/purple palette |\n| 💲 **Cost** | Always visible — API-equivalent cost in Insights and Projects |\n| 🔔 **Alerts** | Notify on status page outages (all components) |\n| ⚡ **Rate Limit** | Notify when usage crosses threshold (50–95%) |\n| 🚀 **Launch at Login** | Start automatically when you log in |\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"screenshots/settings.png\" width=\"360\" alt=\"Settings panel with refresh interval, idle session cutoff, colorblind mode, alerts, and launch at login\" /\u003e\n\u003c/div\u003e\n\n\u003e [!TIP]\n\u003e Click any stat value (percentages, token counts, costs) to copy it to the clipboard.\n\n---\n\n## 📉 Activity \u0026 Insights\n\nInteractive charts across three time windows:\n\n| Mode | Window | Shows |\n|---|---|---|\n| **24H** | Trailing 24 hours | Hourly activity, vs-yesterday trend, peak hour |\n| **7D** | Rolling 7 days | Daily activity, weekly trend, busiest day |\n| **12M** | Rolling 12 months | Monthly activity, month-over-month trend, busiest month |\n\nBelow the chart: API-equivalent cost per model, throttle count, and cumulative stats (All Time messages/sessions, Longest session, Period date range).\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"screenshots/activity.png\" width=\"360\" alt=\"24-hour activity chart with trend arrows, throttle count, and cost breakdown by model\" /\u003e\n\u003c/div\u003e\n\n---\n\n## 💰 API Cost Equivalent\n\nDollar amounts show what your usage **would have cost on Anthropic's pay-per-token API** — not your actual bill. Pro, Max, and Teams subscribers pay a flat monthly fee. When the API-equivalent exceeds your monthly fee, your subscription is saving you money. The bigger the gap, the better the deal. Pricing uses Anthropic's published per-million-token rates.\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"screenshots/projects.png\" width=\"360\" alt=\"Per-project token usage breakdown with costs\" /\u003e\n\u003c/div\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eHow token tracking works\u003c/strong\u003e\u003c/summary\u003e\n\nAI Battery reads Claude Code's session logs (`~/.claude/projects/`) and stats cache (`~/.claude/stats-cache.json`) — it never writes to Claude Code's files or reads message content, only token counts.\n\nTo prevent totals from dropping when Claude Code rebuilds its cache, AI Battery maintains a **persistent ledger** (`~/Library/Application Support/AIBattery/token-ledger.json`) that keeps the high-water mark for each model. Token totals never decrease, even across cache rebuilds.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eHow project tracking works\u003c/strong\u003e\u003c/summary\u003e\n\nThe **Projects** section groups token usage by the directory you ran Claude Code in. AI Battery scans all `.jsonl` session logs under `~/.claude/projects/`, deduplicates by message ID, groups by working directory, and computes API-equivalent cost per project.\n\nProject data appears after you've run at least one Claude Code session.\n\n\u003c/details\u003e\n\n---\n\n## 🔧 Troubleshooting \u0026 FAQ\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cstrong\u003eApp appears in the menu bar then disappears\u003c/strong\u003e\u003c/summary\u003e\n\n**On first launch:** macOS Gatekeeper may silently kill the app because it's not notarized.\n\n```bash\nxattr -cr /Applications/AIBattery.app\n```\n\nThen relaunch. This removes the quarantine flag that macOS adds to downloaded apps.\n\n**After working for a while:** If the icon vanishes after the app has been running, update to the latest version — v1.2.3+ fixed concurrency issues that could cause intermittent crashes during background data refresh and sleep/wake cycles.\n\n**If it still happens:**\n\n1. Open **Console.app** → filter for \"AIBattery\" → look for crash logs\n2. Check your macOS version — macOS 13.0–13.2 had `MenuBarExtra` bugs fixed in 13.3+\n3. [Open an issue](https://github.com/KyleNesium/AIBattery/issues) with the crash log\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003emacOS says \"AI Battery is damaged and can't be opened\"\u003c/strong\u003e\u003c/summary\u003e\n\nThis is the quarantine flag. Run:\n\n```bash\nxattr -cr /Applications/AIBattery.app\n```\n\nThen relaunch.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eKeychain access dialog keeps appearing\u003c/strong\u003e\u003c/summary\u003e\n\nClick **Always Allow** when prompted. AI Battery stores its OAuth refresh token in macOS Keychain (one item per account). After a Sparkle in-app update, a single Keychain prompt may appear because the new binary has a different ad-hoc signature. This is a one-time prompt per update.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eOnly rate limits show — tokens, models, and activity are all empty?\u003c/strong\u003e\u003c/summary\u003e\n\nToken usage, context health, and activity stats come from Claude Code's local session logs (`~/.claude/`). These populate after you've used Claude Code for a bit. To kickstart it:\n\n1. Run a few Claude Code sessions from the terminal\n2. Run `/stats` inside Claude Code — this generates the stats cache\n3. AI Battery refreshes automatically every polling cycle\n\nClaude Code usage windows (5-hour / 7-day) are fetched from Anthropic account metadata. If Anthropic changes that response shape, AI Battery falls back to cached values and may show a warning until fresh usage data is available again.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eGreen ✦ at 0%?\u003c/strong\u003e\u003c/summary\u003e\n\nCredits just reset, or no usage yet — this is normal.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eWhat's \"binding\"?\u003c/strong\u003e\u003c/summary\u003e\n\nWhichever rate limit window is currently the active constraint. The binding window determines the percentage shown in the menu bar.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eWhat's ⚠️ \"throttled\"?\u003c/strong\u003e\u003c/summary\u003e\n\nAnthropic is actively limiting your requests. Wait for the reset timer.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eWhy can AI Battery differ from Claude Code `/usage`?\u003c/strong\u003e\u003c/summary\u003e\n\nAI Battery primarily shows Claude Code 5-hour and 7-day usage from Claude Code account metadata. It may fall back to legacy Anthropic headers or cached values when those windows are temporarily unavailable, so percentages and reset times can still differ from Claude Code `/usage` during API transitions or stale-data fallback.\n\n\u003c/details\u003e\n\n---\n\n## 🔒 Privacy \u0026 Security\n\n| | |\n|---|---|\n| 📂 **Local only** | Reads JSONL for token counts — **never your message content** |\n| 🔑 **Keychain** | OAuth refresh token stored in macOS Keychain (`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`) — access token is memory-only, never written to disk |\n| 🌐 **Network** | `api.anthropic.com` (rate limits) · `console.anthropic.com` (OAuth) · `status.claude.com` (status) · `api.github.com` (update check, once/24h) · `kylenesium.github.io` (Sparkle appcast) |\n| 🚫 **No tracking** | No analytics. No telemetry. No data collection. Period. |\n| 🔍 **Open source** | Every line is auditable — [review the code](https://github.com/KyleNesium/AIBattery) |\n| ✅ **Release checks** | Each release runs [`verify-release.sh`](scripts/verify-release.sh) — validates codesign, Sparkle signatures, version consistency, and bundle integrity before publish |\n\n---\n\n## 🏗 Architecture\n\n```\nAIBattery/\n  Models/       — Data structs (UsageSnapshot, RateLimitUsage, TokenHealthStatus, ...)\n  Services/     — OAuthManager, RateLimitFetcher, SessionLogReader, TokenHealthMonitor, ...\n  ViewModels/   — Single UsageViewModel (@MainActor, ObservableObject)\n  Views/        — SwiftUI views (popover sections, menu bar label, auth screen)\n  Utilities/    — TokenFormatter, ModelNameMapper, ThemeColors, AppLogger\n```\n\n**One dependency** — [Sparkle 2](https://sparkle-project.org/) for auto-update. Everything else is Apple frameworks (SwiftUI, Charts, Security, Foundation, AppKit).\n\n\u003cdetails\u003e\n\u003csummary\u003e📋 \u003cstrong\u003eDetailed specs\u003c/strong\u003e\u003c/summary\u003e\n\n| File | Covers |\n|---|---|\n| [`ARCHITECTURE.md`](spec/ARCHITECTURE.md) | Data flow, project tree, build config, network \u0026 file access |\n| [`DATA_LAYER.md`](spec/DATA_LAYER.md) | Every model, service, and algorithm |\n| [`UI_SPEC.md`](spec/UI_SPEC.md) | View hierarchy, layout rules, section specs |\n| [`CONSTANTS.md`](spec/CONSTANTS.md) | Every hardcoded value — thresholds, URLs, pricing, sizes |\n\n\u003c/details\u003e\n\n---\n\n## ♿ Accessibility\n\n- **VoiceOver** — all interactive elements include accessibility labels and hints; collapsible sections announce state; copy actions announce confirmation\n- **Keyboard navigation** — fully navigable without a mouse\n- **Colorblind mode** — Settings → Display → Colorblind switches to a blue/cyan/amber/purple palette\n- **First-launch tutorial** — 3-step walkthrough on first use\n\n---\n\n## 🗑 Uninstall\n\n**Homebrew:**\n\n```bash\nbrew uninstall --cask aibattery\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e🧹 \u003cstrong\u003eManual uninstall\u003c/strong\u003e\u003c/summary\u003e\n\n1. Right-click **AI Battery** in the menu bar → **Quit**\n2. Open **Applications** in Finder → drag **AI Battery** to the Trash\n\nTo also remove stored settings:\n\n```bash\nsecurity delete-generic-password -s \"AIBattery\" 2\u003e/dev/null   # OAuth tokens (all accounts)\ndefaults delete com.KyleNesium.AIBattery 2\u003e/dev/null           # Preferences\n```\n\nAI Battery doesn't write any other files. Your Claude Code data (`~/.claude/`) is untouched.\n\n\u003c/details\u003e\n\n---\n\n## 🤝 Contributing \u0026 Support\n\nContributions welcome — read the [contributing guide](CONTRIBUTING.md) first. See [CHANGELOG.md](CHANGELOG.md) for version history.\n\nAI Battery is **free and open source** — always will be. If it helps you get more out of Claude, consider [sponsoring the project](https://github.com/sponsors/KyleNesium).\n\n[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-pink?logo=github)](https://github.com/sponsors/KyleNesium)\n\n---\n\n## 🧪 Test Coverage\n\n**845 tests** across 57 test files.\n\n| Area | Tests | What's covered |\n|------|-------|----------------|\n| Models | 239 | Token summaries, rate limit parsing (unified + standard + client data edge cases), health status, metric modes, API profiles, usage snapshots (incl. escalation ladder, hysteresis), model pricing, Claude system status indicators, standard rate limits |\n| Services | 297 | Token ledger, version checker, Sparkle updates, notifications, health monitor (incl. zero-window safety), status checker, session log reader (incl. NSLock/pendingInvalidation concurrency, incremental scanning, entry eviction), account store, stats cache, usage aggregator (incl. side-effects, integration tests), rate limit fetcher, OAuth |\n| Views | 86 | Activity chart data transforms (5H/7D/12M token-based), trend computation, session info formatting, GaugeBar clamping, deferred rendering, status bar toggle, insights view formatting, metric toggle ordering |\n| ViewModels | 44 | Refresh interval clamping, error messages (incl. standard limits fallback), adaptive polling, throttle tracking, idle threshold constants, TTL-based stale rate limit expiry, effective value generic guard |\n| Utilities | 175 | Token/duration formatting, model name mapping, theme colors, secure networking, menu bar icon animations, throttle tracker, typography, spacing, idle suspension policy |\n\n---\n\n## 📄 License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkylenesium%2Faibattery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkylenesium%2Faibattery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkylenesium%2Faibattery/lists"}