Skip to main content

tests PyPI Python License dependencies

tsave

Stop discovering costs after the fact. See where your tokens go before you run a single line.

Smetti di scoprire i costi a consuntivo. Vedi dove vanno i token prima ancora di eseguire il codice.


🇬🇧 English

I got tired of watching my Anthropic bill grow without knowing why.

So I built this: a wrapper around the official SDK that tells you — before you run your code — exactly where your tokens are going and what to do about it.

pip install tsave
tsave scan chatbot.py

No API key needed for that last command. It reads your Python file, walks the AST, and tells you what's wrong.


What it actually does

🔍 Scan your code before you run it

This is the part I'm most proud of. Point it at a .py file and it finds patterns like API calls inside loops, system prompts sent without cache_control, conversation history growing unbounded — the kind of stuff that quietly triples your bill.

Each finding comes with:

  • the line number
  • an estimate of how many tokens you're burning
  • a ready-to-paste fix

🪙 Count tokens accurately

Not with tiktoken — tiktoken undercounts Claude by 15–20%. tsave uses the official Anthropic count_tokens API, the same one that feeds the billing system.

📉 Compress long conversations

When a chat history gets long, tsave summarizes the older turns while keeping recent context intact. In practice, this cuts 65–70% of tokens on multi-turn workloads.

📊 Track what you spend

Every client.create() call gets logged. At the end of a session you can ask for a usage summary, an average cost per request, and a monthly projection.

🪝 Guard your Claude Code sessions

tsave guard is a PreToolUse hook for Claude Code — it catches waste at the session level, before the API is even involved. It intercepts Read and Bash calls and flags the two patterns that quietly bloat a session's context: reading a whole large file when you only needed a slice, and shell commands that dump unbounded output (cat with no pipe, find with no -maxdepth, git log with no limit, unscoped recursive grep, noisy package installs).

It's pure local heuristics — file-size estimation and regex, no API calls — because a hook runs synchronously on every matching tool call and can't add latency or cost of its own.

Add it to .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Bash",
        "hooks": [{ "type": "command", "command": "tsave guard" }]
      }
    ]
  }
}

Numbers

Real runs on real workloads, not synthetic benchmarks:

Scenario Before After At 1K req/day
Multi-turn chatbot (50 turns) 12,400 tokens 4,100 tokens −66.9% saves $7.47/day
RAG pipeline (full doc per call) 18,200 tokens 5,600 tokens −69.2% saves $11.34/day
Batch classifier (loop + Opus) 8,500 tokens 2,800 tokens −67.1% saves $8.55/day

Sonnet 4.6 pricing, $3/MTok input.


Usage

from tsave import TsaveClient

client = TsaveClient()

# count tokens before spending them
tc = client.count_tokens(model="claude-sonnet-4-6", messages=messages)
print(tc.format())
# 847 input tokens | est. $0.0025

# compress a long conversation
result = client.compress(model="claude-sonnet-4-6", messages=long_chat, keep_last_n=4)
print(result.format())
# Original:   1,131 tokens (13 messages)
# Compressed: 363 tokens (3 messages) — 67.9% reduction

# make the actual call — usage is tracked automatically
response = client.create(model="claude-sonnet-4-6", max_tokens=1024, messages=messages)

# see where you stand
print(client.usage_summary())
print(client.monthly_projection(requests_per_day=500).format())
# Monthly (30 days): $410.40

The CLI gives you the same things without writing any code:

tsave scan myapp.py        # static analysis, no API key
tsave analyze              # token breakdown of a conversation
tsave cost                 # cost estimate
tsave compress             # compress a conversation file

What the scanner catches

Pattern What it means
api-in-loop You're making a full API request on every loop iteration
full-file-per-call You're reading an entire file and passing it raw to the API
no-model-routing You're using Opus where Haiku would work fine
system-prompt-redefined Your system prompt gets recreated on every call
uncached-system-prompt Your system prompt is in a loop without cache_control
uncompressed-history Your message history keeps growing with no compression

