Browse documentation

Portable .tine files default to v5 (since 0.42). --for-legacy writes v4. The .tine/ repository format is v3. tine evidence export writes v4. Formats and protocols.

Docs target stable release v0.44.0.Stable vs main checked 2026-11-07

Reference · v0.44.0

Pricing

From the pinned CLI source. Read upstream.

Pricing and usage accounting

OpenTine records normalized consumption and estimates cost from a pinned, effective-dated catalog. A provider response is not a final invoice: taxes, credits, enterprise commitments, regional adjustments, rounding, and provider post-processing may differ.

Public records

Usage has exclusive input, output, cache_read, cache_write_5m, cache_write_1h, and reasoning dimensions, an optional provider total, and typed provider-specific extra dimensions. Exclusive buckets prevent cached or reasoning tokens from being charged twice.

BillingResult reports one of complete, partial, unknown, or unmetered, along with amount_usd, known_subtotal_usd, warnings, the calculation inputs, catalog provenance, the applicable rate-card ID, and its effective date.

RateCard identifies one provider/model (plus aliases), effective range, per-million-token rates, context thresholds, service modifiers or exact service-specific rates, currency, source URLs, and verification date. PricingCatalog performs deterministic provider + model + date resolution.

All arithmetic uses Decimal. The legacy numeric response field cost remains the known USD subtotal for compatibility. For incomplete billing, cost can be non-zero while billing.amount_usd is null.

Resolution and lifecycle

Resolution order is:

  1. an explicit adapter/run rates= override, when the model check below allows it;
  2. an explicitly selected catalog or TINE_PRICING_CATALOG;
  3. workspace .tine/pricing.json, when signed or opted in with OPENTINE_TRUST_WORKSPACE_PRICING=1;
  4. user $XDG_CONFIG_HOME/opentine/pricing.json (a signed one only if no older than the bundled snapshot);
  5. the bundled signed snapshot;
  6. an unknown result—never another provider's price.

A rates= override wins only when the model the provider reports resolves to the same rate card as the model that was requested. If the provider echoes a different model identifier, the override is discarded, the catalog card for the reported model is used instead, and two warnings are appended: provider reported model 'X' for requested model 'Y' and explicit rates were ignored for the different model. When the catalog prices the reported model the status stays complete, so a caller who encoded a negotiated rate is billed the list price and learns of it only from billing.warnings—check them before trusting amount_usd. When the catalog does not price it, the result is unknown; the override is not reinstated either way. Equivalence is decided by resolved rate-card ID, so a catalog alias, or Ollama's conventional :latest tag, still counts as the same model. An unmetered adapter keeps its override unconditionally.

Supplying base_url= to OpenAI, or setting OPENAI_BASE_URL, selects the provider identity openai-compatible by default. Even if that endpoint exposes a model named gpt-4o, OpenTine will report unknown pricing unless the caller explicitly selects a provider or supplies a rates= override.

Later local layers win while effective dates remain deterministic. A local catalog must have its own matching catalog_id hash; it may be unsigned so an enterprise can express negotiated discounts or infrastructure costs without altering the signed upstream snapshot.

Time-of-day pricing (peak / off-peak)

opentine-pricing/2 adds one optional field to a rate card, schedule: an ordered list of windows, each naming the UTC hour ranges it covers, the days it covers (all, weekday, or weekend), and the rates that replace the card's base rates inside it. The first window covering a billing moment wins, ranges are half-open (01:00–04:00 excludes 04:00), and a range whose start is later than its end wraps past midnight. A window's rates override only the dimensions they name.

"rates": {"input": "0.66", "cache_read": "0.022", "output": "1.98"},
"schedule": [
  {
    "id": "peak",
    "days": "weekday",
    "hours": [{"start": "01:00", "end": "04:00"}, {"start": "06:00", "end": "10:00"}],
    "rates": {"input": "1.32", "cache_read": "0.044", "output": "3.96"}
  }
]

The base rates are therefore the out-of-window price — for DeepSeek, the off-peak one. Two defaults follow, and both are deliberate:

  • A card with no schedule prices from rates at every hour, which is what every opentine-pricing/1 card already meant. The field is additive by absence; no existing price moves.
  • A scheduled card priced from a date with no time of day also prices from base rates. A day is not an instant, so there is no moment to place in a window.

