# Tokens for Breakfast — macOS App Specification
## Version 1.0 | Full Product Spec for Development

---

## 1. Product Overview

**App Name**: Tokens for Breakfast  
**Bundle ID**: `com.onekapisch.tokensforbreakfast`  
**Platform**: macOS 13.0 (Ventura) and later  
**Architecture**: Native Swift + SwiftUI + AppKit  
**Distribution**: Direct download from tokensforbreakfast.app (notarized .dmg), not Mac App Store initially  
**Tagline**: *Your daily AI spend. Served clean.*

### What It Is

Tokens for Breakfast is a macOS menu bar application that tracks AI token usage and costs across all major providers and coding tools in real time, stores local history, enforces self-set budgets, and delivers a daily morning digest — all processed locally on the user's Mac with no cloud backend.

### Core Promise

TokenBar shows you the live ticker. Tokens for Breakfast gives you the full picture: live signal, daily history, budget controls, and a morning briefing. It is the one tool that makes AI cost awareness a daily habit instead of a post-billing panic.

---

## 2. Supported Providers (v1.0)

| Provider | Integration Method | Data Captured |
|---|---|---|
| Claude Code (Anthropic) | Local OAuth / Keychain + Anthropic usage API | Tokens in/out, cost, 5-hour window, reset time |
| OpenAI (API key) | OpenAI usage API polling | Tokens in/out, cost by model |
| Cursor | Local log file parsing | Request count, approximate cost |
| GitHub Copilot | Local auth token polling | Request count |
| Gemini (API key) | Google AI Studio usage API | Tokens in/out, cost |
| OpenRouter | OpenRouter usage API | Tokens in/out, cost by model |
| DeepSeek (API key) | API polling | Tokens in/out, cost |
| Mistral (API key) | API polling | Tokens in/out, cost |

**v1.1 roadmap additions**: Vertex AI, Perplexity, Windsurf, Kiro

---

## 3. Pricing & License Model

### Tiers

| Tier | Price | License Type |
|---|---|---|
| Basic | $8 one-time | Lifetime, single device |
| Pro | $15 one-time | Lifetime, single device |

### Basic Tier Includes
- Live token usage in menu bar (up to 3 providers)
- 7-day cost history with daily bar chart
- Basic per-provider cost totals
- System notifications for rate limit warnings
- Claude Code 5-hour window countdown + reset timer
- One daily morning digest notification
- Local SQLite storage, no cloud

### Pro Tier Includes (Everything in Basic Plus)
- Unlimited providers
- 30-day full history with trend charts
- Per-provider daily and weekly budget caps with threshold alerts
- Session-level cost tracking (cost per conversation / agent run)
- Model optimization hints ("This week you spent $12 on Opus for tasks Sonnet handles at $1.40")
- CSV export for any date range
- Provider cost breakdown pie chart
- Weekly summary report (beautiful formatted view, shareable as PNG)
- Priority support

### License Activation
- Payment processor: Lemon Squeezy (handles license key generation, no custom backend needed)
- Activation: User enters license key in Settings — app calls Lemon Squeezy validation endpoint once, caches result locally in Keychain
- Offline: After first activation, app validates cached license locally via HMAC signature (no ongoing internet required)
- No user accounts, no login, no database to maintain

---

## 4. Application Architecture

### Technology Stack

```
Language:       Swift 5.9+
UI Framework:   SwiftUI (primary) + AppKit (menu bar, status item)
Data Storage:   SQLite via GRDB.swift (local only, ~/.tokensforbreakfast/data.db)
Charts:         Swift Charts (native, iOS 16+ / macOS 13+)
Networking:     URLSession with async/await
Credentials:    macOS Keychain Services
Notifications:  UserNotifications framework
Build:          Xcode 15+, minimum deployment macOS 13.0
```

### Process Architecture

```
NSApplication (LSUIElement = true — no Dock icon)
  └── AppDelegate
        ├── StatusBarController     — Manages NSStatusItem + menu
        ├── DataCollectionManager   — Orchestrates all provider polling
        │     ├── ClaudeCodeCollector    (Keychain OAuth + API polling, 60s interval)
        │     ├── OpenAICollector        (API key + usage API, 5min interval)
        │     ├── CursorCollector        (local log file watcher, real-time)
        │     ├── GeminiCollector        (API key + usage API, 5min interval)
        │     └── [other collectors...]
        ├── StorageManager          — GRDB SQLite wrapper
        ├── BudgetEngine            — Evaluates spend vs thresholds, fires alerts
        ├── DigestScheduler         — Schedules 8:00 AM morning notification
        └── LicenseManager          — Lemon Squeezy validation + Keychain cache
```

