tokenpile
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 7 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
A Go CLI + terminal UI that tracks LLM token usage and cost per GitHub issue
Track LLM token usage and cost per GitHub issue. Any agent (Claude Code, OpenCode, Cursor, or your own tooling) calls the CLI to log usage; you browse a TUI to see where time and money went.
Features
- Log token usage from any LLM agent via a single CLI call
- Validates the GitHub issue exists before logging — no phantom entries
- Track by agent name and model separately (e.g.
claude-coderunningclaude-sonnet-4-6) - Sessions with 30-minute idle auto-close for wall-clock time tracking
- Annotate sessions with a
--noteand one or more--taglabels per log call; tags accumulate across calls in the same session - Per-issue spending budget with
tokenpile budget set; report shows consumed vs. total percentage - GitHub issue metadata (title, labels, URL) cached in the local DB at log time
- TUI: issue list with clickable
#NOSC 8 hyperlinks, per-issue detail with Summary and Sessions tabs, budget progress bar (green/yellow/red), token usage chart over time - Open issues in the browser with
o, refresh cached metadata withr - Report and export include issue title and labels
- Ed25519-signed JSON export (schema v2) with sessions and budgets blocks
- Pricing config with built-in defaults and per-model overrides
- SQLite storage — local, no external services required
Installation
Homebrew (macOS / Linux)
brew install cdimonaco/tap/tokenpile
From source
Prerequisites: Go 1.25+
git clone https://github.com/cdimonaco/tokenpile
cd tokenpile
make install
This installs the binary to $GOPATH/bin. Make sure that is on your PATH.
To build without installing:
make build
# produces ./tokenpile
Quick start
1. Authenticate with GitHub
tokenpile auth login --provider github
This opens a browser window for OAuth. The token is stored in your OS keychain (or an encrypted file on headless Linux).
2. Install the skill for your agent
tokenpile skill install --agent claude-code # writes ~/.claude/skills/tokenpile.md
tokenpile skill install --agent codex # appends a block to ~/.codex/AGENTS.md
tokenpile skill install --agent opencode # appends a block to ~/.config/opencode/AGENTS.md
After installation, the agent will automatically call tokenpile log at the end of each response where significant work was done.
For codex and opencode, the skill is appended to their shared AGENTS.md file using HTML comment markers (<!-- tokenpile:start --> / <!-- tokenpile:end -->). Your existing instructions are never touched. Running the command again updates only the tokenpile block in place.
See tokenpile skill list for supported agents and their installation status.
3. Or log manually
tokenpile log \
--issue 42 \
--agent claude-code \
--model claude-sonnet-4-6 \
--tokens-in 12000 \
--tokens-out 3000 \
--note "refactored auth middleware" \
--tag refactor --tag feature
--repo is optional if you run from inside a git repository with a GitHub remote. Otherwise pass it explicitly:
tokenpile log --issue 42 --agent claude-code --model claude-sonnet-4-6 \
--tokens-in 12000 --tokens-out 3000 --repo owner/repo
4. Browse the TUI
tokenpile
Issue list
| Key | Action |
|---|---|
j / k |
navigate up/down |
enter |
open issue detail |
o |
open selected issue in browser |
c |
open chart view |
esc |
go back |
? |
toggle help |
q |
quit |
The list shows a clickable #N link for each issue. In terminals that support OSC 8 hyperlinks (iTerm2, Kitty, most modern terminals) clicking the link opens the issue in your browser.
Issue detail
| Key | Action |
|---|---|
tab |
switch between Summary and Sessions tabs |
o |
open issue in browser |
r |
refresh title and labels from GitHub |
c |
open chart view |
esc |
go back |
d / w |
day / week granularity (chart) |
q |
quit |
Commands
tokenpile log
Record token usage for an issue.
tokenpile log --issue <num> --agent <name> --model <model> \
--tokens-in <n> --tokens-out <n> [--repo owner/repo] \
[--note "description"] [--tag <tag> ...]
| Flag | Description |
|---|---|
--note |
Short description of what was done in this call (last-write-wins per session) |
--tag |
Label for the call; repeatable. Tags accumulate across calls in the same session (union). |
Sessions are managed automatically. The first call for an (issue, repo) pair starts a session; subsequent calls within 30 minutes of the previous log reuse it. After 30 minutes of inactivity since the last log call the session is closed and a new one starts on the next call.
The log command validates that the issue exists on GitHub before inserting the entry. If the issue is not found, the command fails with an error. Issue title and labels are cached in the local DB for use in reports, exports, and the TUI.
tokenpile report
Print a per-(agent, model) breakdown for an issue. The header shows the issue title, URL, and labels if they are in the local cache.
tokenpile report --issue 42
tokenpile report --issue 42 --repo owner/repo
tokenpile report --issue 42 --sessions # also print a per-session breakdown
If a budget is set for the issue, the report shows total consumed vs. budget and the percentage used.
The --sessions flag adds a session list showing start/end time, duration, tags, and note for each session.
tokenpile budget
Set or remove a spending budget for an issue.
tokenpile budget set --issue 42 --amount 10.00 # set $10 budget
tokenpile budget set --issue 42 --amount 10.00 --repo owner/repo
tokenpile budget unset --issue 42 # remove the budget
Once a budget is set, tokenpile report shows the consumed amount alongside the budget, and the TUI issue list shows a colour-coded budget bar (green below 80%, yellow 80–99%, red at or above 100%).
tokenpile auth
tokenpile auth login --provider github # open browser, store token
tokenpile auth logout --provider github # remove stored token
tokenpile auth status # show login state
tokenpile pricing
tokenpile pricing list # show merged config
tokenpile pricing set my-model --in 1.50 --out 6.00 # add/override a model
Prices are per million tokens. Built-in defaults cover the most common Claude, GPT, and Gemini models. User overrides are stored at ~/.config/tokenpile/pricing.yaml and take precedence.
tokenpile export
Export usage data as an Ed25519-signed JSON document (schema v2).
tokenpile export # all data, to stdout
tokenpile export --output data.json # write to file
tokenpile export --repo owner/repo --issue 42 --agent claude-code
tokenpile export --from 2026-01-01T00:00:00Z --to 2026-07-01T00:00:00Z
When filtered to a specific repo+issue, the export includes a sessions block (all sessions for that issue) and a budgets block (budget if set). The Ed25519 signature covers only the entries block; sessions and budgets are informational.
Verify a previously exported file:
tokenpile export verify --file data.json
tokenpile skill
tokenpile skill list # show agents, install status, and skill version
tokenpile skill install --agent claude-code # dedicated file: ~/.claude/skills/tokenpile.md
tokenpile skill install --agent codex # append/update block in ~/.codex/AGENTS.md
tokenpile skill install --agent opencode # append/update block in ~/.config/opencode/AGENTS.md
skill list shows a Version column: "up to date" if the installed skill matches the current version, "outdated (vN)" if a newer version is available. Re-run skill install to upgrade.
For shared AGENTS.md targets (codex, opencode) the command prints a summary of what it did — whether it created the file, appended a new block, or updated an existing one — so you always know exactly what changed.
Configuration
| Variable | Default | Description |
|---|---|---|
TOKENPILE_CONFIG_DIR |
~/.config/tokenpile |
Config directory (overrides XDG) |
TOKENPILE_DATA_DIR |
~/.local/share/tokenpile |
Data directory (overrides XDG) |
TOKENPILE_LOG_LEVEL |
info |
Log level: debug, info, warn, error |
TOKENPILE_LOG_FORMAT |
text |
Log format: text or json |
TOKENPILE_GITHUB_CLIENT_ID |
baked in | Override the built-in GitHub OAuth client ID (development only) |
TOKENPILE_GITHUB_CLIENT_SECRET |
baked in | Override the built-in GitHub OAuth client secret (development only) |
XDG base directories (XDG_CONFIG_HOME, XDG_DATA_HOME) are respected when the TOKENPILE_* overrides are not set.
On first run, an Ed25519 signing keypair is generated at ~/.config/tokenpile/identity.{key,pub} (permissions 0600/0644).
Contributing
Prerequisites
Install asdf and the plugins for Go, golangci-lint, goreleaser, and mockery:
asdf plugin add golang
asdf plugin add golangci-lint
asdf plugin add goreleaser
asdf plugin add mockery
asdf install # reads .tool-versions and installs all pinned versions
Build and test
make build # build binary to ./tokenpile
make test # run all tests with race detector
make lint # run golangci-lint
make fmt # format all Go files with gofmt
make generate # regenerate mocks (requires mockery from asdf)
make clean # remove build artifacts
CI runs fmt check, lint, and test -race on every push and pull request.
To test the GitHub auth flow locally, create your own OAuth App (GitHub → Settings → Developer settings → OAuth Apps) and set:
export TOKENPILE_GITHUB_CLIENT_ID=your_dev_client_id
export TOKENPILE_GITHUB_CLIENT_SECRET=your_dev_client_secret
These env vars override the baked-in values. Released binaries have the production credentials injected by goreleaser via ldflags — end users do not need to set anything.
Project layout
cmd/tokenpile/ CLI entry point and composition root
internal/
usage/ shared data types (Entry, Session, Report, ...)
store/ Store interface + SQLite adapter
provider/ AuthProvider, IssueProvider, Issue type, GitHub implementations
pricing/ two-layer pricing config and cost computation
export/ Ed25519-signed canonical JSON export
skill/ embedded agent skill templates
tui/ Bubble Tea TUI
config/ XDG path resolution and Ed25519 identity management
mocks/ generated mocks for unit tests
schema/ JSON Schema for the export document
Conventions
- Conventional commits:
feat:,fix:,chore:,docs:,test:,refactor:,ci: - One logical change per commit.
- No emojis anywhere.
- All dependencies injected via constructors. No globals.
context.Contextis the first parameter of every function that does I/O.- Package names describe what they contain, not architectural layers. No
domain,model, ordto. - See CLAUDE.md for the full conventions reference.
Adding a new agent skill
- Add a template file at
internal/skill/templates/<agent-name>.md. - Add the agent entry to the
agentsslice ininternal/skill/skill.gowith itsInstallPathfunction. SetShared: trueif the target file is shared with other content (e.g. AGENTS.md) — the install will append/update a marker-delimited block instead of overwriting the file. - Add tests in
internal/skill/skill_test.go.
Running a subset of tests
go test ./internal/store/... # store tests only
go test -run TestSQLiteStore ./... # filter by name
go test -race -count=1 ./... # disable test cache, enable race detector
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found