- Validate:
bun validate- Validates all provider/model configurations - Build web:
cd packages/web && bun run build- Builds the web interface - Dev server:
cd packages/web && bun run dev- Runs development server - No test framework - No dedicated test commands found
- Runtime: Bun with TypeScript ESM modules
- Imports: Use
.jsextensions for local imports (e.g.,./schema.js) - Types: Strict Zod schemas for validation, inferred types with
z.infer<typeof Schema> - Naming: camelCase for variables/functions, PascalCase for types/schemas
- Error handling: Use Zod's
safeParse()with structured error objects includingcause - Async: Use
async/await,for awaitloops for file operations - File operations: Use Bun's native APIs (
Bun.Glob,Bun.file,Bun.write)
- Monorepo: Workspace packages in
packages/(core, web, function) - Config: TOML files for providers/models in
providers/directory - Validation: Core package validates all configurations via
generate()function - Web: Static site generation with Hono server and vanilla TypeScript
- Deploy: Cloudflare Workers for function, static assets for web
- Use
export interfacefor API types,export const Schema = z.object()for validation - Prefix unused variables with underscore or use
_for ignored parameters - Handle undefined values explicitly in comparisons and sorting
- Use optional chaining (
?.) and nullish coalescing (??) for safe property access
Use this checklist when reviewing PRs that add providers or models. The first two items are hard blockers; the last two are strongly recommended but not blockers.
- Must ship a logo. Every new provider needs a
providers/<id>/logo.svgthat follows the logo guidelines below. A PR that adds a provider without a compliant logo is not mergeable as-is. - Should add a sync module when the source is context-rich. If the provider exposes an
API/catalog that can populate full model data (or at least authoritatively delete models
it no longer serves), add a sync module like OpenRouter's (see
sync.md). Only add sync when the source is rich enough to be authoritative; a thin endpoint that cannot populate required fields should stay hand-authored. This is highly recommended, not a blocker.
- Must use
base_modelwhen amodels/metadata entry exists for the underlying model. Do not duplicate provider-agnostic facts inline when they can be inherited. Only write a full inline definition when no matchingmodels/<provider>/<model>.tomlexists. - Reasoning models must declare
reasoning_options. Any model withreasoning = trueneeds areasoning_optionsarray reflecting the provider's actual API surface (see the audit-reasoning-options skill). For niche providers that document a budget or toggle control, express the exact API request syntax the provider expects as a TOML comment next to the option, e.g.:Use[[reasoning_options]] type = "toggle" # API: {"chat_template_kwargs": {"enable_thinking": false}} [[reasoning_options]] type = "budget_tokens" # API: {"thinking": {"budget_tokens": <n>}} min = 1_024 max = 32_000
reasoning_options = []when the model reasons but exposes no verified control.
- PRs that change data should cite their sources. Link to the provider's pricing page, model docs, or API reference that justifies the change in the PR body. This is highly recommended, not a blocker, but PRs without any sourcing should be treated with more scrutiny and verified before merge.
- In-file comments must live at the top of the file. The daily model sync rewrites synced provider TOMLs by parsing and re-serializing them, which discards every comment except a leading header block. Put source citations and rationale as a comment block at the very top of the file (above the first key); comments placed between sections or above individual keys are silently deleted on the next sync run.
- File lives at
providers/<provider-id>/logo.svg, SVG format. - No fixed size or hardcoded colors — use
currentColorfor fills/strokes so the logo adapts to light/dark themes. - Prefer a square
viewBox(e.g.0 0 24 24). - Example:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> <!-- Logo paths here --> </svg>
- Model
idis auto-injected from filename (minus.toml) — never putidin TOML files - Provider models may reuse provider-agnostic facts from
models/viabase_model; otherwise the full provider model definition must be present in the file - Schema uses
.strict()— extra fields cause validation errors
- Provider-agnostic model facts live under
models/<provider>/<model>.toml - Provider TOMLs can inherit those facts with:
Example:
base_model = "<provider-id>/<model-id>" base_model_omit = ["limit.input"] # optional, dot-path strings
base_model = "anthropic/claude-opus-4-6" - Resolved at parse time in
generate(); the final provider JSON output contains nobase_modelorbase_model_omitfields - Merge semantics:
- Plain objects from metadata and provider TOML (
[limit],[modalities], …) are deep-merged - Arrays (e.g.
modalities.input) and primitives are replaced wholesale by the child - Any provider field omitted is inherited verbatim from model metadata
cost,provider,experimental,reasoning_options,interleaved, andstatusare provider-specific and must be declared in provider TOMLs when needed
- Plain objects from metadata and provider TOML (
base_model_omitruns after the merge and deletes each dot-path from the result. Missing paths are ignored. Ancestor tables that become empty as a result are also pruned.- The base model metadata file must exist;
base_modelpointing at a missingmodels/entry is an error
- Dated models:
-v1:0suffix (anthropic.claude-3-5-sonnet-20241022-v1:0.toml) - Latest/undated models: bare
-v1(anthropic.claude-opus-4-6-v1.toml) - Region prefixes:
us.,eu.,global.(default has no prefix)
- Dated models:
@YYYYMMDD(claude-opus-4-5@20251101.toml) - Latest/undated models:
@default(claude-opus-4-6@default.toml)
cost.context_over_200kis a nestedCostobject for >200K token pricing- Cache pricing ratios: standard models use 10%/125% (read/write), regional variants may use 30%/375%
| Field | Required? | Notes |
|---|---|---|
name, release_date, last_updated |
Yes | Human-readable metadata |
attachment, reasoning, tool_call, open_weights |
Yes | Boolean capabilities |
cost, limit, modalities |
Yes | Objects with their own required fields |
family, knowledge, temperature, structured_output |
No | Optional metadata |
status |
No | Use for "alpha", "beta", "deprecated" lifecycle |