### Data Models (SQLite Schema)

```sql
-- One row per API call/session captured
CREATE TABLE usage_events (
  id            TEXT PRIMARY KEY,   -- UUID
  provider      TEXT NOT NULL,      -- 'claude', 'openai', 'cursor', etc.
  model         TEXT,               -- 'claude-sonnet-4-5', 'gpt-4o', etc.
  tokens_input  INTEGER,
  tokens_output INTEGER,
  cost_usd      REAL,
  session_id    TEXT,               -- Groups calls into conversations
  captured_at   DATETIME NOT NULL
);

-- Daily aggregated rollups (pre-computed for chart performance)
CREATE TABLE daily_totals (
  date          TEXT NOT NULL,      -- 'YYYY-MM-DD'
  provider      TEXT NOT NULL,
  tokens_total  INTEGER,
  cost_usd      REAL,
  PRIMARY KEY (date, provider)
);

-- User-set budget limits
CREATE TABLE budgets (
  provider      TEXT NOT NULL,
  period        TEXT NOT NULL,      -- 'daily' or 'weekly'
  limit_usd     REAL NOT NULL,
  PRIMARY KEY (provider, period)
);

-- App settings (key-value)
CREATE TABLE settings (
  key   TEXT PRIMARY KEY,
  value TEXT
);
```

---

## 5. UI Specification

### 5.1 Design Language

**Aesthetic Direction**: Refined morning calm. Think a high-quality espresso bar — clean surfaces, warm neutrals, purposeful typography, zero clutter. Not corporate. Not developer-grungy. Elegant utility.

**Color Palette**:
```
Background primary:   #1C1917  (warm near-black, like dark roast)
Background secondary: #292524  (slightly lifted surface)
Background tertiary:  #3C3836  (card/panel backgrounds)
Accent primary:       #F59E0B  (amber — morning light, "breakfast" warmth)
Accent success:       #34D399  (mint green — healthy spend)
Accent warning:       #FBBF24  (yellow — approaching limit)
Accent danger:        #F87171  (coral red — over budget / rate limited)
Text primary:         #FAFAF9  (warm white)
Text secondary:       #A8A29E  (muted warm gray)
Text tertiary:        #78716C  (dimmed labels)
Border subtle:        #44403C  (panel borders)
```

**Typography**:
```
Display font:   "DM Serif Display" (used for numbers, totals, headlines)
Body font:      "DM Sans" (used for labels, body text, UI)
Mono font:      "JetBrains Mono" (used for token counts, costs, model names)
```

All fonts embedded in app bundle. No system font fallbacks for primary UI.

**Spacing System**: 4pt base grid. Components snap to 4, 8, 12, 16, 24, 32, 48pt.

**Corner Radius**: 6pt for small elements (tags, chips), 10pt for cards, 14pt for panels.

**Visual Motif**: Subtle grain texture overlay on all backgrounds (3% opacity noise). Amber glow on the status bar icon when spend is elevated. No rounded blobs, no gradients on gradients.

---

### 5.2 Menu Bar Status Item

The menu bar item is the primary always-visible surface.

**Display States**:

| State | Icon | Label | Color |
|---|---|---|---|
| Normal (low spend) | ☕ icon | `$0.42 today` | Amber |
| Elevated spend | ☕ icon (brighter) | `$4.20 today` | Yellow |
| Near budget limit | ☕ icon (pulsing) | `$8.90 today` | Orange |
| Over budget | ☕ icon (filled) | `$12.00 !` | Red |
| Rate limited (Claude) | ☕ icon (dimmed) | `⏱ 23m` | Gray |
| No providers set up | ☕ icon | `Set up` | Gray |

**Icon Design**: A minimal coffee cup silhouette, 18x18pt. Custom SF Symbol-style design. When spend is elevated, the steam wisps above the cup animate subtly (2s loop, CSS-style keyframe in Core Animation).

