Catch LLM cost anti-patterns in your Python AI app before they hit prod — a local, static token-cost linter.
Project description
TokenLint
Your LLM bill is bleeding and you don't know which line of code is doing it. TokenLint scans your Python AI app locally and statically (it never runs your code or sends it anywhere) and flags the patterns that quietly inflate token costs — premium models on trivial steps, missing output caps, un-cached static prompts, and unbounded agent loops that burn tokens unpredictably — before they hit production.
Runs in your editor, your terminal, or CI. Zero dependencies, zero network calls.
pipx install tokenlint # or: pip install tokenlint
tokenlint . # scan your project
TokenLint — LLM cost pre-flight
app/agent.py
FAIL R004-unbounded-agent-loop line 30
LLM call inside a `while True` with no break — token runaway risk.
→ Add an explicit max-steps budget and a token/cost ceiling.
~$0.0050/call (gpt-4o)
WARN R001-expensive-model line 19
Call uses 'claude-opus-4', a premium-priced model.
→ If this step is simple, route it to claude-sonnet/haiku.
~$0.0377/call
1 fail 7 warn 0 info
What it catches today (v0.1, free, MIT)
| Rule | What it flags |
|---|---|
R001-expensive-model |
Premium model (Opus / GPT-4o / o1…) on a step that a cheaper model could do |
R002-no-max-tokens |
No output cap — one runaway completion can 10× a call's cost |
R003-no-prompt-cache |
Large static Anthropic system/context with no cache_control (often ~90% of input spend is cacheable) |
R004-unbounded-agent-loop |
LLM call inside while True with no break — the #1 way agents quietly burn money |
R004-llm-call-in-loop |
LLM call in a loop — cost scales with iterations; needs a budget |
R005-large-inline-prompt |
Oversized inline prompt literal sitting in the hot path |
Works with the Anthropic and OpenAI SDKs and raw call patterns. LangChain / LlamaIndex detection is on the roadmap.
CI usage
tokenlint . --fail-on warn # exit non-zero on warnings too, to block a costly merge
Use it inside Claude Code (plugin)
TokenLint ships as a Claude Code plugin: a /tokenlint:cost-preflight skill that
scans your project and offers fixes, plus a non-blocking hook that flags an
unbounded agent loop the moment you write one.
# from the repo (once it's on GitHub)
/plugin marketplace add zlyan1110/tokenlint
/plugin install tokenlint@tokenlint
# or try it locally without installing
claude --plugin-dir ./tokenlint
Then in a session:
/tokenlint:cost-preflight # scan the whole project
/tokenlint:cost-preflight app/ # scan a path
The skill auto-loads when you're working in .py files and will offer to apply
fixes (caps, prompt caching, model routing, agent budgets) with your approval.
TokenLint Pro
The free linter tells you where you're leaking. Pro fixes it for you:
- Auto-fix diffs — PR-ready patches that add caps, prompt caching, and budgets
- Model-routing config generator — send cheap steps to cheap models automatically
- Agent token-budget guard — a drop-in wrapper that hard-stops runaway loops
- Self-host break-even calculator + vLLM/TGI deploy configs — when does running your own inference beat the API, and how to configure it
Pro is in development — not yet for sale. ⭐ Star the repo to be notified when it lands. (Planned: ~$39 one-time or $19/mo for the always-current ruleset.)
Why local + static?
Observability platforms (Helicone, Langfuse, …) show you cost after traffic runs through them. TokenLint catches it before you ship — in the same loop where you write the code (including inside Claude Code / Cursor). The two are complementary; this one is free and runs offline.
License
MIT for the core linter. Pricing table in tokenlint/pricing.py is editable — verify against current provider pricing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tokenlint-0.1.1.tar.gz.
File metadata
- Download URL: tokenlint-0.1.1.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5ee2c5767e621b2fa37032e55f393789d2cc1b27a10a79857ec618d9fff664f
|
|
| MD5 |
278c0183ab24bd0fe04bccf1357a8a5f
|
|
| BLAKE2b-256 |
68fe7e50e126dc07b4ac5437592aa9786ffedda73d18f504680d648b491daaf6
|
Provenance
The following attestation bundles were made for tokenlint-0.1.1.tar.gz:
Publisher:
publish.yml on zlyan1110/tokenlint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tokenlint-0.1.1.tar.gz -
Subject digest:
c5ee2c5767e621b2fa37032e55f393789d2cc1b27a10a79857ec618d9fff664f - Sigstore transparency entry: 1707496701
- Sigstore integration time:
-
Permalink:
zlyan1110/tokenlint@0a5109a4dec6efb66b88a3af05fcc1fc3ff5907f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/zlyan1110
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0a5109a4dec6efb66b88a3af05fcc1fc3ff5907f -
Trigger Event:
push
-
Statement type:
File details
Details for the file tokenlint-0.1.1-py3-none-any.whl.
File metadata
- Download URL: tokenlint-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63a4bf4250f20157d5fcfbe063a274696d63254da4b3780a9ccc9978c26ecee6
|
|
| MD5 |
5e8c21d6331caa4e68abff9410fcd2db
|
|
| BLAKE2b-256 |
c57c4267984411b7322062e8243b641c9114c929a1ac7e98f79d7b23028f4034
|
Provenance
The following attestation bundles were made for tokenlint-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on zlyan1110/tokenlint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tokenlint-0.1.1-py3-none-any.whl -
Subject digest:
63a4bf4250f20157d5fcfbe063a274696d63254da4b3780a9ccc9978c26ecee6 - Sigstore transparency entry: 1707496718
- Sigstore integration time:
-
Permalink:
zlyan1110/tokenlint@0a5109a4dec6efb66b88a3af05fcc1fc3ff5907f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/zlyan1110
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0a5109a4dec6efb66b88a3af05fcc1fc3ff5907f -
Trigger Event:
push
-
Statement type: