- 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
- Model
idis auto-injected from filename (minus.toml) — never putidin TOML files - Models may reuse another model's definition via
extends(see below); otherwise the full definition must be present in the file - Schema uses
.strict()— extra fields cause validation errors
- Syntax — a table at the top of the TOML:
Example:
[extends] from = "<provider-id>/<model-id>" # required omit = ["experimental.modes.fast"] # optional, dot-path strings
from = "anthropic/claude-opus-4-6" - Resolved at parse time in
generate(); the final JSON output contains noextendsfield — it exists only to cut duplication in the TOMLs - Merge semantics:
- Plain objects (
[cost],[limit],[modalities],[provider],[experimental], …) are deep-merged - Arrays (e.g.
modalities.input) and primitives are replaced wholesale by the child - Any field the child omits is inherited verbatim from the base
- Plain objects (
omitruns after the merge and deletes each dot-path from the result (used when the child needs to remove something the base defines, e.g. a provider-specific experimental mode). Every listed path must exist in the merged model, else an error is thrown. Ancestor tables that become empty as a result are also pruned, soomit = ["experimental.modes.fast"]yields noexperimentalkey in the final JSON whenfastwas the only mode.- Chains are allowed (A extends B extends C); cycles throw
- The base model must exist;
[extends.from]pointing at a missing provider/model is an error - The
extendstable is stripped before schema validation, so the merged result must still satisfy the strictModelschema
- 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 |