**Label**: Always shows today's total cost (all providers combined). Updates every 60 seconds. Format: `$X.XX today`. If over $10, rounds to one decimal: `$12.4 today`.

---

### 5.3 Popover Window (Primary UI)

Clicking the menu bar item opens a popover. The popover is **340pt wide** and resizes vertically based on content. It anchors to the status item and uses the standard macOS popover arrow.

**Popover structure (top to bottom)**:

```
┌─────────────────────────────────────────┐
│  HEADER                                 │  Height: 56pt
│  ☕ Tokens for Breakfast    [⚙] [↗]    │
│  Saturday, March 28                     │
├─────────────────────────────────────────┤
│  TODAY OVERVIEW                         │  Height: 80pt
│  $3.42 total today                      │
│  ████████░░░░░░░  34% of daily budget   │
│  Claude 68% · OpenAI 22% · Cursor 10%  │
├─────────────────────────────────────────┤
│  PROVIDERS                              │  Height: varies
│  ┌─ Claude Code ──────────────────────┐ │
│  │ claude-sonnet-4-5  $2.32           │ │
│  │ ⏱ Rate limit window: 3h 42m left  │ │
│  │ ████████████░░  82% of 5h window  │ │
│  └────────────────────────────────────┘ │
│  ┌─ OpenAI ───────────────────────────┐ │
│  │ gpt-4o  $0.75  · gpt-4o-mini $0.35│ │
│  └────────────────────────────────────┘ │
├─────────────────────────────────────────┤
│  7-DAY SPARKLINE                        │  Height: 80pt
│  ▁▃▅▂▇▄█  (bar chart, last 7 days)     │
│  Mon $1.20 ... Today $3.42             │
├─────────────────────────────────────────┤
│  [View Full History] [Export CSV]       │  Height: 36pt
│  [Settings]          [Buy Pro]          │
└─────────────────────────────────────────┘
```

**Provider cards**: Each provider shows as a rounded card with subtle border. Shows: provider logo (SF Symbol or custom asset), primary model used today, cost today, and for Claude Code specifically: the 5-hour window progress bar and reset countdown.

**Today Overview section**: 
- Large DM Serif Display number for total cost
- Horizontal stacked progress bar showing provider split (colored segments)
- If budget is set: progress bar shows % used of daily budget

**7-Day Sparkline**:
- SwiftUI Charts bar chart, 7 bars
- Bars colored by spend level (green to red gradient)
- X-axis: day abbreviations
- Tapping a bar shows that day's total in a tooltip

---

### 5.4 Full History Window (Pro)

A separate NSPanel window (not modal) triggered by "View Full History" button.

**Window size**: 680pt x 520pt, resizable, minimum 560pt x 400pt.

**Left sidebar (200pt)**:
- Date range picker: Today / 7 Days / 30 Days / Custom
- Provider filter checkboxes
- Total for selected range (large DM Serif Display number)

**Main area**:
- **Tab 1: Timeline** — Daily bar chart for selected range using Swift Charts. Bars stacked by provider (color-coded). Hover state shows tooltip with date breakdown.
- **Tab 2: By Provider** — Horizontal bar chart ranking providers by spend, with percentage labels.
- **Tab 3: By Model** — Same as above but broken down to model granularity.
- **Tab 4: Sessions** (Pro only) — Table view of individual sessions/conversations with cost, model, token count, timestamp. Sortable columns.

**Export button** (Pro only): Triggers CSV export sheet with date range confirmation. Exports to Downloads folder. File format: `tokens-for-breakfast-export-2026-03-28.csv` with columns: date, provider, model, tokens_in, tokens_out, cost_usd, session_id.

---

### 5.5 Settings Window

NSPanel, 500pt x 580pt, tabbed.

**Tab 1: Providers**
- List of all supported providers with enable/disable toggle
- For each enabled provider: credential input (API key field for API-based providers, or "Connect" button for OAuth-based like Claude Code)
- API keys stored in macOS Keychain (never in UserDefaults or SQLite)
- "Test connection" button per provider

**Tab 2: Budgets** (Pro feature)
- For each enabled provider:
  - Daily limit field ($XX.XX)
  - Weekly limit field ($XX.XX)
  - Alert threshold slider (alert me at 80% / 90% / 100%)