The billing moment splits in two: its date selects the rate card (effective_from/effective_until), its time of day selects the window. bill() and calculate() accept a datetime for effective_at, and native capture passes the capture instant. tine price --at DATE pins the card-selection date for the whole run — "what would this run cost under the cards effective on DATE" — while each step's window still comes from that step's own recorded timestamp, so a run spanning peak and off-peak is priced at both rates rather than at one. Without --at, a step is carded on the day it was recorded, falling back to today when a record carries no timestamp.

Both schemas load: the loader accepts opentine-pricing/1 and opentine-pricing/2, and an unsigned /1 overlay still layers over the bundled /2 snapshot.

Streamed calls and reported usage

Every price on this page is applied to usage the provider reports. An OpenAI-compatible endpoint sends no usage chunk during a stream unless the request carries stream_options={"include_usage": True}, so a rate card alone is not enough to price a streamed call.

OpenTine adds that field by default for the providers openai, openai-compatible, qwen, xai, glm, and glm-cn, and the Kimi, DeepSeek, Groq, and OpenRouter adapters request it for themselves. The list is an allowlist rather than a default because the field is not universally accepted: Mistral answers it with HTTP 422 extra_forbidden, which fails the whole call rather than losing a number. Together, Mistral, Ministral, and Hermes therefore send nothing, as do OpenAICompatible and the local presets that leave default_include_usage at False.

A streamed call to one of those adapters reports no usage at all, so the result is status: "unknown", amount_usd: null, cost: 0.0, and the warning provider did not report usage; cost is unknown—even though this document advertises rate cards for Together, Mistral, and Ministral. On an unmetered adapter the status stays unmetered and the warning reads provider did not report usage; API cost remains unmetered; the token counts are lost either way. Non-streamed complete() calls are unaffected.

Pass include_usage=True to the adapter if your deployment does accept the field, and confirm on a short streamed call that billing.status is not unknown before relying on streamed cost. LocalAI and KoboldCpp request it by default (both honour it). A Chat Completions stream emits one usage event, the last, so a server that repeats cumulative usage on every chunk (vLLM --enable-force-include-usage, continuous_usage_stats) cannot be counted twice.

Re-pricing a recorded run (tine price)

tine price re-derives cost from what the run recorded. It prices every step the capture itself billed as a model call — a model step, and also the done step a tine run --model … --prompt run ends on, a think step beside tool calls, or a refusal recorded as error — when the step carries usage, a provider and a billing calculation; a harness's closing step carries no usage and is not counted twice. The service tier recorded at capture (billing.calculation.service_tier, or a harness step's service_tier) is applied, so a Claude fast-mode call re-prices at its 2x modifier and a Priority, Flex or US-geo call at its own. A call captured from a local provider (Ollama, LM Studio, vLLM, local-anthropic-compatible, any local preset) re-prices as unmetered, exactly as it was recorded — but only when the model carries no :cloud / -cloud tag and the record carries positive evidence (the capture's own unmetered verdict, or no billing inside a run the harness wrapper captured: a billing-less step in any other run, such as one imported by 0.9.x or through Recorder.import_events, prices unknown); an imported trace or session log is never booked unmetered from its provider label (an imported model call carries an explicit unknown record, every billing block the source carried is dropped whatever its status, and a billing block with a missing or unreadable status never counts as "no verdict"), so an imported local run prices unknown. An imported step never keeps the source file's own cost either: the figure moves to the opentine.source_reported_cost attribute and the step's cost comes from the catalog (--price, or tine price later). Ollama Cloud calls are ollama-cloud and re-price unknown until a card covers them. A run captured with explicit Ollama compute or token rates re-prices as unmetered, because those override rates are not part of the record.

Service tiers

A card's service_modifiers scale every dimension for a named tier. Tiers the adapters and harnesses report: regional (OpenAI's regional-processing domains for models released on or after 2026-03-05; Bedrock regional endpoints and geographic inference-profile prefixes us. / eu. / jp. / au. / apac.; Vertex multi-region and regional endpoints), us / eu (Anthropic inference_geo, Foundry data zones, Fireworks' US host at 1.5x), fast / fast_us, priority / priority_us / priority_eu, flex, batch / batch_regional (on an OpenAI data-residency host a Priority or Flex call bills priority_regional / flex_regional), and offpeak (Gemini's ON_DEMAND_OFFPEAK traffic type, priced only where carded). A tier no card carries is reported unknown, never priced at the standard rate.

