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
691 changes: 106 additions & 585 deletions README.md

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,35 @@ Use Tokmeter when another app, agent, or automation needs local token/cost telem

## Canonical package names

Always use the published npm scope below.

- `@sriinnu/tokmeter-core`
- `@sriinnu/tokmeter-cli`
- `@sriinnu/tokmeter-tui`
- `@sriinnu/tokmeter-web`
- `@sriinnu/drishti`
The published packages are `@sriinnu/tokmeter` and `@sriinnu/drishti`.
Use `@sriinnu/tokmeter` for the core API and `@sriinnu/tokmeter/cli` for convenience helpers.
The core, CLI, TUI, and web workspace packages are private implementation packages.

## Choose the right surface

| Need | Use | Why |
| --- | --- | --- |
| Embedded programmatic access in Node/Bun | `@sriinnu/tokmeter-core` | Lowest-level API with scan, aggregation, pricing, cleanup, and restore support |
| Shell / CI / script automation | `@sriinnu/tokmeter-cli --json` | Stable machine-readable contract without writing parser code |
| Convenience wrappers around common queries | `@sriinnu/tokmeter-cli` imports | Exposes summary, project, model, daily, stats, pricing, digest, cleanup, and restore helpers |
| Embedded programmatic access in Node/Bun | `@sriinnu/tokmeter` | Lowest-level API with scan, aggregation, pricing, cleanup, and restore support |
| Shell / CI / script automation | `npx @sriinnu/tokmeter --json` | Stable machine-readable contract without writing parser code |
| Convenience wrappers around common queries | `@sriinnu/tokmeter/cli` imports | Exposes summary, project, model, daily, stats, pricing, digest, cleanup, and restore helpers |
| Live token/cost answers inside an AI workflow | `@sriinnu/drishti` | MCP server, daemon, statusline, and live tracker APIs |
| Human exploration | `@sriinnu/tokmeter-tui` or `@sriinnu/tokmeter-web` | Best for interactive/manual inspection |
| Human exploration | `npx -p @sriinnu/tokmeter tokmeter-tui` or the web workspace | Best for interactive/manual inspection |

## Recommended integration order

1. If your AI platform can speak MCP, use `@sriinnu/drishti`.
2. If you need batch automation or CI checks, call `@sriinnu/tokmeter-cli --json`.
3. If you need one reusable in-process scan, use `@sriinnu/tokmeter-core`.
4. If you want convenience helpers without shelling out, import from `@sriinnu/tokmeter-cli`.
2. If you need batch automation or CI checks, call `npx @sriinnu/tokmeter --json`.
3. If you need one reusable in-process scan, use `@sriinnu/tokmeter`.
4. If you want convenience helpers without shelling out, import from `@sriinnu/tokmeter/cli`.

## Quick examples

### Shell / CI

```bash
npx @sriinnu/tokmeter-cli --json
npx @sriinnu/tokmeter-cli models --json --project tokmeter
npx @sriinnu/tokmeter-cli digest --json --period week
npx @sriinnu/tokmeter --json
npx @sriinnu/tokmeter models --json --project tokmeter
npx @sriinnu/tokmeter digest --json --period week
```

### Convenience methods
Expand All @@ -47,7 +43,7 @@ import {
loadTokmeterProjects,
loadTokmeterStats,
lookupTokmeterPricing,
} from "@sriinnu/tokmeter-cli";
} from "@sriinnu/tokmeter/cli";

const summary = await loadTokmeterSummary({ month: true });
const projects = await loadTokmeterProjects({ project: "command-relay" });
Expand All @@ -58,7 +54,7 @@ const pricing = await lookupTokmeterPricing("claude-sonnet-4-20250514");
### Direct core usage

