Thank you for your interest in contributing to Tokenleak. This document covers the development setup, workflow, code style, and testing requirements.
- Bun v1.0.7 or later
- Git
# Clone the repository
git clone https://github.com/ya-nsh/tokenleak.git
cd tokenleak
# Install dependencies
bun install
# Build all packages
bun run build
# Run all tests
bun run test
# Lint
bun run lint
# Format
bun run format| Package | Path | Description |
|---|---|---|
@tokenleak/core |
packages/core |
Shared types, constants, aggregation engine |
@tokenleak/registry |
packages/registry |
Provider parsers (Claude Code, Codex, Open Code) |
@tokenleak/renderers |
packages/renderers |
Output renderers (JSON, SVG, PNG, terminal) |
tokenleak |
packages/cli |
CLI entrypoint |
-
Create a branch from
mainusing the naming convention:feat/<short-description>for new featuresfix/<short-description>for bug fixeschore/<short-description>for maintenance taskstest/<short-description>for test-only changes
-
Make your changes with clean, atomic commits using conventional commit messages:
feat: add streak calculatorfix: handle empty JSONL files gracefullytest: add edge cases for rolling window aggregatorchore: update dependencies
-
Ensure
bun run buildandbun run testpass locally before opening a PR. -
Open a PR against
mainwith a structured description including What, Why, How, Test Coverage, and a Checklist. -
Never commit directly to
main.
Tokenleak publishes to npm from GitHub Actions with npm Trusted Publishing. The publish workflow does not store an npm token and does not run for pull requests.
Configure the package once from an npm account with publish access:
npm trust github tokenleak --repo ya-nsh/tokenleak --file publish-npm.yml --env npm-publishUse these trusted publisher fields if configuring in npmjs.com instead:
- Provider: GitHub Actions
- Organization or user:
ya-nsh - Repository:
tokenleak - Workflow file:
publish-npm.yml - Environment:
npm-publish - Allowed action:
npm publish
After a release PR is merged and the version is ready, publish with one of:
# Manual release from the default branch
gh workflow run publish-npm.yml --ref main
# Tag-triggered release
git tag v<version>
git push origin v<version>Only users with write access to the repository can manually trigger the workflow or push release tags. Forks and pull requests cannot publish because the workflow has no pull_request trigger, and the publish job is restricted to ya-nsh/tokenleak on main or v* tags.
- Strict TypeScript: No
anytypes. Useunknownand narrow properly. - No unhandled promise rejections: Always catch or propagate errors.
- Clear error messages: Errors should include context (file path, line number, etc.) and exit with code 1.
- No magic numbers: Use named constants defined in
@tokenleak/core. - Small functions: Each function should have a single, clear purpose.
- JSDoc: All public types and exported functions should have JSDoc comments.
All new code must include tests. Use Bun's built-in test runner (bun:test).
- Every new function has at least one happy-path test.
- Every new function has at least one failure or edge-case test.
- Aim for at least 80% coverage on new files.
- Happy path: valid JSONL/SQLite with realistic data.
- Empty file handling.
- Missing directory (
isAvailablereturnsfalse, does not throw). - Oversized record: fails with a clear error message.
- Model name normalisation: strips date suffixes correctly.
- Cost calculation: known model + known token count = expected cost.
- Streak: no usage = 0, single day = 1, gap resets streak.
- Streak spanning month and year boundaries.
- Rolling 30-day window excludes data outside the window.
- Peak day with ties (pick the most recent).
- Cache hit rate: 0 cache = 0%, all cache = 100%.
- Empty provider data returns zeroed stats without throwing.
To add a new AI coding tool provider:
- Create a new file in
packages/registry/src/providers/. - Implement the
IProviderinterface from@tokenleak/core:name: unique identifier (e.g.,"my-tool")displayName: human-readable namecolors: accent colours for renderingisAvailable(): returnstrueif the tool's data directory existsload(dateRange?): reads and returnsProviderData
- Register the provider in
packages/registry/src/index.ts. - Add tests in
packages/registry/src/providers/__tests__/. - Open a PR with the provider and its tests.