{"id":47622481,"url":"https://github.com/niederme/ai-quota","last_synced_at":"2026-04-18T04:05:01.811Z","repository":{"id":345313729,"uuid":"1184493240","full_name":"niederme/ai-quota","owner":"niederme","description":"macOS menubar utility to monitor your AI coding quota — track OpenAI Codex and Claude Code usage at a glance","archived":false,"fork":false,"pushed_at":"2026-03-26T19:27:45.000Z","size":5007,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T08:18:50.886Z","etag":null,"topics":["claude","claude-code","codex","macos","menubar","openai","quota","sparkle","swift","swiftui"],"latest_commit_sha":null,"homepage":"https://github.com/niederme/ai-quota/releases/latest","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/niederme.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"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}},"created_at":"2026-03-17T16:33:56.000Z","updated_at":"2026-03-26T19:27:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/niederme/ai-quota","commit_stats":null,"previous_names":["niederme/ai-quota"],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/niederme/ai-quota","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niederme%2Fai-quota","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niederme%2Fai-quota/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niederme%2Fai-quota/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niederme%2Fai-quota/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/niederme","download_url":"https://codeload.github.com/niederme/ai-quota/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niederme%2Fai-quota/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: 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":["claude","claude-code","codex","macos","menubar","openai","quota","sparkle","swift","swiftui"],"created_at":"2026-04-01T22:23:02.543Z","updated_at":"2026-04-18T04:05:01.803Z","avatar_url":"https://github.com/niederme.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AIQuota\n\nA native macOS menu bar app for monitoring AI coding quota. Track [OpenAI Codex](https://openai.com/codex) and [Claude Code](https://claude.ai) from the menu bar and desktop widgets without living in a browser tab.\n\nThe marketing site in `docs/` follows the shared Codex web preview convention using `/Users/niederme/.codex/bin/codex-preview-env`. The canonical global convention lives at `/Users/niederme/.codex/docs/web-preview-convention.md`.\n\n![macOS 15+](https://img.shields.io/badge/macOS-15%2B-black?logo=apple)\n![Swift 6](https://img.shields.io/badge/Swift-6.0-orange?logo=swift)\n\n![hero-composite-screenshot-current](https://github.com/user-attachments/assets/78428686-f724-4d02-8cae-24621e227675)\n\n\n---\n\n## Features\n\n- **Menu bar gauge** — a compact, color-coded arc icon that tracks the selected service and shifts from purple to amber to red as you approach the limit\n- **Popover dashboard** — Codex and Claude Code both use the same dual-arc gauge language: the 5-hour window is the outer ring, the 7-day window is the inner ring\n- **Service details that matter** — reset timers, plan info, credits or extra usage, and clear warning states are visible at a glance\n- **Desktop widgets** — polished widget variants for single-service and dual-service monitoring, including configurable small and medium widgets plus a large two-service layout\n- **Graceful empty and loading states** — widgets and the popover keep a stable layout when a service is disconnected, restoring, or waiting on fresh data\n- **Adaptive refresh controls** — choose `Auto` to refresh every minute when the app is active or quota is near a threshold, then back off automatically when idle, offline, or on low power\n- **Guided onboarding** — first launch walks through connecting services, refresh preferences, notifications, and widget setup; if both services are connected, onboarding also asks which one should drive the menu bar icon\n- **Single-service adaptation** — when only one service is enrolled, the app and widgets avoid dead space instead of pretending there should be a second column\n- **ChatGPT and Claude sign-in** — authenticates using your existing browser-backed session, with secrets stored in Keychain and shared widget data kept in the app group\n- **Notification controls** — per-service master switches plus consolidated threshold alerts (one toggle covers low quota, critical quota, and limit reached) plus reset events\n- **Recovery after updates** — widget timelines reload more aggressively on launch, and installed widgets recover more reliably after app replacements\n- **Auto-update** — Sparkle checks silently on launch and twice daily, with gentle reminders instead of intrusive prompts\n\n---\n\n## Widget Lineup\n\n- **Small** — one service, configurable per widget instance\n- **Medium (single-service)** — one service with a larger gauge and detail column\n- **Medium (two-service)** — Codex and Claude Code side by side\n- **Large** — two-service overview with larger gauges and a dedicated detail row\n\nWidgets refresh automatically from cached data, app-driven reloads, and background timeline updates. If macOS ever leaves a pinned widget stuck in a stale state after an update, removing and re-adding that widget instance usually clears the cached archive.\n\n---\n\n## Requirements\n\n- macOS 15 (Sequoia) or later\n- An OpenAI account with Codex access (Plus, Pro, or Team plan)\n- A Claude.ai account (Pro or Max plan) for Claude Code quota\n\n---\n\n## Installation\n\n1. Download `AIQuota.zip` from the [latest release](https://github.com/niederme/ai-quota/releases/latest)\n2. Unzip and move **AIQuota** to your Applications folder\n3. Launch AIQuota — it appears in your menu bar, not the Dock\n4. Follow the guided setup to connect your ChatGPT and/or Claude account\n\n\u003e Notarized by Apple — no Gatekeeper warning on first launch.\n\n---\n\n## Website Preview\n\nThe lightweight website for `aiquota.app` lives in `docs/`.\n\nFrom the repo root:\n\n```bash\nmake\n```\n\nThat serves `docs/` on all interfaces, opens the site locally, and prints:\n\n- a `.local` URL for this Mac\n- a LAN URL for other devices on the same network\n\nDefault preview port is `8123`. If that port is already in use, `make dev` automatically picks the next available port.\n\nLocalhost-only preview:\n\n```bash\nmake dev-local\n```\n\nWorktree-friendly preview:\n\n```bash\nmake dev-thread\n```\n\n`make dev-thread` starts from `8124` so the main checkout can keep `8123`.\n\nProject worktrees should live under repo-local `.worktrees/`.\n\n### Live Reload\n\nUse `make dev-live` for the standard live-reload preview. The underlying switch is `LIVE=1`, which is also available for the thread and local-only variants:\n\n```bash\nmake dev-live\nmake dev-live-thread\nmake dev-local LIVE=1\n```\n\nLive reload watches:\n\n- `docs/**/*.html`\n- `docs/**/*.css`\n- `docs/assets/**/*`\n\nRequirements for live reload:\n\n- Node.js with `npx` available\n- a Node runtime that supports `node:path`\n- recommended local version: Node 24\n\n### Website Deploy\n\nPushing to `main` triggers the website deploy workflow automatically, and you can also run the same deploy manually with `workflow_dispatch` in GitHub Actions. The workflow:\n\n- minifies `docs/site.css` and `docs/site.js`\n- smoke-checks the public site pages before deploy, including release-page sync against GitHub\n- stages the `docs/` site with cache-busted asset URLs\n- syncs the staged site to the remote host over SSH\n- normalizes remote file permissions so shared hosting serves the site correctly\n\nFor manual or local deploys, use:\n\n```bash\n./scripts/deploy-site.sh\n```\n\nSmoke-check the site before deploy:\n\n```bash\n./scripts/check-site-pages.sh\n```\n\nDefault deploy settings in [`scripts/deploy-site.sh`](scripts/deploy-site.sh):\n\n- `DEPLOY_HOST=ssh.suckahs.org`\n- `DEPLOY_USER=suckahs`\n- `DEPLOY_PATH=/home2/suckahs/public_html/aiquota`\n- `SITE_URL=https://aiquota.app`\n\nOptional overrides:\n\n- `DEPLOY_PORT`\n- `DRY_RUN=1`\n- `DEPLOY_IDENTITY_FILE`\n\nGitHub Actions expects the repository secret `SSH_PRIVATE_KEY` to contain the deploy key for `suckahs@ssh.suckahs.org`.\n\n---\n\n## Building from Source\n\nRequires Xcode 16 or later and [XcodeGen](https://github.com/yonaskolb/XcodeGen).\n\n```bash\ngit clone https://github.com/niederme/ai-quota.git\ncd ai-quota\nxcodegen generate\nopen AIQuota.xcodeproj\n```\n\nBuild and run the `AIQuota` scheme targeting **My Mac**.\n\nIf you are iterating on widgets, launching the built app once after install helps WidgetKit pick up new timelines and layouts.\n\n---\n\n## Project Structure\n\n```\nai-quota/\n├── Packages/\n│   └── AIQuotaKit/          # Shared Swift Package (models, networking, storage)\n│       └── Sources/AIQuotaKit/\n│           ├── Models/      # CodexUsage, ClaudeUsage, AppSettings\n│           ├── Networking/  # OpenAIClient, ClaudeClient, AuthManagers, NetworkError\n│           ├── Notifications/ # NotificationManager\n│           └── Storage/     # KeychainStore, SharedDefaults\n├── AIQuota/                 # Main app target (MenuBarExtra)\n│   ├── Views/               # PopoverView, MenuBarIconView, SettingsView\n│   └── ViewModels/          # QuotaViewModel\n└── AIQuotaWidget/           # WidgetKit extension\n    ├── Provider/            # QuotaTimelineProvider\n    ├── WidgetIntent.swift   # AppIntent for per-widget service selection\n    └── Views/               # WidgetSmallView, WidgetMediumView, WidgetGaugeView\n```\n\n---\n\n## Releasing\n\nSee the pre-release checklist at the top of [`scripts/release.sh`](scripts/release.sh). The short version:\n\n1. Update `README.md` (features, requirements, roadmap) — **always do this first**\n2. Bump `MARKETING_VERSION` in `project.yml`\n3. Run `./scripts/bump-build.sh` to increment `CURRENT_PROJECT_VERSION` and regenerate the Xcode project\n4. Archive in Xcode (`Product → Archive`) and export the notarized `.app` to `~/Desktop/AIQuota.app`\n5. Run `./scripts/release.sh \u003cversion\u003e`\n6. Verify `docs/releases/index.html` matches the GitHub releases list, run `./scripts/check-site-pages.sh`, then push the site/appcast updates to `main`\n\n---\n\n## Roadmap\n\n- [ ] iOS / iPadOS app — native app and home screen widgets for iPhone and iPad\n- [ ] Gemini quota support (Google AI plans)\n- [ ] Menu bar icon monochrome mode — option to disable amber/red status colours for a cleaner, always-white icon\n- [x] Marketing website — `aiquota.app` is live with download, releases, and policy pages plus automated deploys from `main`\n- [x] Visualize 7-day quota reset timing — the app now surfaces 7-day reset timing when the weekly window enters the warning range\n- [x] Settings restructured — Accounts section promoted to the top; notification sections named per service with threshold alerts consolidated into a single toggle per window\n- [x] Auth and widget recovery after updates — widgets recover more reliably after app replacements, refresh more aggressively, and valid Claude/Codex sessions now restore automatically instead of showing stale Connect states\n- [x] Widget variations — configurable single-service medium widget plus a large two-service overview\n- [x] Menu bar preference fully respected — the menu bar icon now follows the selected service for both gauge values and warning colour\n- [x] Single-service layout — popover adapts width and layout when only one service is enrolled\n- [x] Menu bar preference in onboarding — when both services are connected, setup asks which to show in the menu bar\n- [x] Stable popover layout — Connect button sits inside the gauge arc when a service needs to reconnect; no layout shifts\n- [x] Guided onboarding — step-by-step setup wizard on first launch; replayable from Settings\n- [x] Per-service notification switches — master toggle per service; sub-thresholds collapse when disabled\n- [x] Dual-arc gauge — concentric rings for 5h and 7-day windows; color-coded purple → amber → red; both percentages labelled in the centre\n- [x] Widget redesign — dual-arc gauges, single-service and dual-service widget variants, improved placeholder states, and more resilient rendering after updates\n- [x] Network recovery — NWPathMonitor detects coming back online and refreshes immediately\n- [x] Claude Code support — 5h and 7-day windows, Max plan credits, reset timers\n- [x] Harmonized window display — both Codex and Claude lead with the 5-hour rate-limit window, with 7-day usage always shown as a secondary row\n- [x] Widget service picker — choose Codex or Claude Code per widget instance\n- [x] Notifications — below 15%, below 5%, limit reached, quota reset; rolling-window drift no longer triggers spurious alerts\n- [x] Check for Updates — manual + silent auto-check on launch and twice daily via Sparkle, with gentle reminders\n\n---\n\n## License\n\nMIT with [Commons Clause](https://commonsclause.com). Free to use, modify, and distribute — commercial or proprietary use is not permitted.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniederme%2Fai-quota","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fniederme%2Fai-quota","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniederme%2Fai-quota/lists"}