Provider-reported cost

OpenRouter's usage.cost and xAI's cost_in_usd_ticks were already read as the provider's own figure; DeepInfra's usage.estimated_cost now is too. A Bedrock model id's routing prefix (global., us., eu., …) and openai. are stripped before card lookup: global. prices at list, a geographic prefix at the regional tier. Hosted vendors without a card (DeepInfra, Cerebras, SambaNova, Upstage, Inception, NVIDIA, Hugging Face, Vercel, Cohere) record unknown, never a guessed price.

Models newer than the bundled snapshot

The bundled snapshot is signed, so it can only gain cards when the release key re-signs it — editing the file in place fails verification with catalog id/hash mismatch and takes billing down with it. Until the next signed release, price a newly launched model with an unsigned overlay.

The repository carries a ready-made three-card overlay at docs/pricing-overlay-claude-5.json, covering claude-opus-5, claude-mythos-5 (Project Glasswing), and claude-haiku-4-5. It is present in a source checkout and in the source distribution, but the wheel contains only the opentine package, so pip install opentine does not put that file anywhere on disk. A single-card overlay is reproduced here so the recipe works either way; it carries that file's claude-opus-5 rates without its fast service modifier or its metadata:

mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/opentine"
cat > "${XDG_CONFIG_HOME:-$HOME/.config}/opentine/pricing.json" <<'JSON'
{
  "schema": "opentine-pricing/1",
  "generated_at": "2026-07-25T00:00:00Z",
  "cards": [
    {
      "id": "anthropic:claude-opus-5:2026-06-24",
      "provider": "anthropic",
      "model": "claude-opus-5",
      "effective_from": "2026-06-24",
      "rates": {
        "input": "5",
        "output": "25",
        "reasoning": "25",
        "cache_read": "0.50",
        "cache_write_5m": "6.25",
        "cache_write_1h": "10"
      },
      "service_modifiers": {
        "batch": "0.5",
        "batch_us": "0.55",
        "us": "1.1"
      },
      "source_urls": [
        "https://platform.claude.com/docs/en/about-claude/pricing"
      ],
      "verified_at": "2026-07-25"
    }
  ],
  "catalog_id": "sha256:affafa21b064e5f30592383bbc2cad164d6ce38c2d1dd8eb7df6e06511b7341a"
}
JSON
tine pricing show anthropic claude-opus-5

A workspace overlay at .tine/pricing.json takes the same content and outranks the user one — but only when you opt in. It comes from the current directory, so a cloned checkout can ship one, and an unsigned overlay could price any model at $0 and disarm every max_cost budget. From 0.9.2 it is ignored (with a note on stderr) unless it is validly signed by a trusted key or OPENTINE_TRUST_WORKSPACE_PRICING=1 is set (1/true/yes/on). A signed overlay older than the newest signed catalog already in use (bundled or installed) is skipped with a notice too: every release catalog ever shipped still verifies under the release key, so an old one checked into a project would otherwise roll prices back. Two different catalogs signed with the same generated_at cannot replace each other, at load or at tine pricing install. A rate card's currency must be an ISO 4217 code (USD, three capitals).

An overlay carries its own catalog_id, so recompute it after any edit. The stored value is the sha256:-prefixed digest, not the bare hex that catalog_hash() returns — storing the bare hex fails every load with catalog id/hash mismatch, which takes all billing down rather than just the overlay:

from opentine.billing.catalog import catalog_hash
data.pop("catalog_id", None)
data["catalog_id"] = f"sha256:{catalog_hash(data)}"   # note the prefix

Note that a merged catalog reports signed=false once any layer is unsigned; the bundled layer's own signature is still verified and enforced on load.

Prices are never downloaded during inference. Catalog updates are explicit and must verify their Ed25519 signature before installation, and a catalog older (generated_at) than the bundled snapshot or the one it would replace is refused, so an update can never roll prices back. A signed user catalog older than the bundled one (say, left over from before an upgrade) is skipped at load:

tine pricing list
tine pricing show anthropic claude-sonnet-5 --at 2026-08-31
tine pricing check /path/to/catalog.json
tine pricing update https://trusted.example/pricing.json

