# Run estimate

What a run is likely to take before it starts: cost, time and (when it makes them) API calls, as ranges with what they're based on. If the high end would go past what's left of an API allowance, that's said before you start. Without enough history it says there's no estimate rather than guessing a number.

- Registry name: `run-estimate` (`@candor/run-estimate`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/run-estimate

## Install

```bash
npx candor-ui add run-estimate
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/run-estimate`.
It brings in: button, locale, locked, scale, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { RunEstimate } from "@/components/run-estimate"

export default function Example() {
  return (
    <div className="grid max-w-3xl gap-4 md:grid-cols-2">
      <RunEstimate
        title="Backfill region on 18,240 projects"
        estimate={{ kind: "estimated", cost: { low: 0.4, high: 1.1 }, time: { low: 180, high: 420 }, apiCalls: { low: 9_000, high: 21_000 }, basis: "23 similar backfills on Staging in the last 30 days" }}
        apiRemaining={13_600}
        apiLabel="Database writes"
        onStart={() => {}}
        onCancel={() => {}}
      />
      <RunEstimate title="Audit the invoices constraints" estimate={{ kind: "unknown", reason: "fewer than 5 runs like this one have finished." }} onStart={() => {}} onCancel={() => {}} />
    </div>
  )
}
```

## <RunEstimate>

Props:

- `title: string`: What the run will do, as a heading.
- `estimate: Estimate`: Cost, time and API-call ranges with what they're based on, or unknown with the reason.
- `apiRemaining?: number | undefined`: Calls left today against the API's allowance, when known.
- `apiLabel?: string | undefined`: What the calls are, e.g. "CRM API calls". Defaults to "API calls".
- `onStart?: (() => void) | undefined`: Shows a Start button; called when it's clicked.
- `onCancel?: (() => void) | undefined`: Shows a Cancel button; called when it's clicked.
- `startLocked?: string | undefined`: Why Start can't be used yet. Without one, Start is enabled.
- `className?: string | undefined`

## Strings (`runEstimate`)

The fixed words, English by default. Override any of them under `runEstimate` in `<LocaleProvider strings={{ runEstimate: { … } }}>`; the table is exported as `runEstimateStrings`.

- `apiCalls`: API calls
- `estimateFor`: Estimate for {title}
- `beforeItStarts`: Before it starts
- `noEstimate`: No estimate yet: {reason}
- `modelCost`: Model cost
- `time`: Time
- `basedOn`: Based on {basis}.
- `overAllowance`: At the high end this uses more {apiLabel} than the {remaining} left today, which other integrations share.
- `notNow`: Not now
- `startRun`: Start run

## Types

### Range

```ts
{ low: number; high: number }
```

### Estimate

```ts
| { kind: "estimated" cost: Range /** The cost range as your server wrote it ("about $0.40 to $0.90"), shown instead of `cost` formatted. */ costText?: string | undefined /** Seconds. */ time: Range /** Calls against a rate-limited API, when the run makes them. */ apiCalls?: Range | undefined /** What it's based on, e.g. "23 similar runs in the last 30 days". */ basis: string } /** Too little hist
```

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
