Skip to main content
Glama

tokenzip

bytes per image

Vision models count image tokens by tiles, not megapixels. A 3000×2000 screenshot costs Claude exactly the same 1568 tokens whether you upload 6 megapixels or the 1328×885 it internally resizes to. tokenzip computes that exact size per provider and re-encodes the image: same tokens, same detail the model ever sees, far fewer bytes uploaded.

$ tokenzip screenshot.png --provider anthropic

screenshot.png — 3000×2000 (Claude (Anthropic))
  billed tokens : 1568 ≈ $0.0047/image
  model sees    : 1328×885
  pixels to send: 19.6% (80% fewer bytes)
  note          : send 1328×885: identical tokens & detail, 80% fewer bytes

Install / run

npm install @asynx6/tokenzip          # CLI: npx @asynx6/tokenzip, lib: require('@asynx6/tokenzip')
npm install -g @asynx6/tokenzip       # global `tokenzip` command
# or no install at all (zero deps): clone + `node tokenzip.js ...`

Note: use the scoped name @asynx6/tokenzip. The bare name tokenzip on npm belongs to a different publisher — npx tokenzip downloads their placeholder package, not this one.

Related MCP server: latent-gate

Hook it into your AI tools

Claude Code — never burn 1568 tokens on a bloated Read again. The hook intercepts image Reads, rewrites oversized files into a tokenzip cache, and Claude sees the resized copy:

claude --settings '{"hooks":{"PreToolUse":[{"matcher":"Read","hooks":[{"type":"command","command":"npx -y @asynx6/tokenzip hook claude-code"}]}]}}'

Or add the same block permanently to .claude/settings.json. PNG and baseline JPEG inputs only; anything weird passes through untouched.

Claude Desktop / OpenCode / Cursor / anything that speaks MCP:

{ "mcpServers": { "tokenzip": { "command": "npx", "args": ["-y", "@asynx6/tokenzip", "mcp"] } } }

OpenCode uses the same JSON under mcp in its config (type: "local"). Tools exposed: tokenzip_estimate, tokenzip_optimize (writes a file and tells you exact token/byte deltas), tokenzip_batch_dir.

As a library:

import { PROVIDERS, anthropicTokens } from '@asynx6/tokenzip';
import { optimize } from '@asynx6/tokenzip/optimize';

anthropicTokens(3000, 2000);              // 1568 — what one shot costs
const plan = optimize('anthropic', 3000, 2000);
// plan.best = { w: 1328, h: 885, tokens: 1568 }  — resize to this, bill unchanged

CLI, hook, MCP, and library share the same tested formulas — no drift between "what the tool says" and "what your code does".

What it does

  • Per-provider token math for Claude, GPT-4o+, and Gemini — the resize + tile formulas from each provider's own docs, pinned with tests (512²→255 tokens, 768²→787, 2×768→258, etc.). Formula sources and dates are recorded in FORMULAS.md.

  • Exact mode: shrink to the size the provider's own pipeline ends up at. Token bill unchanged, upload bytes slashed (matters for latency, egress fees, mobile, batch agents that resend images every turn).

  • Budget mode (--max-tokens 300): binary-searches the largest resize that fits your cap, and tells you how many tokens it saves per image.

  • Re-encode (--out): writes the optimized image. PNG (built-in zero-dep encoder, 8-bit) and JPEG (baseline DCT encode; decode accepts baseline JPEG input) — no external binaries.

  • Folder mode (--dir ./shots): per-image analysis across a directory.

Why this saves anything

The money saving is a myth worth killing honestly: tiles are billed on the provider's post-resize dimensions, so resizing first costs you zero tokens saved on a single image. What you actually save:

  1. Upload bandwidth and time — a screenshot batch of 500 images at 80% fewer bytes is a real bill on egress-priced storage and a real wall-clock cut for agents.

  2. Budget mode is where money moves: an agent that sends 1105-token tiles per screenshot but only needs layout understanding can cap at 300 and cut its vision bill ~70%, with the tool finding the sharpest image that fits.

  3. Knowing the floor: images under ~768px are one tile on every provider — making screenshots small is the optimization, and tokenzip shows the exact per-provider breakpoints.

Benchmarks

node bench.mjs regenerates this table in-memory (reproducible, no network, no fixtures):

input (JPEG q85)

size

Anthropic tok

exact→ bytes

budget 300 tok→

screenshot-like

3000×2000

1568

1328×885 · 436 KB → 181 KB (−58%)

512×341 · 34 KB (−805 tok)

chat UI

1280×800

1366

already optimal · 19 KB → 19 KB

512×320 (−1105 tok)

phone shot

1080×2400

1568

727×1616 · 306 KB → 243 KB (−21%)

230×512 (−1190 tok)

The chat-UI row is the honest counter-example: an image already near the provider floor gains nothing — and tokenzip tells you that instead of shrinking something pointlessly.

Limitations (read before trusting)

  • JPEG: baseline encode/decode (4:4:4 + 4:2:0, quality knob). Progressive and lossless JPEG inputs throw a clear error instead of guessing. WebP has no codec in v0.x — convert or help us build it.

  • 8-bit PNGs, non-interlaced.

  • Token formulas match provider docs as of 2026-09; they have changed before. FORMULAS.md pins sources, dates, and the update procedure; test-tokens.js fails loudly when docs and code diverge.

  • Cost figures are order-of-magnitude list-price estimates. Your rate plan differs.

  • Budget mode optimizes pixels-per-token, not task quality. Only you know whether 300 tokens still reads your chart. Check the resized output.

Tests

node test-tokens.js   # 12 provider-math cases against documented examples
node test-png.js      # codec roundtrips, palette, resize, optimize invariants
node test-jpeg.js     # JPEG encode→decode roundtrip vs own decoder + System.Drawing check
node bench.mjs        # regenerates the README benchmark table

Contributing

Start with CONTRIBUTING.md — it explains the codec architecture in one page.

License

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      B
      maintenance
      Shrinks logs, JSON, docs and web pages before your AI reads them: offline, deterministic, no API key. Folds repetitive log lines (12,037 to 127 tokens on a 400-line log) while code, URLs and quoted strings come back byte-for-byte. Also fetches URLs as clean text, counts tokens exactly, and has optional local Ollama tools for image and text compression.
      72 PyPI
      25
      -
    • A
      license
      Not graded
      quality
      A
      maintenance
      Enables AI coding clients that lack native vision to analyze screenshots of code, errors, UIs, and documents by routing images through a single image_understand tool backed by multiple vision LLM providers such as GLM-4.6V, DeepSeek-OCR, Qwen3-VL-Flash, Doubao-Seed, and Hunyuan-Vision. Handles local files, remote URLs, and Data URIs with automatic multi-crop, compression, retry, and OCR-friendly preprocessing, and can be deployed over stdio or shared HTTP/Docker for multiple clients.
      664 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Adds image understanding to AI coding clients that lack native vision, letting them analyze screenshots, error messages, UI layouts, and documents through a single unified tool. Routes requests across multiple vision LLM providers with automatic preprocessing, multi-crop handling for large or text-dense images, and retry logic.
      664 npm
      MIT