The digest-covered run manifest pins the resolved catalog ID/hash, each underlying layer's ID/hash/signature metadata, the selected rate card, effective date, normalized usage, rates, context rule, currency conversion, and service modifier. Signed catalogs can therefore update independently of package releases without making an old run depend on today's catalog.

Frontier snapshot

The bundled snapshot generated on 2026-07-20 includes these required frontier cards (USD per million tokens):

FamilyInputCache readOutputOther rules
GPT-6 Astra10.001.0050.00cache writes 12.50; >272K input multipliers (whole request); batch/flex 0.5x; fast 2x
GPT-5.6 Sol (gpt-5.6)5.000.5030.00cache writes; >272K input multipliers; batch/flex/priority
GPT-5.6 Terra2.500.2515.00same dimensions and threshold rules
GPT-5.6 Luna1.000.106.00same dimensions and threshold rules
Claude Fable 5.110.000.2550.005m write 12.50; 1h write 20.00; US inference 1.1x; no fast mode
Claude Fable 510.001.0050.005m write 12.50; 1h write 20.00; US inference 1.1x
Claude Opus 4.5–4.85.000.5025.00exact model IDs; 5m write 6.25; 1h write 10.00; 4.6+ US inference 1.1x
Claude Sonnet 52.000.2010.00launch price, now standard; US inference 1.1x

Claude Sonnet 5's scheduled 2026-09-01 rise to $3/$15 was cancelled by Anthropic and never entered the catalog; the $2/$10 card runs from 2026-06-30 with no end.

Claude Fable 5.1 and Claude Mythos 5.1 are the only models whose cache hits cost 0.025x base input rather than the family-wide 0.1x. Every card states cache_read outright and nothing derives it from input, so the published $0.25/MTok is what bills; no family rule can override it. Fable 5.1 has no fast mode (that tier covers Claude Opus 5 and Opus 4.8), so no fast modifier is carded and a fast-tier request stays visibly unknown.

GPT-6 Astra's >272K threshold is request-scoped upstream — "priced at 2x input and cache rates and 1.5x output for the full request" — and context_thresholds are applied the same way: crossing the line replaces the base rates for every dimension of the whole call, not just for the tokens above it. No priority-tier price is published for Astra, so that tier is left uncarded rather than guessed.

