Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Models and Cost

Heph does not have "a model". It has tiers: named groups of one model each, and each piece of work is sent to the tier for its role. The coding you ask for goes to the tier whose role includes coding; a plan turn goes to the review tier; a --quick turn to the quick tier. A profile is a set of tiers, and each conversation runs on one (Tiers and Profiles). You can change which model fills which role in config, or override the choice for one conversation.

The default tiers

Each provider's catalog defaults make a built-in profile of three tiers; with one provider, it is the default profile. heph profiles prints them all:

TierRolesDefault model (Bedrock)
frontiercoding, reviewThe catalog's large model, e.g. Claude Opus
workhorseresearch, summarizeThe catalog's small model, e.g. Claude Haiku
fastquick, commit-message, titleThe same small model, as its own tier so it can be pointed elsewhere

Only coding, review, and quick are used by anything today; the other roles exist so the layout does not change when the features that use them arrive. The first-run config file lists these tiers as comments, with the actual model ids, so you can see what was picked.

Thinking

A tier whose role includes coding or review has extended thinking on by default, at high effort; the others have it off. Thinking is the model reasoning before it answers, and it shows in the conversation folded to one line. It costs output tokens and improves the work on hard problems; for a quick question it is waste, which is why the fast tier has it off.

[tiers.NAME] thinking = "off" or "adaptive" overrides the default; effort = "low" | "medium" | "high" | "xhigh" | "max" sets how much. Models that do not take an effort level (Haiku 4.5, Sonnet 4.5, Opus 4.1) get a thinking token budget derived from the effort instead; heph knows which is which from the catalog. A GPT model reasons at its own default effort when the tier says off, since its API has no switch for it, and on Bedrock returns no summary of the reasoning to fold into the conversation.

Overriding for one conversation

--profile picks the profile; --tier NAME=MODEL runs one of its tiers on another model, and --model is short for --tier on the tier doing the conversation's role:

heph --profile work                             # every role from the work profile
heph --model fast                               # the turns on the fast tier's model
heph --model claude-haiku-4-5-20251001          # a model id, if one configured provider has it
heph --model bedrock/us.anthropic.claude-sonnet-4-6   # provider/model, when several could
heph --tier fast=claude-sonnet-4-6              # commit messages and titles on Sonnet

A bare model id is looked up across your configured providers; if two of them offer it, heph asks you to say which with the provider/ prefix. The tier keeps its own settings (roles, max_tokens, thinking) on the new model. The conversation keeps the choice: --continue routes it the same way.

The status bar shows the model's short name: opus-5, sonnet-4-6, haiku-4-5-20251001.

Native Ollama

heph --model ollama/NAME selects an already installed tool-capable model without a cloud credential. With no routing, all roles use it and continuation retains that bootstrap. Existing profiles keep their other role assignments; selecting a local conversation model is not a local-only promise, and mixed routing produces a warning. No automatic download or cloud fallback occurs. heph models --provider ollama discovers the selected endpoint; ordinary cloud startup does not probe an unselected local server.

Text attachments and vision-capable image attachments use the normal workflow. Thinking defaults to the server's behavior unless the tier explicitly configures supported controls. Runtime allocation, attachment limits, locality cautions, and experimental validation status are in Providers.

What things cost

Every request is recorded with its token counts, split four ways, and its cost at the model's catalog rates:

TokensRate
inputPrompt tokens sent fresh
outputWhat the model wrote, thinking included
cache writePrompt tokens written to the provider's cache
cache readPrompt tokens served from the cache, at a fraction of the input rate

heph models shows the four base rates for every model. The status bar shows muted totals like $1.00 / $4.00 / $8.00, in this order:

  • Session: requests made by this active heph process, across ref switches. A new process starts at zero, even when resuming a pending turn.

  • Total: all requests in this ref's ancestor history. Resuming restores it; /clear does not erase it. Forks inherit ancestor spend, but daily totals count each request only once. Moving the ref changes its reachable total.

  • Day: all requests across projects, sessions, providers, and models under this heph data root today. Days use the OS timezone through Jiff (or TZ), including daylight-saving transitions; totals refresh every five seconds.