Files that can't be parsed (syntax errors, unsupported encodings) are reported as "could not analyze" — never silently skipped or marked clean. The CLI exits non-zero on them. UTF-8 BOM files are handled transparently.


Development

git clone https://github.com/remo12262/token-saver.git
cd token-saver
pip install -e ".[dev]"
pytest
# 85 tests, all pass without an API key

Models & pricing

Model Input Output
Claude Opus 4.8 / 4.7 / 4.6 $5.00/MTok $25.00/MTok
Claude Sonnet 4.6 $3.00/MTok $15.00/MTok
Claude Haiku 4.5 $1.00/MTok $5.00/MTok

MIT license. Built in one evening with Claude Code.




Built in one evening with Claude Code.

🇮🇹 Italiano

Mi ero stancato di guardare la mia bolletta Anthropic crescere senza capire perché.

Così ho costruito questo: un wrapper attorno all'SDK ufficiale che ti dice — prima di eseguire il codice — esattamente dove stanno andando i tuoi token e cosa fare al riguardo.

pip install tsave
tsave scan chatbot.py

Per quest'ultimo comando non serve nessuna API key. Legge il file Python, analizza l'AST, e ti dice cosa c'è che non va.


Cosa fa concretamente

🔍 Analizza il codice prima che tu lo esegua

Questa è la parte di cui vado più fiero. Puntalo su un file .py e trova pattern come chiamate API dentro i loop, system prompt inviati senza cache_control, cronologie di conversazione che crescono senza controllo — il tipo di cose che silenziosamente triplicano la bolletta.

Ogni finding mostra:

  • il numero di riga
  • una stima dei token sprecati
  • una correzione pronta da incollare

🪙 Conta i token in modo preciso

Non con tiktoken — tiktoken sottostima Claude del 15–20%. tsave usa l'API ufficiale count_tokens di Anthropic, la stessa che alimenta il sistema di fatturazione.

📉 Comprime le conversazioni lunghe

Quando una cronologia di chat diventa lunga, tsave riassume i turni più vecchi mantenendo il contesto recente intatto. In pratica, questo taglia il 65–70% dei token sui workload multi-turno.

📊 Traccia quello che spendi

Ogni chiamata client.create() viene registrata. A fine sessione puoi richiedere un riepilogo dei consumi, il costo medio per richiesta e una proiezione mensile.

🪝 Proteggi le tue sessioni Claude Code

tsave guard è un hook PreToolUse per Claude Code — intercetta lo spreco a livello di sessione, prima ancora che l'API entri in gioco. Controlla le chiamate Read e Bash e segnala i due pattern che gonfiano silenziosamente il contesto: leggere un intero file grande quando serviva solo una porzione, e comandi shell che riversano output senza limiti (cat senza pipe, find senza -maxdepth, git log senza limite, grep ricorsivo non delimitato, installazioni di pacchetti rumorose).

È tutto euristica locale — stima della dimensione file e regex, nessuna chiamata API — perché un hook gira in modo sincrono su ogni tool call che corrisponde, e non può permettersi latenza o costo propri.

Aggiungilo a .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Bash",
        "hooks": [{ "type": "command", "command": "tsave guard" }]
      }
    ]
  }
}

I numeri

Risultati reali su workload reali, non benchmark sintetici:

Scenario Prima Dopo A 1.000 req/giorno
Chatbot multi-turno (50 turni) 12.400 token 4.100 token −66,9% risparmia $7,47/giorno
Pipeline RAG (doc completo per chiamata) 18.200 token 5.600 token −69,2% risparmia $11,34/giorno
Classificatore batch (loop + Opus) 8.500 token 2.800 token −67,1% risparmia $8,55/giorno

Prezzi Sonnet 4.6, $3/MTok in input.


Utilizzo