The catalog also contains provider-scoped cards for current defaults and frontier families from Kimi, DeepSeek, Google Gemini, Grok/xAI, GLM/Z.AI, Qwen, Groq, Together, Mistral/Ministral, Meta (Muse), MiniMax, StepFun, Xiaomi MiMo and Fireworks, and cloud namespaces bedrock (global endpoints at first-party list, regional 1.1x), vertex (Claude; regional and multi-region 1.1x) and foundry (Claude at Anthropic's rates with the US Data Zone at 1.1x; Azure OpenAI GPT-6 with Data Zone US 1.1x and EU 1.2x). The 0.11.0 snapshot holds 224 signed cards, verified 2026-10-15. Use tine pricing list for the exact effective records rather than copying rates into code. Direct Nous/Hermes rates are dynamic in the upstream service, so that card is intentionally unknown until a local overlay supplies a price.

The current snapshot includes Kimi K3 ($3 input, $0.30 cache hit, and $15 output per MTok), Gemini 3.5 Flash, GLM-5.2, DeepSeek V4 Pro/Flash, and the current DeepSeek deepseek-chat/deepseek-reasoner aliases. Gemini audio and cached-audio tokens remain separate dimensions, and exact Batch/Flex/Priority rates are pinned where a scalar modifier would be wrong. Grok 4.5 and 4.3 apply xAI's higher rate to every token dimension once total prompt input exceeds 200K. Alibaba's proprietary qwen-plus is intentionally not aliased to the distinct qwen3.6-27b card; it remains visibly unpriced until its region-, context-, and thinking-mode-dependent rates are represented. Qwen3.7-Max's pay-as-you-go promotion is effective-dated through 2026-07-23; explicit 5-minute cache writes/hits and automatic implicit-cache hits retain their distinct provider rates. Qwen3.8-Max, Qwen3.8-27B, and Qwen3.8-Flash carry the same two-tier cache shape: the base cache_read is the automatic implicit hit and the explicit_cache service tier carries the explicit hit rate (equal to the implicit rate on Qwen3.8-Flash, which the vendor prices identically). Alibaba publishes no availability date for the Qwen3.8-27B and Qwen3.8-Flash hosted prices, so those cards begin on the day the price was confirmed rather than being backdated over an unsourced window.

qwen3.8-flash-next is deliberately held — not carded and not aliased. qwencloud.com/models/qwen3.8-flash-next returns HTTP 404 and the model is open-weight only; the hosted, priced model is the distinct qwen3.8-flash ("Qwen3.8-Flash is the official version based on Qwen3.8-Flash-Next with more production features"). Aliasing the two would attach a hosted price to a model that has none, so a qwen3.8-flash-next run reports cost unknown until a local overlay supplies a price. The direct GLM adapter prices the Z.AI global endpoint; a China-region key uses provider identity glm-cn and remains visibly unpriced unless a regional local overlay is supplied. That miss now carries a warning naming the endpoint and the overlay remedy, so it reads as a deliberate hold rather than a stale catalog; the status stays unknown and no amount is invented, so completeness gates are unaffected. Supplying an overlay or an explicit rate override silences it.

Anthropic's adapter sends an explicit inference_geo when configured and uses the geography reported in response usage for billing. US-only inference on supported current models applies the documented 1.1x multiplier across input, output, cache writes, and cache reads; it composes with the Batch discount. GPT-4o's May launch, August price cut, and October prompt-cache discount are separate effective records, so historical runs do not receive backdated rates. Mistral records use the provider's API IDs (mistral-large-2512, mistral-small-2603, mistral-medium-3-5, and ministral-14b-2512) while the documented *-latest names remain aliases. Kimi Batch requests use the provider's exact per-dimension rates rather than a rounded scalar discount. Groq Flex/on-demand tiers retain their documented real-time prices, Llama Batch receives its 50% discount, and public-tier model shutdown dates are recorded as lifecycle metadata. Cards remain priceable for enterprise committed-spend customers, whom Groq explicitly exempts.

Release maintainers sign snapshots with python -m scripts.sign_pricing_catalog ... --key /secure/private.pem --key-id .... Private release keys must remain outside the source tree; old public keys stay trusted after a public release unless they are explicitly revoked. The r3 key is the first public OpenTine catalog trust anchor; unpublished pre-release keys were retired before v0.3.0 because durable private-key custody could not be demonstrated.

Primary rate sources are linked on every card, including the OpenAI model catalog, Anthropic pricing, Kimi models and pricing, DeepSeek pricing, Gemini pricing, xAI pricing, Z.AI pricing, and Alibaba Model Studio pricing.

Media, voice and omni models

A rate card prices token dimensions per million tokens, as before. Schema opentine-pricing/3 adds two optional fields. units maps a dimension to its unit — image, second, minute, character or request — and that dimension's rate is per unit ({"rates": {"images:1024x1024:high": "0.17"}, "units": {"images:1024x1024:high": "image"}}). same_rate_as names a dimension the vendor bills like another ({"input_video": "input"}); it is never inferred.

Media dimensions: per-modality tokens input_image, input_audio, input_video, output_image, output_audio, output_video (split out of input/output), and per-unit images[:variant], video_seconds[:variant], audio_input_seconds, audio_output_seconds, audio_minutes, tts_characters, realtime_minutes, requests. A dimension the card does not price makes the result partial with a "missing rates" warning — media is never billed at the text rate. A per-unit dimension (or its :variant) is priced only in the unit the card states: a card that prices one without a units entry is refused at load, and a /1 or /2 catalog carrying per-unit rate names is refused. Older catalogs (/1, /2) cannot carry these fields, and a 0.10 reader refuses a /3 catalog. Gemini image and video input stay in the input bucket (they bill at the text rate on every model except Live).

Local infrastructure rates

Ollama and other local adapters preserve usage while reporting unmetered API cost by default, at capture and when tine price re-prices the run. Optional input/output token rates and compute-second rates let a workspace estimate infrastructure cost. unmetered means “no metered API price,” not “the hardware is free.”

Normal cost budgets warn and continue using the known subtotal. Set Budget(strict_cost=True) to halt before the next model call once any hosted price or observed usage dimension becomes indeterminate.