Skip to content

F-e-u-e-r/ai-pet-usage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

45 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿพ AI Pet Usage

A macOS desktop pet that reacts to AI usage โ€” quota, token burn, cost, and work rhythm.

macOS 14+ Swift 5 SwiftUI + AppKit Local-first License: AGPL-3.0-only

Your AI usage becomes a living companion โ€” no dashboards to open, no commands to run.

English ยท ็น้ซ”ไธญๆ–‡

  /\_/\        tokens today   โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–‘โ–‘โ–‘  68%
 ( o.o )       burn rate      steady ยท mood: focused
  > ^ <        next reset     in 2h 14m

Implemented and running. A SwiftUI/AppKit menu-bar app with a floating pixel pet, built from scratch. The repo contains the working app (SwiftPM, Sources/) plus the docs that matter most: exactly which local files are read and why (docs/DATA_SOURCES.md) and where the project is headed (ROADMAP.md).

โœจ Highlights

  • ๐ŸŽ Native macOS โ€” SwiftUI + AppKit menu-bar app with a floating pixel-pet panel.
  • ๐Ÿ“Š Three pages, not one crowded dashboard โ€” Today, Limits, and Projects, plus a Trends view with usage heatmap and streaks.
  • ๐Ÿ”Œ Provider adapters โ€” Codex and Claude Code (with official 5h/weekly limits); Grok Code enabled by default (token usage + plan tier; this app does not yet ingest Grok's official limits); Antigravity behind a research gate; OpenCode planned next.
  • ๐Ÿงฎ Local ledger + limit engine โ€” quota, reset windows, token burn rate, and per-model costs from a pricing registry that is sourced & dated per entry.
  • ๐Ÿ• Feeding/XP loop and mood engine โ€” the pet reacts to signals such as quota remaining, burn rate, stale data, focus sessions, and usage milestones.
  • ๐Ÿ“„ Offline HTML report export โ€” a local, offline-readable snapshot of Today, Limits, Projects, pricing assumptions, and data-quality notes.
  • ๐Ÿ‘€ Live updates & scheduled exports โ€” FSEvents file-watching keeps data fresh; report export can run on a schedule.
  • ๐Ÿชถ Monitor-only (low RAM) mode โ€” Settings โ†’ General: the floating pet window and animations are never created, and the feeding/XP engine is only instantiated in full-pet mode (switching to monitor-only releases it); usage tracking, menu bar, pages, notifications, and export keep working.
  • โŒจ๏ธ Headless aipet CLI โ€” status, reports, and sprite export from the terminal.

๐Ÿ“ฆ Install (alpha)

Homebrew (Apple Silicon) โ€” recommended:

brew install --cask F-e-u-e-r/tap/ai-pet-usage

This handles install, brew upgrade, and brew uninstall. Or grab the latest AI-Pet-Usage-โ€ฆ-arm64.zip from Releases and drag the app to Applications.

Build from source (about a minute; required for Intel Macs):

git clone https://github.com/F-e-u-e-r/ai-pet-usage.git
cd ai-pet-usage
Scripts/build-app.sh
open "dist/AI Pet Usage.app"
  • Requirements: macOS 14+. The Homebrew cask and the prebuilt zip are Apple Silicon; building from source needs the Xcode Command Line Tools (xcode-select --install).
  • First launch: the alpha is ad-hoc signed and not notarized, so macOS blocks it the first time. Try to open the app, then go to System Settings โ†’ Privacy & Security and choose Open Anyway (only if you trust the release). Homebrew does not remove this one-time approval โ€” only Developer ID notarization would (planned for the beta).
  • The app lives in the menu bar; enable launch at login in Settings if you want it always on. It can check GitHub for updates (opt-in โ€” Settings โ†’ General โ†’ Automatically check for updates; a version check only, no usage data is sent), or check on demand from the menu bar.
  • Developer IDโ€“signed/notarized downloads are planned for the beta (see ROADMAP.md).

Claude Code official limits (optional statusline hook)

Claude Code pipes its official rate limits (the real 5-hour / weekly used_percentage) into whatever statusLine command you configure. If a hook saves that payload locally, the app shows provider-reported limits โ€” no manual token budget needed.

Easiest: one command. The aipet CLI ships inside the app bundle and installs everything (writes the bundled hook, backs up settings.json first, and โ€” if your statusLine already points at a script file โ€” wraps that script untouched):

"/Applications/AI Pet Usage.app/Contents/MacOS/aipet" install-hook          # Homebrew / zip install
.build/debug/aipet install-hook                                             # built from source

Add --dry-run to preview without writing. If your existing statusLine is a compound command (with pipes/arguments) rather than a single script path, it won't guess โ€” it refuses with guidance and leaves everything unchanged, so you can wrap it manually (see below). It also refuses (changing nothing) on symlinked/dotfiles-managed settings, non-command statusLine types, and unmanaged hook references, and prints the revert line after installing.

Manual alternative โ€” the same hook lives in the repo at Scripts/claude-statusline-hook.sh (not in the app bundle โ€” Homebrew users: clone the repo or grab the file from the source zip of a release).

Fresh install (you don't have a custom statusline yet) โ€” add to ~/.claude/settings.json:

"statusLine": {"type": "command", "command": "/bin/bash /path/to/ai-pet-usage/Scripts/claude-statusline-hook.sh"}

Already have a custom statusline? Use wrapper mode โ€” your script is never modified, and its stdin (the exact original JSON bytes), stdout, stderr, and exit code all pass through untouched:

  1. Open ~/.claude/settings.json, find your current statusLine.command, and save that string somewhere (rollback = paste it back).
  2. Replace it with the hook wrapping your command:
"statusLine": {"type": "command", "command": "/bin/bash /path/to/ai-pet-usage/Scripts/claude-statusline-hook.sh --wrap /Users/you/.claude/statusline-command.sh"}
  • The wrap target must be executable; for a plain shell script without the executable bit, use --wrap /bin/bash -- /path/to/script.sh.
  • Extra arguments go after --, one per argument (--wrap /path/to/cmd -- --compact); compound shell command strings are not accepted.
  • What gets persisted is a frozen allowlist only โ€” this exact shape, nothing else (session ids, transcript paths, cwd, and any unknown fields are dropped at every level):
{"schema_version": 1, "captured_at": "<UTC ISO8601>",
 "model": {"id": "...", "display_name": "..."},
 "rate_limits": {"five_hour": {"used_percentage": 42, "resets_at": 1789000000},
                 "seven_day":  {"used_percentage": 81, "resets_at": 1789400000}}}
  • The hook makes no network requests; the file stays under ~/Library/Application Support/AIPetUsage/. A payload without usable rate_limits never overwrites the last good file; staleness is judged by the app from the file's mtime.
  • Alternative: any other tool that already saves the payload to ~/.claude/usage-status.json works too โ€” then you don't need this hook at all.

๐Ÿš€ Build & run

Scripts/swiftpm.sh build                 # build everything
Scripts/swiftpm.sh run usagecore-tests   # run the test suite
Scripts/build-app.sh                     # produce dist/AI Pet Usage.app
open "dist/AI Pet Usage.app"

.build/debug/aipet status                # headless status (CLI)
.build/debug/aipet sprites               # export pixel-pet contact sheets โ†’ dist/sprite-preview/
.build/debug/aipet report --out r.html   # headless HTML export

Important

Always build through Scripts/swiftpm.sh, not bare swift build.

Why the wrapper exists (dev-machine CommandLineTools quirks)

This machine's CommandLineTools installation has two version-mismatch defects (a stale PackageDescription.private.swiftinterface and a duplicate SwiftBridging modulemap) that the wrapper works around per-invocation without touching system files. A CLT reinstall (sudo rm -rf /Library/Developer/CommandLineTools && xcode-select --install) makes the workarounds auto-disable. The CLT also lacks XCTest, so tests run as the usagecore-tests executable with an XCTest-compatible mini harness.

๐Ÿ—‚๏ธ Repository layout

Path What lives there
Sources/UsageCore Provider adapters, ledger, limit engine, pricing, HTML report โ€” no UI dependencies, so the parser logic can be reused by a CLI or Tauri build later. Model prices live in model-prices.json (sourced & dated per entry; see docs/DATA_SOURCES.md).
Sources/PetCore Feeding/XP engine and mood engine โ€” consumes only normalized UsageCore state.
Sources/AIPetUsage The macOS app: menu bar, floating pet panel, the three pages, settings.
Sources/aipet Headless CLI for verification and scripting.
Sources/usagecore-tests Test suite with synthetic fixtures.
docs/DATA_SOURCES.md Exactly which local files are read, and why.

๐Ÿ›ก๏ธ Privacy โ€” local-first by default

  • โœ… Reads only known local usage files or user-configured paths.
  • ๐Ÿšซ Does not upload usage data. The optional update check (Settings โ†’ General) contacts GitHub for the latest version only โ€” no usage data is sent, and it can be turned off.
  • ๐Ÿšซ Does not require account credentials.
  • ๐Ÿ’ฌ Every permission prompt explains why it is needed.
  • ๐Ÿงฉ Provider adapters stay isolated, so data-source changes do not affect the pet engine.

See PRIVACY.md for the promise in plain language and docs/DATA_BOUNDARY.md for the per-data-class checklist of where each thing can (and can't) go.

โš™๏ธ Concurrency model (app + CLI)

The app and the aipet CLI share ~/Library/Application Support/AIPetUsage/. This is safe by design:

  • CLI status/report are read-only by default โ€” they render the ledger and limit state already on disk (add --refresh to rescan provider logs).
  • Every writing phase (app refresh, CLI --refresh, reindex) takes an exclusive interprocess file lock (refresh.lock, flock-based). A process that cannot get the lock within 60s skips the write, reports "refresh skipped" in data-quality notes, and serves cached data.
  • Before writing, each process converges with the other's progress (ledger reload on size change, per-file max-offset merge of scan state, limit-state reload). Event IDs are content-stable, so any overlap deduplicates instead of double-counting.

๐Ÿงญ Product direction

The app combines two ideas:

  1. A lightweight desktop pet with engagement mechanics.
  2. A local-first AI usage monitor for tools such as Codex, Claude Code, Antigravity, Grok Code, and later OpenCode.

The pet makes usage state visible without requiring the user to open dashboards or run commands, reacting to useful signals such as quota remaining, reset windows, token burn rate, stale data, focus sessions, and usage milestones.

The product deliberately avoids a crowded single-page dashboard: usage is separated into the three pages (Today, Limits, Projects), and the HTML report export is part of the alpha scope as a local, offline-readable snapshot of the same data.

Platform & stack

macOS-first; Windows and Linux are planned as the next platform step after the macOS MVP is stable.

  • SwiftUI + AppKit for the desktop shell, floating pet window, menu bar, notifications, and launch-at-login.
  • A separate usage core with provider adapters, so the parser logic can later be reused by a Tauri or CLI version.
  • Local JSON or SQLite storage for settings, achievements, and daily summaries.

Provider priority: v1 core โ€” Codex and Claude Code ยท shipped, limited data โ€” Grok Code (enabled by default; token usage + plan tier; this app does not yet ingest Grok's official limits) ยท research โ€” Antigravity, if a reliable local data source appears ยท v2 โ€” OpenCode.

๐Ÿ“š Documentation

Document Contents
ROADMAP.md Phased delivery plan from product definition through distribution.
PRIVACY.md ยท docs/DATA_BOUNDARY.md Privacy promise (plain language) and the per-data-class boundary checklist.
docs/DATA_SOURCES.md Exact local files read by each provider adapter and the limit-calculation policy.
docs/HTML_REPORT_EXPORT_SPEC.md Local static HTML report export requirements.

โš–๏ธ License

Copyright (C) 2026 F-e-u-e-r

This project is licensed under the GNU AGPL-3.0-only. All code and pixel art (the dog, cat, and bird string-grid sprites) are original to this repository and carry the same license.

The app reads local data files produced by third-party tools (Claude Code, Codex, and Grok CLI session logs and status files). Reading them does not change their respective ownership or terms, and this project never redistributes their contents โ€” everything stays on your machine (see docs/DATA_SOURCES.md).

About

๐Ÿพ A macOS desktop pet that reacts to your AI usage โ€” quota, token burn rate, cost, and work rhythm. Local-first SwiftUI menu-bar app with Codex & Claude Code adapters.

Topics

Resources

License

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors