English · 简体中文
See every token.
Local-first observability for AI coding agents.
Monitor token usage, trends, and session history from Claude Code, Codex, opencode, and Grok Build / CLI in one native macOS menu bar app.
Download the latest release · Watch the 45-second product film · Run from source · Contribute
Click the poster to play the 1080p product film. All projects, sessions, and numbers shown are fictional.
When several AI coding agents are working at once, token usage is scattered across tools, file formats, and sessions. You can see what each agent produces, but it is much harder to answer:
- Which tasks are running right now, and which one is consuming tokens fastest?
- Is a context window approaching its limit?
- Based on local history, how many tokens might this task use by the time it finishes?
- Over the past 7 or 30 days, which agents, models, and projects used most of the tokens?
- Which session contains the work you did last week?
tokenScope brings those answers into a native menu bar panel.
tokenScope is not a proxy, gateway, or new billing layer. It does not intercept model traffic and does not need API keys. It only reads session records that your agents have already stored locally, outside the request path.
That means it does not change how your agents run, and it does not upload prompts, project names, or usage data to another service.
▶ Watch the professional product film with sound · Open the lightweight HD demo
Every public demo is generated from DemoFixture.swift. Demo mode does not start the real data store or open any local session files.
The menu bar is the first layer of information: it normally shows today's total token usage; while tasks are active, it also shows their combined consumption rate.
| Capability | How tokenScope handles it |
|---|---|
| Unified observability | Normalizes JSONL, SQLite, and directory-based session formats from four agents into one model for sessions, tokens, and models. Sources that are not installed are ignored automatically. |
| Near-real-time monitoring | Uses FSEvents, incremental file reads, and source-level refreshes to show cumulative tokens, recent tokens/min, trends, and context usage when available. Refresh speed depends on the source. |
| Historical prediction | Uses recent local sessions that are not considered active to estimate a current task's final P50 / P90 token usage, with an ETA when applicable. |
| Multi-agent coordination | Collapses Codex parent tasks and subagents into a Codex Squad while keeping each member's role, tokens, rate, and trend visible. |
| Token composition | Separates uncached input, output, cache reads, and cache writes. When a model changes during a session, usage is attributed to the corresponding model by message or delta wherever possible. |
| Statistics and trends | Provides today, 7-day, and 30-day windows, aggregated by agent and model, with time trends and a 30-day activity heatmap. |
| Session history | Scans local history and locates work by agent, project name, or session title. Safety-bounded session details are built on demand only when opened. |
| Large-data optimization | Caches summaries by (path, size, mtime) after the first scan and parses active JSONL incrementally by byte offset, avoiding a full rescan on every update. |
| Interface languages | Defaults to English on first launch. Switch between English and Simplified Chinese immediately from Settings; the preference stays on this Mac. |
| Light and dark appearance | Follows macOS by default, with persistent System, Light, and Dark choices in Settings. Each appearance uses its own semantic surface and contrast hierarchy. |
“Near-real-time” does not mean every source provides authoritative process state. Claude Code and Grok Build / CLI can combine session data with local process information; in some cases, Codex, opencode, and other sources infer activity from recent modification time. In the current implementation, file events usually reach the primary state within roughly 1–2 seconds, while source-level refreshes for opencode and Grok Build / CLI run about every 10 seconds. When activity is inferred from modification time, a session changed within roughly the last 120 seconds may be considered active. Context usage is likewise shown only when a source provides enough information.
Prediction runs entirely on your Mac; it is not a remote black-box model. For a task that has already consumed c tokens, tokenScope:
- Looks at sessions from the past 120 days that are not considered active, excluding short sessions below 2,000 tokens.
- Uses a project-level distribution when at least 15 same-project samples exist; otherwise it falls back to history from the same agent.
- Keeps only sessions whose final token total is at least the current consumption
c. - When at least 5 conditional samples remain, calculates P25, P50, and P90 from their final totals. The interface emphasizes the median and the more conservative percentile.
- Recalculates as the task progresses, so the historical percentiles move closer to the point the task has already reached.
In plain language, tokenScope answers:
“Among similar historical tasks that had already reached this usage level, where did they usually finish?”
This is an empirical distribution estimate, not a quota, guarantee, or probabilistically calibrated billing forecast. In the current implementation, a “historical session” means a session not considered active. Because some sources use changes within the last 120 seconds to infer activity, idle, abandoned, or later-resumed sessions can also enter the reference pool.
When fewer than 5 conditional samples are available, the displayed values are no longer empirical percentiles. The current implementation sets base = max(current value, historical maximum), then calculates P50 = 1.1 × base and P90 = 1.4 × P50. The interface shows “Beyond history” only when there are zero conditional samples; with 1–4 samples it still uses the P50 / P90 labels, which is a known communication limitation. ETA appears only when the recent rate is valid, the current value is below P50, and the estimate falls between 1 minute and 10 hours.
tokenScope's aggregate total is composed of whichever token buckets a source can provide:
Total tokens = uncached input + output + cache reads + cache writes
Cost figures must be understood as API-price-equivalent cost, not an actual bill:
- ChatGPT, Claude, or Grok subscriptions may be billed through plans, credits, or other rules.
- When the opencode database records a cost, tokenScope prefers the source-provided figure.
- Other sources are calculated by multiplying model-level token buckets by the price table bundled with the project. That table is not updated automatically over the network.
- Unknown models are excluded from cost conversion by default.
gpt-5.3-codex-sparkis a documented exception: because it has no standalone API price, the current implementation estimates it using pricing from the same model family. - OpenAI long-context surcharges cannot be fully reconstructed from the available session summaries, so related estimates may be a lower bound.
- When a session contains both known and unknown models, the displayed estimate may cover only the priceable portion.
The current UI labels all of these figures as “API Equivalent,” but it does not further distinguish “recorded directly by the source,” “covers known models only,” “long-context lower bound,” or the price table's verification date. For that audit information, inspect the relevant pricing source.
The implementation and price tables live in Pricing.swift and OpenAIPricing.swift. Price updates must document their source, verification date, and applicable limitations in code.
| Agent | Local source | Key handling |
|---|---|---|
| Claude Code | ~/.claude/projects, ~/.claude/sessions |
Deduplicates streamed usage; detects running processes; rolls standalone subagent transcripts into the parent session. |
| Codex | ~/.codex/sessions, ~/.codex/archived_sessions, ~/.codex/session_index.jsonl |
Corrects double counting caused by inherited cumulative values after fork / resume; identifies parent tasks and subagents and assembles a Codex Squad. |
| opencode | ~/.local/share/opencode/opencode.db |
Queries SQLite in read-only mode; refreshes summaries when the database or WAL changes; prefers source-recorded cost. |
| Grok Build / CLI | ~/.grok/sessions, active_sessions.json, logs/unified.jsonl |
Combines durable turn usage, active processes, and live logs to complete in-progress tasks when the source allows it. |
Data directories are currently fixed; there is no UI for custom source paths yet. tokenScope supports only the four agent families listed above.
flowchart LR
A["Local agent session sources<br/>JSONL · SQLite · session logs"] --> B["Source adapters<br/>Read-only parsing · incremental reads"]
B --> C["Unified SessionSummary<br/>Tokens · models · time · project"]
C --> D["UsageStore<br/>Cache · refresh · active-task merge"]
D --> E["Local computation<br/>Prediction · pricing · trend aggregation"]
E --> F["macOS menu bar<br/>Monitor · statistics · history"]
The core data path has no third-party Swift packages and makes no runtime network requests. The first scan reads existing sessions and builds summaries; subsequent updates process only new or changed content.
To accelerate startup, tokenScope writes an invalidatable summary cache locally:
~/Library/Application Support/TokenScope/summary-cache-v4.json
Original agent session sources remain read-only. The summary cache can contain local paths, project names, session titles, models, and usage statistics, so it should also be treated as private local data.
To clear the cache, quit tokenScope first and then delete summary-cache-v4.json above. The next launch will rebuild it from the original sessions. When uninstalling, you may also remove ~/Library/Application Support/TokenScope/.
- No network requests: tokenScope does not upload sessions, tokens, prices, project names, or prompts.
- No telemetry: there are no analytics events, user accounts, or cloud dashboard.
- No API keys required: tokenScope does not call model APIs or proxy agent traffic.
- Original sources are read-only: JSONL and directory-based sessions are parsed but never modified; the opencode database is opened with
SQLITE_OPEN_READONLY. - Session views are built on demand: the first scan still reads raw session bytes to extract tokens, timestamps, models, projects, and session titles; the summary cache does not store the full transcript. Only when you open session details does the app read the source again and build a view bounded by message count, line size, and text length.
- Public demos are isolated from real data:
--demouses completely fictional fixtures and never startsUsageStore.
This also means that the real UI, benchmarks, and some development renders may display project names, session titles, costs, or prompt content. Before submitting an issue, pull request, screenshot, or log, inspect and redact it carefully. Never upload a complete transcript or database.
Download the v1.1.0 Universal macOS DMG from GitHub Releases, open it, and drag TokenScope.app into Applications. A portable Universal zip and SHA-256 checksums are included in the same release.
The v1.1.0 release is Developer ID–signed and notarized by Apple, with the notarization ticket stapled to the DMG. There is no automatic update channel.
- macOS 14 or later
- Swift 6 toolchain (Xcode 16+ or the corresponding Command Line Tools)
- Source compiles in Swift 5 language mode
- No third-party SwiftPM package dependencies
rsvg-convert, required bymake_app.shto generateAppIcon.icns
git clone https://github.com/wuwangzhang1216/tokenScope.git
cd tokenScope
./scripts/make_app.sh
open build/TokenScope.appThe script creates a Universal build/TokenScope.app, copies the Inter font resources, generates the application icon, and uses local ad hoc signing by default. Set TOKENSCOPE_SIGN_IDENTITY for Developer ID signing; distribution DMG, zip, and checksum artifacts are produced by scripts/release.sh.
swift build
swift run TokenScopetokenScope is a MenuBarExtra app. After launch, look for it in the macOS menu bar rather than waiting for a conventional Dock window.
The first launch scans existing sessions. A large local history can make that first scan take longer; once the summary cache has been created, later launches and refreshes are substantially lighter.
The app defaults to English and follows the macOS appearance on first launch. Open the gear at the bottom of the panel to switch between English and Simplified Chinese and choose System, Light, or Dark; changes apply immediately without interrupting a scan or resetting the current view.
The repository currently has no standalone automated test target or CI gate. Accuracy is checked through release builds, source-specific verification tools, and UI rendering tools.
swift build -c release
# Compare aggregate totals with source data
.build/release/TokenScope --benchmark
# Render all three panels for visual inspection
.build/release/TokenScope --render /tmp/tokenscope-ui
# Source-specific debugging checks
.build/release/TokenScope --opencode-check
.build/release/TokenScope --grok-checkPrivacy reminder: The checks above read real local sessions. Their output or screenshots may include project names, session titles, and costs; source checks can also print session excerpts. Do not paste them directly into a public issue or pull request.
Use fictional-data mode for safe public demonstrations:
.build/release/TokenScope --demo tour
# Render publication-safe English and Simplified Chinese screenshots
# from the complete frozen demo fixture
TS_LANGUAGE=en TS_DEMO_DATA=1 .build/release/TokenScope --render /tmp/tokenscope-ui-en
TS_LANGUAGE=zh-Hans TS_DEMO_DATA=1 .build/release/TokenScope --render /tmp/tokenscope-ui-zh
# Force light or dark appearance for public screenshots of the fictional demo
TS_APPEARANCE=light .build/release/TokenScope --demo monitor
TS_APPEARANCE=dark .build/release/TokenScope --demo statsAvailable demo scenes also include intro, monitor, density, squad, stats, history, macro, and menubar.
The professional product film in this repository is reproducible:
- Real SwiftUI views are rendered from fictional data into publication-safe light and dark source frames.
promo/uses JS / JSX and Remotion to animate those exact frames with titles, transitions, and motion graphics.- The soundtrack is synthesized locally in code and contains no third-party music or samples.
- The final film is 1920×1080 at 60 fps, encoded as H.264 + AAC.
See promo/README.md for the complete preview, render, and derivative workflow.
| Path | Responsibility |
|---|---|
Sources/TokenScope/main.swift |
Application entry point and dispatch for headless verification modes |
App/ |
Menu bar lifecycle, UI state, statistics, and model aggregation |
Store/ |
Full scans, incremental updates, FSEvents, caching, and source merging |
Parsing/ |
Claude / Codex JSONL, opencode SQLite, and Grok Build / CLI session / log parsing |
Prediction/ |
Conditional-percentile prediction and API-price-equivalent cost |
Views/ |
Monitor, statistics, session history, and design system |
DemoFixture.swift / DemoMode.swift |
Fictional demos isolated from real data |
promo/ |
Product-film timeline, asset staging, and original soundtrack |
- macOS 14+ only.
- GitHub Releases provides Developer ID–signed, Apple-notarized Universal macOS DMG and zip artifacts; the notarization ticket is stapled to the DMG. There is currently no automatic update channel.
- Reads data only from the fixed default directories for Claude Code, Codex, opencode, and Grok Build / CLI.
- There is no agent-version / schema compatibility matrix yet. Parsers may need to be updated when upstream local formats change.
- Token and context fields are limited by each source schema; the four sources are not guaranteed to be fully symmetrical.
- Prediction depends on local historical samples and cannot replace a budget, quota, or billing system.
- Cost is an API-price-equivalent estimate based on a static price table, not actual subscription spending.
- Historical search matches project names and session titles, not every message body.
- The history list scans the full dataset but shows at most the 300 most recent filtered results at once.
- The session reader loads at most 1,500 sanitized messages and skips oversized content.
These constraints remain explicit in the code instead of being hidden behind stronger-looking numbers that the available data cannot support.
Issues, pull requests, documentation improvements, and new local data-source adapters are all welcome. Even if this is your first Swift or open-source contribution, you can start with a small, clearly scoped problem.
We would especially value contributions in these areas:
- Local source adapters for new agents or new session schemas
- Parser correctness, fork / resume handling, subagent merging, and performance on large datasets
- Fixture-driven parser regression tests and macOS CI
- Price updates with a documented source, verification date, and limitations
- Prediction methods and explainability
- Light / dark UI, Reduce Motion, accessibility, and localization
- Fictional demo fixtures, product-film shots, documentation, and translations
Before you begin, read CONTRIBUTING.md. The project has three non-negotiable principles:
- Local-only: Do not add network requests, telemetry, or uploads.
- Honest numbers: Distinguish facts, conversions, and estimates; show unknown when a value cannot be calculated reliably.
- Respect private data: Do not commit real transcripts, databases, project paths, or unreviewed screenshots and logs.
A high-quality pull request should:
- Keep the change small and single-purpose, and explain why it is needed.
- List the build and verification commands that were actually run.
- For parser changes, document the supported schema, verification method, and—when practical—the minimal synthetic sample used.
- Include redacted screenshots in both light and dark mode for UI changes.
- Cite the source, verification date, and known limitations for pricing or estimation updates.
Good starting points:
- Report a bug or request a feature
- Browse existing issues
- View pull requests
- Report a security vulnerability privately
When reporting a bug, include your macOS and Swift / Xcode versions, the affected agent and its version, minimal reproduction steps, and the expected and actual behavior. Prefer synthetic examples. If you must excerpt a real schema, first remove prompts, project names, usernames, and absolute paths. For larger features or architectural changes, open an issue first so the boundaries can be aligned.
There is not yet a general-purpose fixture runner: --demo exists to present the UI safely, not to validate real parser schemas. Parser contributors should explain in their pull request how they verified the input format. Building a shareable fixture test system with no private data is itself a highly welcome contribution.
Implementation details: protecting count accuracy
A resumed or forked rollout may inherit its parent session's cumulative total_token_usage. Taking the final cumulative value directly would count the inherited usage twice. tokenScope computes the differences between cumulative values within the current file, then adds the first event's own usage to obtain the actual increment for that rollout.
Claude subagent transcripts live in separate subagents/**/agent-*.jsonl files, and their usage does not always appear in the main file. tokenScope parses them separately, rolls the usage into the parent session, and skips journal.jsonl, which follows a different schema.
Claude can write several rows for one response as content blocks stream in; early rows in subagent files can also contain intermediate usage values. tokenScope keeps the final usage for each request and message identifier to avoid double counting.
Completed turns use durable turn_completed.usage data. While the current turn is still running, tokenScope supplements it with inference-completion events from unified.jsonl when available, then defers to the durable data once it arrives.
Local session libraries can reach tens of gigabytes. Parsers first apply low-cost byte filtering, cache summaries by file size and modification time, and tail only new content in active files.
tokenScope is released under the MIT License.
The logo, color palette, and design tokens live in assets/brand/. The Inter font is bundled under its accompanying license; see INTER-LICENSE.txt.
If tokenScope helps you understand how your local agents work, consider starring the repository, sharing your feedback, or contributing one small improvement.