from tsave import TsaveClient

client = TsaveClient()

# conta i token prima di spenderli
tc = client.count_tokens(model="claude-sonnet-4-6", messages=messages)
print(tc.format())
# 847 input tokens | est. $0.0025

# comprimi una conversazione lunga
result = client.compress(model="claude-sonnet-4-6", messages=long_chat, keep_last_n=4)
print(result.format())
# Originale:   1.131 token (13 messaggi)
# Compresso:   363 token (3 messaggi) — riduzione del 67,9%

# fai la vera chiamata — l'utilizzo viene tracciato automaticamente
response = client.create(model="claude-sonnet-4-6", max_tokens=1024, messages=messages)

# vedi dove sei
print(client.usage_summary())
print(client.monthly_projection(requests_per_day=500).format())
# Mensile (30 giorni): $410.40

La CLI ti dà le stesse cose senza scrivere codice:

tsave scan myapp.py        # analisi statica, senza API key
tsave analyze              # breakdown dei token di una conversazione
tsave cost                 # stima dei costi
tsave compress             # comprimi un file di conversazione

Cosa rileva lo scanner

Pattern Cosa significa
api-in-loop Stai facendo una richiesta API completa a ogni iterazione del loop
full-file-per-call Stai leggendo un file intero e passandolo grezzo all'API
no-model-routing Stai usando Opus dove basterebbe Haiku
system-prompt-redefined Il tuo system prompt viene ricreato a ogni chiamata
uncached-system-prompt Il tuo system prompt è in un loop senza cache_control
uncompressed-history La cronologia dei messaggi continua a crescere senza compressione

I file non analizzabili (errori di sintassi, encoding non supportati) vengono segnalati come "could not analyze" — mai saltati in silenzio o dati per puliti. La CLI esce con codice ≠ 0 su questi file. I file con BOM UTF-8 sono gestiti in modo trasparente.


Sviluppo

git clone https://github.com/remo12262/token-saver.git
cd token-saver
pip install -e ".[dev]"
pytest
# 85 test, tutti passano senza API key

Modelli e prezzi

Modello Input Output
Claude Opus 4.8 / 4.7 / 4.6 $5,00/MTok $25,00/MTok
Claude Sonnet 4.6 $3,00/MTok $15,00/MTok
Claude Haiku 4.5 $1,00/MTok $5,00/MTok

---

📣 Share / Condividi

LinkedIn Twitter/X Facebook

Licenza MIT. Costruito in una serata con Claude Code.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tsave-0.3.0.tar.gz (32.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tsave-0.3.0-py3-none-any.whl (23.0 kB view details)

Uploaded Python 3

File details

Details for the file tsave-0.3.0.tar.gz.

File metadata

  • Download URL: tsave-0.3.0.tar.gz
  • Upload date:
  • Size: 32.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tsave-0.3.0.tar.gz
Algorithm Hash digest
SHA256 b85707e9d8b9f4cab7eaf5ec9c04498f397e123b997d7ce3bd5329d90cd41ddf
MD5 c38509b33e1b73b957c7719607f3d3ac
BLAKE2b-256 c9db338a00b3e5a2279054056edcfeeaf879eb196b686245e056283472361e1b

See more details on using hashes here.

Provenance

The following attestation bundles were made for tsave-0.3.0.tar.gz:

Publisher: publish.yml on remo12262/token-saver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tsave-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: tsave-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 23.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tsave-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1307a67f4878476218fa81f626b3e9c1bc9674d0ca225c5dd9a1b6c180259998
MD5 15157822306c95e1a831d129559df5c1
BLAKE2b-256 5d28001f0cfb311fef57be492ccd939df5e3dd2764fe46cff39800893d0d5afe

See more details on using hashes here.

Provenance

The following attestation bundles were made for tsave-0.3.0-py3-none-any.whl:

Publisher: publish.yml on remo12262/token-saver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page