{"id":48707943,"url":"https://github.com/roastcodes/ttdash","last_synced_at":"2026-06-06T14:00:17.285Z","repository":{"id":350571868,"uuid":"1206404573","full_name":"roastcodes/ttdash","owner":"roastcodes","description":"TTDash is a local-first dashboard and CLI for toktrack usage data","archived":false,"fork":false,"pushed_at":"2026-06-06T12:04:49.000Z","size":4828,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T13:22:06.986Z","etag":null,"topics":["ai-cost","antrophic","claude-code","cli","codex","cost-tracker","dashboard","gemini","llm","local-first","openai","token-tracker","token-tracking","tokens","toktrack","usage-tracking"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@roastcodes/ttdash","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/roastcodes.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":null,"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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-09T22:07:17.000Z","updated_at":"2026-06-06T12:04:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/roastcodes/ttdash","commit_stats":null,"previous_names":["roastcodes/ttdash"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/roastcodes/ttdash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastcodes%2Fttdash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastcodes%2Fttdash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastcodes%2Fttdash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastcodes%2Fttdash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roastcodes","download_url":"https://codeload.github.com/roastcodes/ttdash/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastcodes%2Fttdash/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33984824,"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-06T02:00:07.033Z","response_time":107,"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":["ai-cost","antrophic","claude-code","cli","codex","cost-tracker","dashboard","gemini","llm","local-first","openai","token-tracker","token-tracking","tokens","toktrack","usage-tracking"],"created_at":"2026-04-11T12:20:34.713Z","updated_at":"2026-06-06T14:00:17.162Z","avatar_url":"https://github.com/roastcodes.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TTDash\n\n[![CI](https://github.com/roastcodes/ttdash/actions/workflows/ci.yml/badge.svg)](https://github.com/roastcodes/ttdash/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/%40roastcodes%2Fttdash)](https://www.npmjs.com/package/@roastcodes/ttdash)\n[![License](https://img.shields.io/github/license/roastcodes/ttdash)](LICENSE)\n[![Node \u003e=20](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js\u0026logoColor=white)](https://github.com/roastcodes/ttdash/blob/main/package.json)\n\n`TTDash` is a local-first dashboard and CLI for `toktrack` usage data. It runs entirely on your machine, turns raw usage exports into charts and operational summaries, and keeps your stored data, settings, and imports on local disk instead of a hosted backend.\n\n`TTDash` is built around the usage data provided by [`toktrack`](https://github.com/mag123c/toktrack). Thanks to [mag123c](https://github.com/mag123c) for creating and maintaining the data source this dashboard builds on.\n\n## Keep Claude Code History\n\nClaude Code cleans up old sessions after 30 days by default. If you want long-term cost history in `toktrack` and `TTDash`, raise or effectively disable that cleanup in `~/.claude/settings.json`:\n\n```json\n{\n  \"cleanupPeriodDays\": 9999999999\n}\n```\n\n![TTDash dashboard screenshot](docs/ttdash-dashboard.png)\n\n## Why TTDash\n\n- Local-first by default: no cloud backend, no remote database, no analytics\n- Fast to try: `npx` and `bunx` work without a global install\n- Built for daily usage review, cost tracking, and model/provider breakdowns\n- Works with `toktrack` exports and legacy `ccusage` JSON\n- Can auto-import local `toktrack` data and run in the background\n\n## Dashboard At A Glance\n\nDeeper cost and model analysis:\n\n![TTDash analytics screenshot](docs/ttdash-dashboard-analytics.png)\n\nSettings, local backups, and saved defaults:\n\n![TTDash settings screenshot](docs/ttdash-dashboard-settings.png)\n\n## Quick Start\n\nRequirements:\n\n- Node.js `20+`\n- A modern browser on the same machine\n- Typst CLI only if you want PDF export\n\nRun `TTDash` directly from the npm registry:\n\n```bash\nnpx --yes @roastcodes/ttdash@latest\n```\n\nOr with Bun:\n\n```bash\nbunx @roastcodes/ttdash@latest\n```\n\nSmoke-check the published CLI without starting the dashboard:\n\n```bash\nnpx --yes @roastcodes/ttdash@latest --help\nbunx @roastcodes/ttdash@latest --help\n```\n\nFor a persistent global install:\n\n```bash\nnpm install -g @roastcodes/ttdash\nttdash\n```\n\n```bash\nbun add -g @roastcodes/ttdash\nttdash\n```\n\n## First Run\n\nStart the app:\n\n```bash\nttdash\n```\n\n`TTDash` starts a local server, opens the dashboard in your browser, and automatically retries on the next free port if `3000` is already in use.\n\nThen either:\n\n1. Click `Auto-Import` to load local `toktrack` data\n2. Upload a `toktrack` JSON file manually\n3. Upload a legacy `ccusage` export\n4. Open `Settings` to export or import local backups\n\nThe auto-import path prefers:\n\n1. local `toktrack`\n2. `bunx` with the exact `toktrack` package spec pinned by this TTDash release\n3. `npx --yes` with the exact `toktrack` package spec pinned by this TTDash release\n\n## Common Commands\n\nQuick examples:\n\nRun on a specific port:\n\n```bash\nttdash --port 3010\n```\n\nDisable browser auto-open:\n\n```bash\nttdash --no-open\n```\n\nImport local data immediately on startup:\n\n```bash\nttdash --auto-load\n```\n\nStart in the background:\n\n```bash\nttdash --background\n```\n\nStop a running background instance:\n\n```bash\nttdash stop\n```\n\nCombine flags when needed:\n\n```bash\nttdash --background --port 3010 --auto-load\nttdash --background --no-open\n```\n\nEnvironment-variable equivalents:\n\n```bash\nPORT=3010 ttdash\nNO_OPEN_BROWSER=1 ttdash\nHOST=127.0.0.1 ttdash\n```\n\n## CLI Reference\n\nUsage:\n\n```bash\nttdash [options]\nttdash stop\n```\n\nOptions:\n\n| Option              | Description                                  |\n| ------------------- | -------------------------------------------- |\n| `-p, --port \u003cport\u003e` | Set the start port                           |\n| `-h, --help`        | Show CLI help                                |\n| `-no, --no-open`    | Disable browser auto-open                    |\n| `-al, --auto-load`  | Run local auto-import immediately on startup |\n| `-b, --background`  | Start TTDash as a background process         |\n\nCommands:\n\n| Command       | Description                                                                                                             |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `ttdash stop` | Stop one or more running background instances. If multiple instances are running, TTDash prompts for which one to stop. |\n\nEnvironment variables:\n\n| Variable                                  | Description                                            |\n| ----------------------------------------- | ------------------------------------------------------ |\n| `PORT`                                    | Override the start port                                |\n| `NO_OPEN_BROWSER=1`                       | Disable browser auto-open                              |\n| `HOST`                                    | Override the bind host                                 |\n| `TTDASH_ALLOW_REMOTE=1`                   | Explicitly allow binding to a non-loopback host        |\n| `TTDASH_REMOTE_TOKEN=\u003clong-random-token\u003e` | Required for non-loopback binds; use at least 24 chars |\n\nBinding to a non-loopback host such as `0.0.0.0` exposes the local dashboard API to your network, including destructive routes for local data and settings resets. TTDash refuses that bind unless you set both `TTDASH_ALLOW_REMOTE=1` and a `TTDASH_REMOTE_TOKEN` with at least 24 characters. Only use remote token access over a trusted LAN, VPN, or SSH tunnel; for any public hostname, put TTDash behind an HTTPS reverse proxy with valid TLS termination before sending the bearer token.\n\nExample:\n\n```bash\nTTDASH_ALLOW_REMOTE=1 TTDASH_REMOTE_TOKEN=\u003clong-random-token\u003e HOST=0.0.0.0 ttdash\ncurl -H \"Authorization: Bearer $TTDASH_REMOTE_TOKEN\" http://127.0.0.1:3000/api/usage\n```\n\nWhen calling the server from another device, replace `127.0.0.1` with the server's LAN, VPN, or\nSSH-tunneled host. For public hostnames, call an HTTPS reverse proxy URL instead; do not send the\nbearer token over public HTTP.\n\nRemote API requests can authenticate with the `Authorization: Bearer $TTDASH_REMOTE_TOKEN` header or the equivalent `X-TTDash-Remote-Token: $TTDASH_REMOTE_TOKEN` header.\n\n## Features\n\n- Provider and model filtering across OpenAI, Anthropic, Google, and other imported providers\n- KPI sections for overall usage, today, and current month\n- Cost charts, cumulative projection, forecast, token mix, model mix, heatmap, and weekday analysis\n- Drill-down modal for per-day details\n- CSV export and PDF export\n- Command palette, keyboard shortcuts, and responsive layout\n- Settings-backed defaults, section visibility, and local backups\n\n## Local Storage and Privacy\n\n`TTDash` is designed to stay local:\n\n- No cloud backend\n- No remote database\n- No third-party fonts, analytics, or runtime tracking\n- Imported usage data is stored on your machine\n- Settings such as language, theme, provider limits, filters, and layout are stored on your machine\n\nPlatform paths:\n\n- macOS: `~/Library/Application Support/TTDash/`\n- Windows: `%LOCALAPPDATA%\\\\TTDash\\\\` for data and `%APPDATA%\\\\TTDash\\\\` for settings\n- Linux: `~/.local/share/ttdash/` for data and `~/.config/ttdash/` for settings\n\n## Backups\n\nThe `Settings` dialog can export and import:\n\n- app settings backups\n- stored usage data backups\n\nData-backup import is conservative by design:\n\n- missing days are added\n- identical days are skipped\n- conflicting existing days stay local and are reported instead of being overwritten silently\n\nIf you want to fully replace the current dataset with a fresh `toktrack` JSON, keep using the normal upload action in the header.\n\n## Troubleshooting\n\n### `ttdash` not found after install\n\nMake sure your global package manager bin directory is in `PATH`.\n\nFor Bun:\n\n```bash\necho $PATH\nls -la ~/.bun/bin/ttdash\n```\n\n### Port already in use\n\n`TTDash` automatically retries on the next port. You can also force one:\n\n```bash\nPORT=3010 ttdash\n```\n\n### Auto-import cannot find `toktrack`\n\nInstall `toktrack` locally or ensure `bunx` / `npx` can execute it in the same terminal environment where you run `ttdash`.\n\n### PDF export fails\n\nPDF export requires the Typst CLI to be installed locally.\n\nmacOS:\n\n```bash\nbrew install typst\n```\n\nOther platforms:\n\n- install Typst from `https://typst.app/`\n- make sure `typst --version` works in the same terminal where you run `ttdash`\n\n## Installation From Source\n\nClone the repository and install locally:\n\nmacOS / Linux:\n\n```bash\nsh install.sh\nttdash\n```\n\nWindows:\n\n```bat\ninstall.bat\nttdash\n```\n\nManual source install:\n\n```bash\nnpm install\nnpm run build\nnpm install -g .\nttdash\n```\n\nOr with Bun:\n\n```bash\nbun install\nbun run build\nbun add -g \"file:$(pwd)\"\nttdash\n```\n\n## Development\n\nRun the app locally from the repo:\n\n```bash\nnpm install\nnpm run dev\nnode server.js\n```\n\n- Vite dev server: `http://localhost:5173`\n- API / production server: `http://localhost:3000`\n\nBuild the production bundle:\n\n```bash\nnpm run build\n```\n\n`npm run build` is the gated build and runs `format:check` and `lint` before bundling. If you only want the Vite production bundle, use:\n\n```bash\nnpm run build:app\n```\n\nRun the main local gate without Playwright:\n\n```bash\nnpm run verify\n```\n\nFor the full serial CI/release-style local gate, including coverage thresholds and Playwright, use:\n\n```bash\nnpm run verify:full\n```\n\nOn a local machine with enough CPU, the staged parallel fast path gives quicker feedback across the\nsame main test surfaces without the coverage-instrumented pass:\n\n```bash\nPLAYWRIGHT_TEST_PORT=3016 npm run verify:full:parallel\n```\n\nKeep `npm run verify:full` or `npm run test:vitest:coverage` in the final validation path whenever\ncoverage thresholds matter.\n\nIf you want to run the steps individually, use:\n\n```bash\nnpm run check:deps\nnpm run test:architecture\nnpm run test:unit:coverage\nnpm run test:e2e:ci\n```\n\nTo inspect the slowest suites and test cases after a Vitest run:\n\n```bash\nnpm run test:timings\n```\n\nThe Playwright suite starts an isolated local app per worker under `.tmp-playwright/workers/`. For\nstable Playwright-only validation from another base port, use the CI-style worker cap:\n\n```bash\nPLAYWRIGHT_TEST_PORT=3016 npm run test:e2e:ci\n```\n\nUse `npm run test:e2e` when you intentionally want the fresh app build plus the default local worker\ncount.\n\nRefresh the README screenshots:\n\n```bash\nnpm run docs:screenshots\n```\n\n## Release and Project Docs\n\n- Contributor guide: [`CONTRIBUTING.md`](CONTRIBUTING.md)\n- Release guide: [`RELEASING.md`](RELEASING.md)\n- Architecture rules: [`docs/architecture.md`](docs/architecture.md)\n- Test architecture: [`docs/testing.md`](docs/testing.md)\n- Security policy: [`SECURITY.md`](SECURITY.md)\n- Code of conduct: [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md)\n\n## Status\n\nGitHub Actions now runs formatting checks, ESLint, `tsc --noEmit`, unit/integration coverage, the production bundle, packaged-artifact verification, and Playwright smoke tests for pull requests and pushes to `main`.\n\n## License\n\nMIT. See [`LICENSE`](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froastcodes%2Fttdash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froastcodes%2Fttdash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froastcodes%2Fttdash/lists"}