- Global daily budget override
- "Notify me when I'm on track" toggle (positive reinforcement: morning digest says "You're on track — $2.10 yesterday, $10 weekly budget 21% used")

**Tab 3: Notifications**
- Morning digest: toggle + time picker (default 8:00 AM)
- Rate limit warning: toggle + threshold (alert when Claude Code window is X% full)
- Budget threshold alerts: toggle
- Digest preview button (shows what this morning's notification would have said)

**Tab 4: License**
- Current tier display (Basic / Pro / Not activated)
- License key input field
- Activate button
- "Buy Pro" button (opens tokensforbreakfast.app/pricing in browser)
- Device ID display (for support)

**Tab 5: About**
- App version, build number
- "Check for updates" button (opens release page)
- Changelog (embedded text)
- Link to support email

---

### 5.6 Morning Digest Notification

Delivered via UserNotifications at user-configured time (default 8:00 AM).

**Basic notification**:
```
Title:  ☕ Morning Report — March 28
Body:   Yesterday: $3.42 total · Claude 68% · OpenAI 22%
        This week: $18.90 of $50 weekly budget
```

**Pro notification** (richer, actionable):
```
Title:  ☕ Morning Report — March 28
Body:   Yesterday: $3.42 (↑ 12% vs avg)
        Week so far: $18.90 · 38% of $50 budget
        Top spender: Claude Sonnet — $2.32
        
        [View History] [Set Budget]
```

Tapping the notification opens the popover.

---

### 5.7 Model Optimization Hints (Pro)

Displayed in the History window as a "Tips" section below charts.

Algorithm logic:
1. Collect all sessions from the past 7 days where Opus or GPT-4o was used
2. Calculate average tokens per session for that provider/model
3. Compare cost against what the same token count would cost on the next tier down
4. If savings > $1 over the 7-day period, surface a tip

**Example tip UI**:
```
┌──────────────────────────────────────────────────┐
│  💡  Optimization Opportunity                     │
│  Last week you spent $14.20 on Claude Opus.      │
│  Claude Sonnet would have cost ~$1.60 for the    │
│  same volume. That's $12.60 you could save       │
│  per week by reserving Opus for complex tasks.   │
│                                [Dismiss]         │
└──────────────────────────────────────────────────┘
```

This is not prescriptive — it is informational. No automated switching.

---

### 5.8 Weekly Summary Report (Pro)

Accessible from the History window. Generates a shareable image.

The summary is rendered as an NSView and exported to PNG (1200x900pt, @2x). Layout:

```
┌──────────────────────────────────────────────────┐
│  ☕ TOKENS FOR BREAKFAST                          │
│  Weekly Report — March 22–28, 2026               │
│                                                  │
│  TOTAL SPEND          DAILY AVERAGE              │
│  $42.80               $6.11                      │
│                                                  │
│  ▁▃▅▂▇▄█  (7-day bar chart)                      │
│                                                  │
│  TOP PROVIDERS                                   │
│  Claude ████████████  $28.40  66%               │
│  OpenAI ████░░░░░░░░  $10.20  24%               │
│  Cursor ██░░░░░░░░░░  $4.20   10%               │
│                                                  │
│  Most used model: claude-sonnet-4-5              │
│  Peak day: Thursday ($12.40)                     │
│                                                  │
│  tokensforbreakfast.app                         │
└──────────────────────────────────────────────────┘
```

User can share this to Twitter/X, LinkedIn, or copy to clipboard. The brand "tokensforbreakfast.app" appears as a subtle footer — organic marketing.

---

## 6. Data Collection Technical Details

### 6.1 Claude Code (Anthropic)

Claude Code stores OAuth credentials in macOS Keychain under the service name used by the Claude CLI. The app reads these credentials (with user permission granted at setup via macOS security prompt), then polls the Anthropic internal usage API endpoint at 60-second intervals.

For the 5-hour rate limit window: The app calculates window usage by summing token events within the rolling 5-hour period from the first event timestamp.

**Important**: This uses the same APIs the official claude.ai web interface uses. The app reads usage data only — never conversation content.

### 6.2 OpenAI

Uses the OpenAI usage API (`/v1/usage`) with the user's API key stored in Keychain. Polls every 5 minutes. Cost calculation uses hardcoded model pricing table (updated with each app release via a bundled JSON file — no network call needed for pricing).

### 6.3 Cursor

Cursor stores session data in local log files at `~/Library/Application Support/Cursor/`. The app uses a file system event watcher (FSEvents) to detect changes and parse relevant usage entries in real time.

### 6.4 Privacy

- Zero telemetry. No analytics SDK. No crash reporting that phones home.
- All data stays in `~/.tokensforbreakfast/` on the user's machine
- API keys stored exclusively in macOS Keychain
- No network connections except: provider API polling (user-configured), Lemon Squeezy license validation (once at activation)
- A privacy audit log is available in Settings > About showing every outbound network request made

---

## 7. App Lifecycle & Launch Behavior

- `LSUIElement = YES` — No Dock icon, runs as agent app
- Launches at login via `SMAppService` (macOS 13+ API, no LaunchAgent plist needed)
- On first launch: onboarding flow (see section 8)
- Menu bar item appears immediately on launch
- Data collection starts immediately for configured providers
- Background: NSBackgroundActivityScheduler for periodic polling at set intervals
- Sleep/wake: Re-polls all providers 30 seconds after wake from sleep

---

## 8. Onboarding Flow

A guided sheet presented on first launch. 4 steps, no friction.

**Step 1: Welcome**
```
☕  Good morning.
Welcome to Tokens for Breakfast.

Your AI spend, tracked locally,
served every morning.

Takes 2 minutes to set up.
[Get Started →]
```

**Step 2: Choose Your Providers**
Grid of provider logos with checkboxes. User selects which they use. "Don't worry — you can add more later."

**Step 3: Connect Providers**
For each selected provider, one at a time:
- Claude Code: "Click Connect — we'll read your existing Claude CLI credentials from Keychain"
- API key providers: Text field with placeholder "sk-..." and a small inline test button

**Step 4: Set a Budget (Optional)**
"What's your comfortable daily AI spend?" — a simple slider from $0 to $50/day. Skippable with "I'll set this later."

**Step 5: You're Ready**
```
☕  You're all set.

We'll check your spend every morning.
Your menu bar is ready.

[Open Menu Bar →]
```

---

## 9. Update Mechanism

No Sparkle or auto-update framework needed for v1.0. Updates are distributed as:
1. GitHub Releases page (free download, check version)
2. "Check for updates" button in Settings opens the GitHub release page
3. In-app update badge in Settings when a new version is available (checked at app launch by fetching a version manifest JSON from GitHub Pages — one HTTPS GET, no SDK)

---

## 10. File Structure

```
TokensForBreakfast/
├── TokensForBreakfast.xcodeproj
├── TokensForBreakfast/
│   ├── App/
│   │   ├── AppDelegate.swift
│   │   ├── TokensForBreakfastApp.swift
│   │   └── Info.plist
│   ├── MenuBar/
│   │   ├── StatusBarController.swift
│   │   ├── PopoverViewController.swift
│   │   └── MenuBarIconView.swift
│   ├── UI/
│   │   ├── Popover/
│   │   │   ├── PopoverView.swift
│   │   │   ├── TodayOverviewSection.swift
│   │   │   ├── ProviderCardView.swift
│   │   │   ├── SparklineView.swift
│   │   │   └── PopoverFooterView.swift
│   │   ├── History/
│   │   │   ├── HistoryWindowController.swift
│   │   │   ├── HistoryView.swift
│   │   │   ├── TimelineChartView.swift
│   │   │   ├── ProviderBreakdownView.swift
│   │   │   ├── ModelBreakdownView.swift
│   │   │   └── SessionsTableView.swift
│   │   ├── Settings/
│   │   │   ├── SettingsWindowController.swift
│   │   │   ├── ProvidersSettingsView.swift
│   │   │   ├── BudgetsSettingsView.swift
│   │   │   ├── NotificationsSettingsView.swift
│   │   │   ├── LicenseSettingsView.swift
│   │   │   └── AboutSettingsView.swift
│   │   ├── Onboarding/
│   │   │   ├── OnboardingWindowController.swift
│   │   │   └── OnboardingView.swift
│   │   └── Components/
│   │       ├── ProviderLogoView.swift
│   │       ├── CostLabel.swift
│   │       ├── BudgetProgressBar.swift
│   │       ├── OptimizationTipCard.swift
│   │       └── WeeklySummaryExportView.swift
│   ├── Core/
│   │   ├── DataCollection/
│   │   │   ├── DataCollectionManager.swift
│   │   │   ├── ClaudeCodeCollector.swift
│   │   │   ├── OpenAICollector.swift
│   │   │   ├── CursorCollector.swift
│   │   │   ├── GeminiCollector.swift
│   │   │   └── OpenRouterCollector.swift
│   │   ├── Storage/
│   │   │   ├── StorageManager.swift
│   │   │   ├── UsageEvent.swift
│   │   │   ├── DailyTotal.swift
│   │   │   └── Budget.swift
│   │   ├── Budget/
│   │   │   └── BudgetEngine.swift
│   │   ├── Digest/
│   │   │   └── DigestScheduler.swift
│   │   ├── License/
│   │   │   └── LicenseManager.swift
│   │   ├── Pricing/
│   │   │   ├── ModelPricingTable.swift
│   │   │   └── pricing.json
│   │   └── Utils/
│   │       ├── KeychainHelper.swift
│   │       ├── CostFormatter.swift
│   │       └── DateHelpers.swift
│   └── Resources/
│       ├── Assets.xcassets
│       │   ├── AppIcon.appiconset
│       │   ├── MenuBarIcon.imageset
│       │   └── ProviderLogos/
│       └── Fonts/
│           ├── DMSerifDisplay-Regular.ttf
│           ├── DMSans-Regular.ttf
│           ├── DMSans-Medium.ttf
│           └── JetBrainsMono-Regular.ttf
├── Tests/
│   ├── StorageManagerTests.swift
│   ├── BudgetEngineTests.swift
│   └── CostCalculationTests.swift
└── README.md
```

---

## 11. Pricing JSON (pricing.json)

Bundled in the app, updated with each release. Allows cost calculation without network requests.

```json
{
  "version": "2026-03-28",
  "models": {
    "claude-opus-4-6": {
      "input_per_million": 15.00,
      "output_per_million": 75.00
    },
    "claude-sonnet-4-6": {
      "input_per_million": 3.00,
      "output_per_million": 15.00
    },
    "claude-haiku-4-5": {
      "input_per_million": 0.80,
      "output_per_million": 4.00
    },
    "gpt-4o": {
      "input_per_million": 2.50,
      "output_per_million": 10.00
    },
    "gpt-4o-mini": {
      "input_per_million": 0.15,
      "output_per_million": 0.60
    },
    "gemini-2.0-flash": {
      "input_per_million": 0.075,
      "output_per_million": 0.30
    }
  }
}
```

---

## 12. Accessibility

- All interactive elements have `accessibilityLabel` set
- Color is never the sole indicator of status (icons accompany color states)
- Full keyboard navigation in settings windows
- VoiceOver support for all primary UI elements
- Respects system reduce-motion preference (disables coffee cup animation)
- Supports both light and dark macOS appearance (app uses dark theme by default but adapts to macOS appearance setting)

---

## 13. App Icon

**Concept**: A coffee cup with a small token/coin visible inside the steam. Clean vector style. Works at all sizes from 16px to 1024px.

At 16px (menu bar): Only the cup silhouette, no detail.  
At 32px and above: Cup with subtle steam wisps.  
At 512px (App Store / about page): Full illustration with warm amber steam and a faint grid/token pattern in the steam.

Background: Dark roast brown (`#1C1917`) with amber accent. Not white. Not blue. Every AI tool has a blue icon.

---

## 14. Marketing Website (tokensforbreakfast.com / .app)

Landing page structure:
1. Hero: "Your daily AI spend. Served clean." — menu bar mockup
2. The problem: One paragraph, no bullet lists. The billing page always wins. TokenBar (not named) only shows live. We show everything.
3. Feature highlights: Live signal + History + Budgets + Morning digest. Each with a real screenshot.
4. Provider logos: All supported providers
5. Pricing: Two cards, lifetime
6. Download button (direct .dmg)
7. One testimonial section (launch: pull from beta testers on X)
8. Footer: tokensforbreakfast.app · Made by @onekapisch · Privacy Policy · Terms

**What to NOT do on the website**: Repeat the same phrase 20 times. Be vague about features. Make the Pro vs Basic distinction unclear. These are all TokenBar sins.