Dollar amounts have no approximation markers. The status bar uses two decimal places; other cost displays use two above $1 and four otherwise. A request interrupted before final provider usage keeps its input estimate; it is not a confirmed bill. Accounting runs on independent read-only workers, not on prompt edits or sidebar toggles. The status bar keeps last-good amounts without refresh messages; - means no compatible sample, not zero spend. In /stats and the sidebar, loading means the first sample is pending; updating or stale keeps a compatible last-good value visible. Routine refreshes do not pulse valid compact labels. Known ledger changes show updating; ten seconds without a compatible successful sample shows stale. Retries keep failures visible until recovery. Errors remain visible in /stats, and missing data is unavailable, not zero. A ref/tip or local-day change clears incompatible values rather than displaying them under the new label. These totals include title, branch-name, and commit-message requests as well as normal rounds. They are displays, not enforced daily budget limits.

Each turn-end line shows tokens and USD separately for uncached input, output (including thinking), cache reads, and cache writes. It survives reopening. The cache status figure is the share of live prompt tokens served from cache; /clear resets live token/cache counters, not persisted spend.

/cost opens a focused dashboard at any width: session, thread, and today split into uncached input, output (including thinking), cache read, and cache write tokens and USD. It also shows cross-project daily spend, requests, and all-category token counts for today plus the previous six local calendar days. Empty days are included; today is marked partial. The seven-day total and daily average include partial today. Weekly provider/model totals are ranked by spend. Request and estimate counts indicate how much usage lacks final provider data. The input cache hit rate is cache-read tokens divided by uncached input plus cache-read and cache-write tokens; without input tokens it is n/a.

The dashboard opens from cached data and refreshes asynchronously while open. Weekly reads open each project once per batch. Failures retain compatible last-good values with visible errors, never a misleading zero; changed dates or timezones clear incompatible samples. Up/Down, PgUp/PgDn, and the wheel scroll; Esc or another non-scroll key closes it. A late completion never reopens it. There are no arguments or filters. The sidebar's cost hint points to /cost.

In a wide terminal the sidebar shares skills with today's provider/model cost breakdown. /stats opens immediately at any terminal width using cached totals, then updates the same window with fresh details. Tool attribution has its own loading notice until the detailed sample arrives. Up/Down, PgUp/PgDn, and the wheel scroll; Esc or another non-scroll key closes it. A late completion never reopens a closed window. Reopened conversation text appears first; its cost summaries arrive as a batch and show unavailable rather than zero if that read fails.

The stats view also shows estimated tool request shares for this thread. A request that generates several recorded tool calls is split equally among them, including its input and output tokens. This does not measure the execution cost of a tool, does not include later requests processing its results, and leaves requests without tools unattributed. Shares are not added to spend again.

Cost is computed from the catalog's rates, not from a bill, so it is an estimate that is exact when the rates are. heph models is the place to check them; the catalog is a snapshot embedded in the binary.

If an Ollama response omits final usage counts, the status bar shows tok unknown and cost incomplete instead of claiming actual zero usage. Native cached-token metrics and nanosecond timings are retained when supplied. Default local rates are zero API charges, not zero electricity or hardware cost.

Failover

A tier may list several provider/model references for the same model:

[tiers.frontier]
models = ["bedrock/us.anthropic.claude-opus-5", "anthropic/claude-opus-5"]
roles = ["coding", "review"]

The first configured provider that is usable is the one heph talks to. Falling over to the next on a failed request is not implemented yet; today the list picks the first provider you have credentials for.

Choosing

The defaults are a reasonable start: a frontier model for the work you review and a small one for the rest. Reasons to change them:

  • Cost. Point coding at Sonnet for everyday work and keep Opus for a --model override when a problem is hard, or a profile for it.
  • Provider. You have both an API key and Bedrock; configure both providers and choose per tier.
  • GPT. The openai and bedrock-openai providers carry OpenAI's models, the second under the same AWS credentials as bedrock. A tier is one protocol, so a GPT tier lists GPT providers only; see Providers.
  • A local or gateway model. A server speaking the Messages or the Responses protocol can be a provider with its own models and rates; see Providers.