# Usage meters

What's used against each limit: seats, an environment's daily API allowance, agent work. The bar's fill carries severity (accent → warning → danger past 75% and 90%); its track is a lighter step of the same hue. Where the plan sets no limit the meter says so and shows the count alone — it never draws a bar against a made-up cap. A usage's `estimate` (your own figure, such as a quote) is a tick on the bar with its label, never a projection the meter makes up. When your server formats the figures ("about $4"), `usedText`, `limitText` and `estimateText` are shown as written; the numbers only place the bar.

Usage that's done but not metered yet (`pending`) is a striped part of the bar after what's used, said in words, and how far a run may still go past the limit (`mayExceedBy`) is said under the meter: both are your figures, never the meter's projection.

- Registry name: `usage-meters` (`@candor/usage-meters`)
- 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/usage-meters

## Install

```bash
npx candor-ui add usage-meters
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/usage-meters`.
It brings in: locale, ops, relative-time, utils.

## Example

```tsx
"use client"

import { UsageMeters } from "@/components/usage-meters"
import type { Usage } from "@/lib/ops"

const usages: Usage[] = [
  { label: "Seats", used: 6, limit: 8, unit: "seats", note: "2 pending invites would use both." },
  { label: "CI minutes today · Production", used: 864, limit: 1_000, unit: "minutes", resetsAt: new Date(Date.now() + 9 * 3_600_000).toISOString() },
  { label: "Agent runs this month", used: 412, limit: null, unit: "runs" },
  // estimate: your own figure (a quote, a forecast), marked on the bar and labelled; the meter never projects one.
  { label: "Spend on this job", used: 1.2, limit: 4, unit: "USD", estimate: 2.6, estimateLabel: "Quoted" },
  // pending: done but not metered yet; mayExceedBy: your provider's own figure for how far a run may go past the limit.
  { label: "Agent spend today", used: 7.4, limit: 10, unit: "USD", usedText: "$7.40", limitText: "$10", pending: 1.1, pendingText: "about $1.10", mayExceedBy: 2, mayExceedByText: "$2" },
]

export default function Example() {
  return <UsageMeters className="max-w-xl" usages={usages} />
}
```

## <UsageMeters>

Props:

- `usages: Usage[]`: One meter per limit: what's used, the limit (null when there is none), the unit and when it resets.
- `className?: string | undefined`

## Strings (`usageMeters`)

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

- `usage`: Usage
- `noCap`: No cap on your plan.
- `resets`: Resets {time}.
- `estimate`: Estimate
- `estimateValue`: {label}: {value}
- `pending`: {value} not yet metered
- `mayExceed`: May go over the limit by up to {value}.

## 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`.
