{"id":50004102,"url":"https://github.com/danmunoz/trmnl-token-meter-cli","last_synced_at":"2026-06-03T23:00:55.868Z","repository":{"id":358700620,"uuid":"1242640150","full_name":"danmunoz/trmnl-token-meter-cli","owner":"danmunoz","description":"Private local Codex usage collector that syncs sanitized token and cost aggregates to a TRMNL display.","archived":false,"fork":false,"pushed_at":"2026-05-18T17:00:45.000Z","size":144,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-18T18:38:41.106Z","etag":null,"topics":["cli","codex","openai","token-usage","trmnl","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/trmnl-token-meter","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danmunoz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-18T15:59:57.000Z","updated_at":"2026-05-18T17:03:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/danmunoz/trmnl-token-meter-cli","commit_stats":null,"previous_names":["danmunoz/trmnl-token-meter-cli"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/danmunoz/trmnl-token-meter-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danmunoz%2Ftrmnl-token-meter-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danmunoz%2Ftrmnl-token-meter-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danmunoz%2Ftrmnl-token-meter-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danmunoz%2Ftrmnl-token-meter-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danmunoz","download_url":"https://codeload.github.com/danmunoz/trmnl-token-meter-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danmunoz%2Ftrmnl-token-meter-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33883102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","codex","openai","token-usage","trmnl","typescript"],"created_at":"2026-05-19T15:00:46.779Z","updated_at":"2026-06-03T23:00:55.862Z","avatar_url":"https://github.com/danmunoz.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TRMNL Token Meter CLI\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/trmnl-token-meter-preview.png\" alt=\"TRMNL Token Meter display preview\" width=\"800\" /\u003e\n\u003c/p\u003e\n\nTRMNL Token Meter is a local collector for showing AI coding token usage on a TRMNL display.\n\nThe CLI runs on your computer, reads enabled local Codex, OpenCode, and Claude usage records, calculates aggregate token and estimated cost totals, and syncs those totals to your TRMNL Token Meter plugin. It is meant for people who want a private, glanceable meter for how much AI coding usage is happening today, this week, and this month.\n\nPrivacy is the core design constraint: raw usage content stays on your machine. The CLI does not upload prompts, responses, commands, diffs, file contents, repository names, or file paths. It sends only aggregate totals and status fields needed to render the TRMNL display.\n\n## Compatibility\n\n- Supported OS: macOS and Linux\n- Supported Node: `\u003e=22.13.0`\n\nThe package manifest enforces the OS restriction at install time.\n\n## How It Works\n\n1. The CLI checks which supported sources are available locally without reading usage content from sources that are not enabled.\n2. It scans only the sources enabled for this device in the TRMNL Token Meter web configuration.\n3. It converts those records into daily, rolling-window, and per-model aggregates.\n4. It uploads only the sanitized aggregate snapshot, collector version, source availability, and enabled-source list needed by the TRMNL Token Meter backend.\n\nThe collector is designed to be useful without becoming another remote analytics pipe. Raw session content stays local.\nNewly supported providers do not start syncing automatically. When a newer CLI\nrelease detects additional supported providers, it prints a privacy note and\npoints you to the web configuration page to enable them.\n\n## Quick Start\n\n1. Install the TRMNL Token Meter plugin in TRMNL.\n2. Open the plugin management page and generate a pairing code.\n3. Run the CLI on the computer you want to track:\n\n```bash\nnpx trmnl-token-meter\n```\n\n4. Enter the pairing code, choose a machine name, and use this backend URL when prompted:\n\n```text\nhttps://trmnl-token-meter-backend.trmnltkn.workers.dev\n```\n\nSetup pairs this machine, uploads the first sanitized aggregate snapshot, and installs background sync. After setup, uploads continue automatically on the configured interval.\n\n## Install Options\n\nRun directly from npm without a global install:\n\n```bash\nnpx trmnl-token-meter\n```\n\nIf you want a persistent local command instead, install from npm:\n\n```bash\nnpm install -g trmnl-token-meter\ntrmnl-token-meter --version\n```\n\n## What Gets Sent\n\nEach upload sends a sanitized aggregate snapshot. The CLI computes this locally before upload. Individual usage records are not sent; only aggregate data, total tokens, estimated costs, and generic status fields are sent. Token mix fields such as input, output, cache read, and cache creation stay local.\n\nCompact representative example:\n\n```json\n{\n  \"schema_version\": \"2026-05-28.v4-14day-window\",\n  \"machine_id\": \"mach_abc123\",\n  \"machine_label\": \"My MacBook\",\n  \"generated_at\": \"2026-05-18T12:42:57.320Z\",\n  \"periods\": {\n    \"today\": {\n      \"start\": \"2026-05-18\",\n      \"end\": \"2026-05-19\",\n      \"total_tokens\": 162000,\n      \"estimated_cost_usd\": 1.2345,\n      \"cost_status\": \"known\",\n      \"pricing_catalog_version\": \"2026-06-02.codexbar-parity\",\n      \"warning_codes\": []\n    },\n    \"last_7_days\": {\n      \"start\": \"2026-05-12\",\n      \"end\": \"2026-05-19\",\n      \"total_tokens\": 680000,\n      \"estimated_cost_usd\": 5.4321,\n      \"cost_status\": \"known\",\n      \"pricing_catalog_version\": \"2026-06-02.codexbar-parity\",\n      \"warning_codes\": []\n    },\n    \"last_14_days\": {\n      \"start\": \"2026-05-05\",\n      \"end\": \"2026-05-19\",\n      \"total_tokens\": 1040000,\n      \"estimated_cost_usd\": 8.7654,\n      \"cost_status\": \"known\",\n      \"pricing_catalog_version\": \"2026-06-02.codexbar-parity\",\n      \"warning_codes\": []\n    },\n    \"last_30_days\": {\n      \"start\": \"2026-04-19\",\n      \"end\": \"2026-05-19\",\n      \"total_tokens\": 2120000,\n      \"estimated_cost_usd\": 16.789,\n      \"cost_status\": \"known\",\n      \"pricing_catalog_version\": \"2026-06-02.codexbar-parity\",\n      \"warning_codes\": []\n    }\n  },\n  \"daily\": [\n    {\n      \"date\": \"2026-05-18\",\n      \"start\": \"2026-05-18\",\n      \"end\": \"2026-05-19\",\n      \"total_tokens\": 162000,\n      \"estimated_cost_usd\": 1.2345,\n      \"cost_status\": \"known\",\n      \"pricing_catalog_version\": \"2026-06-02.codexbar-parity\",\n      \"warning_codes\": [],\n      \"has_usage\": true,\n      \"is_missing\": false\n    }\n  ],\n  \"models\": [\n    {\n      \"name\": \"gpt-5\",\n      \"total_tokens\": 136000,\n      \"estimated_cost_usd\": 1.01,\n      \"cost_status\": \"known\",\n      \"pricing_catalog_version\": \"2026-06-02.codexbar-parity\",\n      \"warning_codes\": []\n    }\n  ],\n  \"source_summaries\": [\n    {\n      \"provider\": \"codex\",\n      \"periods\": { \"...\": \"same aggregate period shape as top-level periods\" },\n      \"daily\": [{ \"...\": \"same daily aggregate shape\" }],\n      \"models\": [{ \"...\": \"same model aggregate shape\" }]\n    }\n  ],\n  \"collector\": {\n    \"version\": \"0.1.0\",\n    \"source\": \"codexbar-local-cost\",\n    \"codex_home\": \"default\",\n    \"cost_engine_version\": \"2026-06-02.codexbar-parity\",\n    \"supported_providers\": [\"codex\", \"opencode\", \"claude\"],\n    \"enabled_providers\": [\"codex\"],\n    \"provider_statuses\": [\n      { \"provider\": \"codex\", \"status\": \"available\" },\n      { \"provider\": \"opencode\", \"status\": \"available\" },\n      { \"provider\": \"claude\", \"status\": \"missing\" }\n    ],\n    \"sources\": [\n      {\n        \"kind\": \"codex_sessions\",\n        \"enabled\": true,\n        \"status\": \"read\",\n        \"record_count\": 42\n      }\n    ],\n    \"warnings\": []\n  }\n}\n```\n\nThe real upload can include up to 15 daily rows, up to 25 normalized model rows,\nand optional source summaries for sources enabled in the web configuration.\nSource availability is reported separately so the backend can show enablement\ncontrols without requiring the CLI to read disabled source contents. It does not\ninclude raw session records or anything needed to reconstruct your conversations.\n\n## What Never Gets Sent\n\nThe CLI does not upload:\n\n- Prompts or responses\n- Tool output\n- Shell commands\n- File contents\n- Diffs\n- Absolute paths\n- Repository names\n- Raw Codex JSONL lines\n- Raw OpenCode SQLite rows or session content\n- Raw Claude project transcripts\n- Priority database rows\n- Pi session contents\n- Auth files, browser cookies, API keys, TRMNL secrets, pairing codes, or collector tokens in aggregate uploads\n\nNo individual usage data is sent. No raw usage content is analyzed remotely. The private parts of your AI coding activity stay local.\n\n## Commands\n\nOpen setup or the local control menu:\n\n```bash\nnpx trmnl-token-meter\n```\n\nWhen a terminal is attached, the control menu uses arrow-key selection and Enter to confirm.\n\nShow current pairing, background sync, and server status:\n\n```bash\nnpx trmnl-token-meter status\n```\n\nUpload one snapshot immediately:\n\n```bash\nnpx trmnl-token-meter sync --once\n```\n\nAdd or replace the paired TRMNL meter:\n\n```bash\nnpx trmnl-token-meter add\n```\n\nRevoke this machine and stop background sync:\n\n```bash\nnpx trmnl-token-meter revoke\n```\n\nRemove background sync:\n\n```bash\nnpx trmnl-token-meter uninstall\n```\n\nBy default, `uninstall` keeps local pairing credentials. Use `uninstall --revoke` if you also want to revoke this machine from the TRMNL meter.\n\n## Background Sync\n\nAfter pairing, the CLI installs a local background job so the display keeps updating without leaving a terminal open.\n\n- macOS: `launchd`\n- Linux: `systemd` when available, otherwise `cron`\n\nThe TRMNL management page controls the collector upload cadence with `1 hour`\n(default), `4 hours`, and `24 hours` presets. Running `status` or completing a\nsuccessful upload lets the CLI refresh the local scheduler when that preference\nchanges.\n\nUse `npx trmnl-token-meter status` to inspect whether background sync is installed and when the last local/server sync completed.\n\n## Non-Interactive Setup\n\nFor scripts or troubleshooting, pair manually:\n\n```bash\nnpx trmnl-token-meter pair \\\n  --code ABCD-1234 \\\n  --machine-label \"My MacBook\" \\\n  --api-base-url https://trmnl-token-meter-backend.trmnltkn.workers.dev\n```\n\nThen install background sync:\n\n```bash\nnpx trmnl-token-meter service install\n```\n\nUpload once:\n\n```bash\nnpx trmnl-token-meter upload\n```\n\n## Test Locally\n\nTo test the CLI from this repository with a persistent local command, install it globally from the repo root:\n\n```bash\npnpm install\npnpm build\nnpm install -g .\n```\n\nThen you can run the CLI directly from later terminal sessions:\n\n```bash\ntrmnl-token-meter --version\ntrmnl-token-meter setup --api-base-url https://trmnl-token-meter-backend.trmnltkn.workers.dev\ntrmnl-token-meter status\n```\n\nThis is useful for local development and manual testing. The public setup flow still uses `npx trmnl-token-meter`.\n\n## Inspect Before Uploading\n\nUse `collect` to print the exact sanitized payload locally without uploading:\n\n```bash\nnpx trmnl-token-meter collect\n```\n\nThis is the best way to verify what would be sent. The output is the aggregate snapshot, not raw session content.\n\n## Local Configuration\n\nThe collector stores credentials, service metadata, and sync state locally on your machine.\n\n- `CODEX_HOME` controls where Codex usage files are read from. Default: `~/.codex`\n- `TRMNL_TOKEN_METER_OPENCODE_DB` points to a specific OpenCode SQLite database. Default: `~/.local/share/opencode/opencode.db`\n- `TRMNL_TOKEN_METER_CLAUDE_CONFIG_DIR` or `TRMNL_TOKEN_METER_CLAUDE_PROJECTS_HOME` points to a Claude config or projects directory when auto-detection is not enough\n- `TRMNL_TOKEN_METER_API_BASE_URL` overrides the backend URL\n- `TRMNL_TOKEN_METER_CONFIG_DIR` overrides the config directory\n- `TRMNL_TOKEN_METER_CACHE_DIR` overrides the cache directory\n- `TRMNL_TOKEN_METER_INCLUDE_PI_SESSIONS=1` includes compatible Pi session aggregates when present\n- `PI_HOME` overrides the Pi home directory. Default: `~/.pi`\n\nDefault local paths:\n\n- macOS config: `~/Library/Application Support/trmnl-token-meter`\n- macOS cache/logs: `~/Library/Caches/trmnl-token-meter`\n- Linux config: `${XDG_CONFIG_HOME:-~/.config}/trmnl-token-meter`\n- Linux cache/logs: `${XDG_CACHE_HOME:-~/.cache}/trmnl-token-meter`\n\nBackground service logs are written to the cache directory as `service.log` and `service.err.log`.\n\n## Project Policies\n\n- Security reporting: [SECURITY.md](./SECURITY.md)\n- Contributing guide: [CONTRIBUTING.md](./CONTRIBUTING.md)\n- Code of conduct: [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)\n- License: [LICENSE](./LICENSE)\n- Release process: [docs/releasing.md](./docs/releasing.md)\n- User-facing change log: [CHANGELOG.md](./CHANGELOG.md)\n\n## Contributing\n\nContributions are welcome, especially around privacy hardening, cross-platform service behavior, documentation, and test coverage.\n\nBefore opening a pull request:\n\n1. Install dependencies with `pnpm install`.\n2. Run `pnpm typecheck`, `pnpm lint`, `pnpm test`, `pnpm test:privacy`, and `pnpm test:pack`.\n3. Update docs and tests in the same change when behavior or payload shape changes.\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for the full contributor workflow and [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) for collaboration expectations.\n\n## License\n\nThis project is released under the [MIT License](./LICENSE).\n\n## Local Sources\n\nBy default, the CLI reads Codex usage from `CODEX_HOME` when set, otherwise `~/.codex`. It also reads OpenCode usage from `~/.local/share/opencode/opencode.db` and scans Claude project transcripts when they exist.\n\nExpected local inputs:\n\n- `$CODEX_HOME/sessions/**/*.jsonl`\n- `$CODEX_HOME/archived_sessions/**/*.jsonl`\n- `$CODEX_HOME/logs_2.sqlite` for priority-tier cost evidence\n- OpenCode SQLite database at `~/.local/share/opencode/opencode.db`\n- Claude project JSONL under `CLAUDE_CONFIG_DIR/projects`, `~/.config/claude/projects`, or `~/.claude/projects` when present\n- `~/.pi/agent/sessions/**/*.jsonl` only when Pi session merging is explicitly enabled\n\nTo read another Codex directory:\n\n```bash\nCODEX_HOME=/path/to/codex-home npx trmnl-token-meter collect\n```\n\nTo read a specific OpenCode SQLite database:\n\n```bash\nTRMNL_TOKEN_METER_OPENCODE_DB=/path/to/opencode.db npx trmnl-token-meter collect\n```\n\nThe OpenCode source reports provider `opencode` and source kind `opencode_sqlite`. The collector reads only normalized `session` columns needed for model, timestamp, token totals, and stored session cost; OpenCode costs come from `session.cost` instead of the local pricing catalog. It does not read OpenCode messages, parts, titles, paths, directories, projects, account metadata, or diff storage.\n\nTo read a specific Claude config or projects directory:\n\n```bash\nTRMNL_TOKEN_METER_CLAUDE_CONFIG_DIR=/path/to/claude-config npx trmnl-token-meter collect\nTRMNL_TOKEN_METER_CLAUDE_PROJECTS_HOME=/path/to/claude/projects npx trmnl-token-meter collect\n```\n\nPi session merging is off by default. Enable it for one command with:\n\n```bash\nnpx trmnl-token-meter collect --include-pi-sessions\n```\n\n## Background Sync\n\nInteractive setup installs background sync automatically.\n\nOn macOS, the CLI installs a user `launchd` agent. On Linux, it prefers a user `systemd` timer and falls back to cron when systemd user services are unavailable.\n\nWhen you run a newer CLI release, it refreshes the installed background runner copy in place so scheduled syncs keep using the current package version.\n\nThe TRMNL management page controls the collector upload cadence with `1 hour`\n(default), `4 hours`, and `24 hours` presets. The CLI reconciles that cadence on\npair, `status`, and successful uploads.\n\nForeground continuous mode is available for debugging:\n\n```bash\nnpx trmnl-token-meter run\n```\n\nClosing the terminal stops foreground mode. Normal setup uses the background scheduler instead.\n\n## Update Checks\n\nHuman-facing commands check npm for a newer `trmnl-token-meter` version at most once per day. Disable that check with either:\n\n```bash\nTRMNL_TOKEN_METER_DISABLE_UPDATE_CHECK=1 npx trmnl-token-meter status\nnpx trmnl-token-meter status --no-update-check\n```\n\n## Local Files\n\nThe CLI stores its local credential and sync metadata in the platform config directory with restrictive permissions.\n\n- macOS: `~/Library/Application Support/trmnl-token-meter`\n- Linux: `${XDG_CONFIG_HOME:-~/.config}/trmnl-token-meter`\n\nThe collector credential is used only to authenticate this machine with your TRMNL Token Meter plugin. Revoking the machine invalidates that credential.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanmunoz%2Ftrmnl-token-meter-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanmunoz%2Ftrmnl-token-meter-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanmunoz%2Ftrmnl-token-meter-cli/lists"}