Token estimation

The token counter on the result screen tells you how much of your model's context window the current output will consume. It updates live as files come and go.

How the count is produced

Token counting runs against @dqbd/tiktoken, a WebAssembly build of OpenAI's tokenizer. The default encoding is the one used by o1-preview-2024-09-12, which most modern LLM models match closely enough to be useful as a unified estimate.

What gets counted is the whole assembled output, the same string the preview shows and the copy button copies: the XML root or Markdown headings, the per-file tags, the header and the file tree, not just the text of your files. Those wrappers are charged for like everything else. Measured across 60 public repositories on 2026-09-07 they are a median 2.4% of the bundle, and 17.8% on a repository of many small files.

The encoder runs synchronously after the page boots, so toggling files on and off does not introduce a perceptible delay for typical projects.

Above 1 MB the count is sampled

Running the WASM encoder over a multi-megabyte bundle blocks the main thread long enough to feel like the tab has frozen. So above 1 MiB of text the count is extrapolated instead of taken: 64 evenly spaced 4 KiB slices are tokenized for real, and the total is scaled by the ratio those slices show. The cost is a flat 256 KiB of tokenizing whatever the bundle's size. The constants live in apps/web/src/lib/tokens-client.ts and the threshold in apps/web/src/lib/tokens.ts.

Before 2026-09-07 this path was Math.ceil(length / 4), an English-prose ratio applied to every language. On the 30 repositories of that 60 repository sample that crossed the threshold it ran a median 13.5% off and 62.5% off on a repository written in Chinese. Sampling brings the same 30 to a median 0.8% off and 4.5% at worst, all of them within 5% of the true count.

Math.ceil(length / 4) survives in one place only: the fallback when the encoder itself fails to load.

If you want an exact count rather than a sampled one, narrow the output with the filter patterns until the bundle is under 1 MiB.

Model selector

The model selector lives in the Adjust what's included drawer, next to the cost estimate. The catalog ships with the build and is refreshed at every deploy from models.dev, the same source the cost estimates use.

A few facts that make the picker behave the way it does:

  • Models are sorted by release date descending, so the newest Claude, GPT, Gemini, and so on appear at the top.
  • The picker shows the canonical model (e.g. claude-sonnet-4-6) and a via {provider} hint for the cheapest priced provider that offers that model on the day of the deploy. If the cheapest provider changes between deploys, the hint changes; the canonical id stays the same so your selection survives.
  • The selected model's identifier is the catalog UID (lab/model-id), persisted in localStorage. Models removed from the catalog upstream are pruned at load time.

See also

  • Token costs for which toggles cost or save tokens.
  • Filter precedence for the layered filtering pipeline that decides which files contribute to the count.
  • How many tokens is a codebase? for the 60 repository measurement the figures above come from, and what a whole repository costs to send.
  • Context window costs for what filling 100K, 500K or 1M tokens costs across every model in the catalogue.