Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,11 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test

macos-app:
name: macOS menu-bar app
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Test menu-bar package
run: swift test --package-path macos
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
/macos/.build/
*.swp
*.swo
.DS_Store
Expand Down
15 changes: 10 additions & 5 deletions FUTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ Cache parsed data to survive provider log rotation (e.g., Claude Code's 30-day d
- Live-updating stats

### macOS Menu Bar App
SwiftUI `MenuBarExtra` with:
- Quick usage summary in menu dropdown
- Pacemaker budgeting (green/orange/red status)
- Provider toggles
- Click to open detailed view
Phase 1 local alpha is implemented in `macos/` with:
- Quick usage summary in the menu dropdown
- Tokens, cost, and combined headline metrics
- Today, week, month, and all-time scopes using UTC date boundaries
- Configurable executable path, refresh interval, metric, and scope
- Explicit empty, error, timeout, and unavailable-cost states

Remaining work is packaging, signing, distribution, provider filtering, and
budget notifications. The alpha intentionally invokes the local status command
directly and does not add a daemon, IPC layer, telemetry, or network service.

### MCP Server Integration
Expose usage data as an MCP tool so AI assistants can self-monitor their token consumption. Useful for cost-aware agents.
Expand Down
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,55 @@ cd tokemon
cargo install --path .
```

### macOS menu-bar app (local alpha)

The repository includes an optional macOS 13+ menu-bar client. It runs entirely on
the local machine and reads the versioned status document from the installed
`tokemon` executable. The client always requests offline status data, so it does
not start a daemon, open a network connection, or require provider credentials.

Build and launch it from the repository:

```bash
swift build --package-path macos -c release
macos/.build/release/TokemonMenuBar &
```

For a user-local install, copy the release executable to a stable path and
launch that path:

```bash
mkdir -p "$HOME/.local/bin"
install -m 755 macos/.build/release/TokemonMenuBar "$HOME/.local/bin/TokemonMenuBar"
"$HOME/.local/bin/TokemonMenuBar" &
```

Remove the local install with `rm "$HOME/.local/bin/TokemonMenuBar"`. The
source checkout and Rust CLI are unaffected.

The menu shows a headline metric, scope, refresh time, and clear empty/error
states. Open **Preferences…** to choose the executable path, metric (tokens,
cost, or combined), scope (today, week, month, or all time), and refresh interval.
Cost is labelled unavailable when the status response has no pricing table rather
than presenting an unpriced zero. **Open dashboard** launches the detailed local
view in a terminal window.

This is an opt-in local alpha while the menu-bar packaging, signing, and
distribution workflow are developed separately.

#### Troubleshooting

- **Executable not found:** build or install `tokemon`, then leave the path
blank to use `PATH`, or select the full path in **Preferences…**.
- **Path is not executable:** choose the executable file itself, not its
containing directory, and ensure it has execute permission.
- **Cost unavailable:** the local status response did not have a pricing table;
token totals remain available and no zero-cost estimate is shown.
- **Incompatible or malformed status:** update the CLI and applet together; the
applet rejects unknown schema versions instead of guessing at fields.
- **Stale result after a failure:** the last successful result remains visible
with an orange error message while the next scheduled refresh is pending.

## Quick Start

```bash
Expand Down
16 changes: 16 additions & 0 deletions macos/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// swift-tools-version: 6.0

import PackageDescription

let package = Package(
name: "TokemonMenuBar",
platforms: [.macOS(.v13)],
products: [
.executable(name: "TokemonMenuBar", targets: ["TokemonMenuBar"]),
],
targets: [
.executableTarget(name: "TokemonMenuBar"),
.testTarget(name: "TokemonMenuBarTests", dependencies: ["TokemonMenuBar"]),
],
swiftLanguageModes: [.v5]
)
24 changes: 24 additions & 0 deletions macos/Sources/TokemonMenuBar/App.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import AppKit
import SwiftUI

@main
struct TokemonMenuBarApp: App {
@StateObject private var model = AppModel()

init() {
NSApplication.shared.setActivationPolicy(.accessory)
}

var body: some Scene {
MenuBarExtra {
MenuContentView(model: model)
} label: {
Text(model.menuBarTitle)
.monospacedDigit()
.onAppear {
model.start()
}
}
.menuBarExtraStyle(.window)
}
}
Loading
Loading