```ts
import { TokmeterCore } from "@sriinnu/tokmeter-core";
import { TokmeterCore } from "@sriinnu/tokmeter";

const core = new TokmeterCore();
await core.scan({ providers: ["codex", "claude-code"], since: "2026-04-01" });
Expand All @@ -79,3 +75,7 @@ const summary = core.getSummary();
- `packages/core/src/index.ts`
- `packages/cli/src/index.ts`
- `packages/mcp/src/index.ts`

## Licenses

Applications use AGPL-3.0-only; core source uses MPL-2.0. See [licenses and source](docs/licensing.md).
44 changes: 22 additions & 22 deletions docs/consuming-tokmeter.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,31 @@ Use this guide when another AI project, CLI, service, or editor integration need

| Need | Use | Why |
| --- | --- | --- |
| Local programmatic access in Node/Bun | `@sriinnu/tokmeter-core` | Lowest-level API with full scan, aggregation, filtering, cleanup, and pricing access |
| Shell automation / CI / scripting | `@sriinnu/tokmeter-cli` with `--json` | Stable shell entrypoint that emits machine-readable JSON |
| Convenience helpers without shelling out | `@sriinnu/tokmeter-cli` imports | Wraps the common summary/project/model/stats queries |
| Local programmatic access in Node/Bun | `@sriinnu/tokmeter` | Lowest-level API with full scan, aggregation, filtering, cleanup, and pricing access |
| Shell automation / CI / scripting | `npx @sriinnu/tokmeter --json` | Stable shell entrypoint that emits machine-readable JSON |
| Convenience helpers without shelling out | `@sriinnu/tokmeter/cli` imports | Wraps the common summary/project/model/stats queries |
| Live token telemetry from an AI agent | `@sriinnu/drishti` | MCP server, daemon, live tracker, and statusline surface |
| Human exploration | `@sriinnu/tokmeter-tui` or `@sriinnu/tokmeter-web` | Best for interactive/manual use, not for automation |
| Human exploration | `npx -p @sriinnu/tokmeter tokmeter-tui` or the web workspace | Best for interactive/manual use, not for automation |

## Canonical published package names

Always use the published names below. Older shorthand like `@tokmeter/*` is not the canonical npm scope.

- `@sriinnu/tokmeter-core`
- `@sriinnu/tokmeter-cli`
- `@sriinnu/tokmeter-tui`
- `@sriinnu/tokmeter-web`
- `@sriinnu/drishti`
The published packages are `@sriinnu/tokmeter` and `@sriinnu/drishti`.
Use `@sriinnu/tokmeter` for the core API and `@sriinnu/tokmeter/cli` for convenience helpers.
The core, CLI, TUI, and web workspace packages are private implementation packages.

## Recommended integration order

1. If your tool can speak MCP, use `@sriinnu/drishti`.
2. If you need batch automation or CI checks, use `@sriinnu/tokmeter-cli --json`.
3. If you need embedded logic in Node/Bun code, use `@sriinnu/tokmeter-core` directly.
4. If you want convenience wrappers around common queries, import from `@sriinnu/tokmeter-cli`.
2. If you need batch automation or CI checks, use `npx @sriinnu/tokmeter --json`.
3. If you need embedded logic in Node/Bun code, use `@sriinnu/tokmeter` directly.
4. If you want convenience wrappers around common queries, import from `@sriinnu/tokmeter/cli`.

## Shell / CI integration

### Full summary

```bash
npx @sriinnu/tokmeter-cli --json
npx @sriinnu/tokmeter --json
```

This returns the same summary shape used by the web dashboard:
Expand All @@ -49,13 +45,13 @@ This returns the same summary shape used by the web dashboard:
### Focused queries

```bash
npx @sriinnu/tokmeter-cli projects --json
npx @sriinnu/tokmeter-cli models --json --project tokmeter
npx @sriinnu/tokmeter-cli stats --json --month
npx @sriinnu/tokmeter-cli digest --json --period week
npx @sriinnu/tokmeter projects --json
npx @sriinnu/tokmeter models --json --project tokmeter
npx @sriinnu/tokmeter stats --json --month
npx @sriinnu/tokmeter digest --json --period week
```

## Convenience helpers from `@sriinnu/tokmeter-cli`
## Convenience helpers from `@sriinnu/tokmeter/cli`

```ts
import {
Expand All @@ -67,7 +63,7 @@ import {
runDigest,
runCleanup,
runRestore,
} from "@sriinnu/tokmeter-cli";
} from "@sriinnu/tokmeter/cli";

const summary = await loadTokmeterSummary({ month: true });
const projects = await loadTokmeterProjects({ project: "command-relay" });
Expand All @@ -81,7 +77,7 @@ Use these wrappers when you want the convenience of the CLI package but not the
## Direct core usage

```ts
import { TokmeterCore } from "@sriinnu/tokmeter-core";
import { TokmeterCore } from "@sriinnu/tokmeter";

const core = new TokmeterCore();
await core.scan({ since: "2026-04-01", providers: ["codex", "claude-code"] });
Expand Down Expand Up @@ -121,3 +117,7 @@ Use `@sriinnu/drishti` when an AI assistant should answer token/cost questions d
- `SKILL.md`
- `packages/core/src/index.ts`
- `packages/mcp/src/index.ts`

## Licenses

Applications use AGPL-3.0-only; core source uses MPL-2.0. See [licenses and source](licensing.md).
4 changes: 2 additions & 2 deletions docs/licensing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ Tokmeter's applications (CLI, TUI, web dashboard, daemon/MCP server, and macOS a

## Included materials

The npm distributions include `dist/licenses/`. The macOS app includes `Contents/Resources/Licenses/`, accessible using **Licenses & source** in the popup footer. Each contains:
The npm distributions include `dist/licenses/`. The macOS app includes `Contents/Resources/Licenses/`, accessible using **Licenses** in the popup footer. Each contains:

- `AGPL-3.0-only.txt` — the application license.
- `MPL-2.0.txt` — the core source license, including when the core is bundled in `@sriinnu/tokmeter`.
- `tokmeter-source.tar.gz` — local source and build inputs collected when this artifact was packaged. The application and core source retain the licenses described above.
- In the macOS app, `Sparkle.txt` — the complete notices supplied with the bundled Sparkle artifact, including its embedded third-party components.

JavaScript dependencies are installed separately by the package manager; their notices reside in their respective installed packages. The source snapshot includes the dependency manifests and lockfile. Build tools and platform SDKs are obtained separately.
JavaScript dependencies are installed separately by the package manager; their notices reside in their respective installed packages. The source snapshot includes the dependency manifests, lockfile, integration skills, and synthetic fixture used by native contrast tests. Build tools and platform SDKs are obtained separately.

Extract the source archive, install Bun and Node.js, and run `bun install --frozen-lockfile` followed by `bun run build` from its root. For the native app, install Xcode on macOS and run `swift build -c release --package-path packages/macos-bar`. Use `bash packages/macos-bar/bundle.sh --no-install` for a local ad-hoc bundle. Apple distribution credentials are not needed for a local build and are never included.

Expand Down
38 changes: 38 additions & 0 deletions docs/macos-completion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
type: Note
status: Active
---

# macOS completion

Owner: Srinivas + Codex. Started 2026-09-06 after the 1.10.0 release. Workflow: branch → reviewed PR → main. **This work is complete only when all six rows are closed with the evidence below.** Passing source tests, publishing a release, and preparing a trial kit do not close the corresponding real-world checks.

| ID | Area | Status | Completion evidence |
|---|---|---|---|
| MAC-01 | Clean installation and first use | In progress | Published app installed on a fresh macOS account/VM or another Mac, with no Tokmeter checkout/global package; supported Node installation discovered; missing prerequisites explained; daemon starts once and real Claude/Codex usage appears. Record app, daemon, OS, architecture, and install path. |
| MAC-02 | Sustained reliability | Open | At least 72 elapsed hours on one identified installed build, recording app/daemon identity, readiness, RSS/CPU, and recovery. Include natural sleep/wake, a reboot, local midnight, and a controlled daemon restart. Fix unexplained failures and rerun affected evidence. |
| MAC-03 | Real Sparkle upgrade | Open | An installed, notarized prior version discovers the published update, downloads/verifies/replaces/relaunches through Sparkle, and resumes usage. Record before/after versions and preservation of settings/history. Signature-only checks do not close this. |
| MAC-04 | Accounting coverage | Open | Independently reconcile numeric live samples for the primary Claude Code/Codex paths, cover resets/replays/mixed formats/cache/reasoning/day boundaries, and qualify every other advertised integration by observed evidence. Explicitly list unavailable data and un-audited historical ranges. |
| MAC-05 | macOS usability and accessibility | Open | Keyboard-only and VoiceOver walkthroughs; small-screen/text clipping checks; Today/history projects discoverable; empty/offline/error states actionable. Fix issues and record the actual app/build used. |
| MAC-06 | Five-person week-long trial | Needs participants | Five consenting macOS users complete seven days of ordinary use and supply the trial feedback. Log install problems, accounting mismatches, repeat use, and fixes. Invitations require selected recipients and explicit send authorization. No recruitment or trial completion is claimed yet. |

## Current checkpoint

- Baseline: published 1.10.0 (46), Apple Silicon, macOS 14+. Release source tag `v1.10.0`; release and distribution PRs #73/#74 merged.
- Active branch: `fix/macos-first-run-and-reliability`.
- MAC-01 finding: auto-start uses `npx @sriinnu/tokmeter daemon start`, but that package dynamically imports Drishti without installing it. The monorepo masks this missing dependency. Auto-start must invoke the published daemon package directly.
- MAC-01 finding: toolchain discovery only checks `/opt/homebrew/bin/npx` and `/usr/local/bin/npx`; managed Node installations and missing prerequisites need explicit handling.
- MAC-02 finding: generic API/decode/version errors enter the same auto-start path as an unreachable daemon. Recovery and incompatible-data states need distinct treatment.
- Spare Mac/VM availability and participant selection requested; independent implementation continues while those are identified.
- First-use fixes implemented on the active branch: invoke the version-matched Drishti package, discover paired Node/npx in system and managed installations, provide Install Node/Retry actions, preserve protocol errors, and drain bounded subprocess output continuously. Native checks: 22 passed, one optional demo render skipped. Fresh-machine acceptance remains open.
- Reproduced the published CLI-only failure from an isolated npm installation: `tokmeter daemon status` cannot resolve `@sriinnu/drishti`. No daemon or usage data was modified by this reproduction.
- MAC-05 source fixes: content-sized popup, explicit disclosure text color, readable Paper model costs, wrapping signal readings, and Noise retired from the picker. The first local build collapsed its body; the failure was reproduced with the full popup and corrected using direct geometry observations. [Review and validation](macos/popover-usability.md): 26 native tests passed, one optional render skipped, including full-popup first-layout and live disclosure-binding regressions. Installed-app interaction, keyboard, and VoiceOver acceptance remains open.
- Signed commit/PR handoff is pending the configured hardware signing key, which was unavailable on the last attempt. These branch changes have not reached main. Corrected local test build 1.10.0 (46.2) replaced 46.1 and was relaunched from `/Applications` on 2026-09-08; binary identity and local signature verified. The Git signing key is not required for local installation.
- Latest local build: 1.10.0 (46.6), installed and running from `/Applications`. Status colors and badge backgrounds now follow the selected theme explicitly. The user's 46.5 screenshot proved the previous adaptive-color fix still failed in the live popup. Opposing-host native widget captures now assert selected-theme pixels; 27 native tests passed. Binary/signature identity verified; the user accepted 46.6 contrast on 2026-09-08. Remaining interaction/accessibility acceptance stays open.

## Evidence and closure rules

- Record commands/results and build identity in focused documents under `docs/macos/`; keep raw usage, paths identifying private projects, transcripts, and credentials out of committed evidence.
- Long-running observations record elapsed time and identity changes; a restart or changed build starts a new segment and cannot silently inherit a completed soak.
- Source/fixture checks may close substeps, never the fresh-Mac, real-update, observed accessibility, or week-long user criteria by themselves.
- Keep this note current in each PR. Completed rows link to evidence and the merged fix. Unresolved rows stay open with the next action and dependency.
35 changes: 35 additions & 0 deletions docs/macos/first-use.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
type: Note
status: Active
---

# MAC-01: first use

Status: implementation and local regression checks complete; fresh-Mac acceptance open. Changes start from released 1.10.0 and are tracked in [macOS completion](../macos-completion.md).

## Reproduction and fixes

A fresh temporary npm prefix containing only `@sriinnu/tokmeter@1.10.0` fails on `tokmeter daemon status`: its dynamic import of `@sriinnu/drishti` cannot resolve. The app used this same package to start the daemon. A workspace or global installation containing both packages masked the defect.

The app now invokes the Drishti package matching its own version. Drishti declares its dependency on Tokmeter, so npm resolves the complete daemon installation. A first download has a bounded 120-second budget. Subprocess stdout/stderr are drained concurrently with bounded retained output, preventing a full pipe from wedging npm until timeout.

Node discovery requires executable Node and npx in the same installation. It supports the standard Homebrew/local paths and conventional Volta, nvm, fnm, mise, and asdf installation directories without sourcing shell profiles. Missing/old Node presents installation and retry actions. Protocol/decode errors from a running service remain visible instead of triggering another daemon launch.

## Local evidence

- Published CLI-only reproduction failed with the expected missing Drishti import; no daemon was started or stopped.
- Managed-installation fixtures cover absent Node, unpaired npx, numeric version selection, and the GUI subprocess PATH.
- Runner tests cover 512 KiB on each output pipe, bounded retention, nonzero exit, a missing executable, and timeout.
- Protocol mismatch test checks that warming/fresh flags and live color claims clear without starting a second service.
- The real error views are rendered at 320 points for text/action layout inspection. This is visual fixture evidence, not a VoiceOver or fresh-Mac result.
- Native suite: 22 passed; one unrelated optional walkthrough render skipped. Repository lint and whitespace checks passed.

## Fresh-Mac acceptance, still required

1. Use another Apple Silicon Mac, a fresh macOS account, or a macOS VM. Record OS and published app/daemon versions.
2. With Node absent, verify the prerequisite explanation and installation action. Install supported Node using a normal method; do not add a Tokmeter checkout or global Drishti package.
3. Open the app and retry. Verify one daemon starts, the app moves out of warming, and the expected Claude/Codex usage appears.
4. Restart the app and verify it attaches to the same daemon without another scan process.
5. Exercise offline download failure and recovery; confirm errors are actionable and retry is bounded.

Record observed results before closing MAC-01. A temporary npm directory on the development Mac is not a substitute for this check.
Loading