Skip to main content
veri run <config.toml> is a thin shortcut over the explicit veri jobs create / veri deployments create. It reads the required kind field from the config and dispatches. The contract is plural-noun-verb (veri jobs create configs/train.toml); veri run exists to save typing on the common path.

Scaffold a project: veri init

veri init NAME writes 8 files into ./NAME. With no NAME, scaffolds into the current directory.
The scaffolded configs/train.toml trains on a dataset named gsm8k-train. Register it once, then price the job before submitting it:
By default init refuses to write into a non-empty directory. Use --force to scaffold alongside existing files (existing files are preserved):

Dispatch rules

Every config starts with a required kind line:
veri run <path> reads kind and routes: A missing kind errors and lists the valid values; an unknown value also prints a “did you mean” hint:

Override TOML fields from the CLI

Use --set <dotted.key>=<value> to override any nested value. Convenience long-flags expand to --set internally.

Type coercion

Values parse as Python literals: integers, floats, true / false, quoted strings and lists. Anything else (including dates) stays a plain string. To force a string on a numeric-looking value, use --set-string:
Without --set-string, 20260512 is sent as an integer and the API rejects it (output_name: invalid type: integer).

Repeated flags build a list

Conflict detection

The merger rejects a scalar where the config already has a table, and a sub-key under a path another --set made a scalar:

Convenience long-flags

These flags are sugar over --set on veri jobs create: veri deployments create <config> expands its flags the same way (--name, --gpu-type, --gpu-count, --from-hf, --from-model, and the replica and scaling flags); see Create from a config.

Config schemas

veri.toml (project root)

configs/train.toml

[dataset].id must reference an already-registered dataset, by name or id: register it first with veri datasets upload or veri datasets connect-hf. The trained model is saved to Veri storage. [reward].file is a local path (relative paths resolve against the config file’s directory); the file’s source is attached to the job at submit. Multi-reward: files = ["a.py", "b.py"] plus optional weights = [1.0, 0.5].

configs/deploy.toml

[autoscaling] accepts exactly min_replicas, max_replicas, concurrency_target, scale_to_zero_window_seconds, idle_delete_after_days, and self_heal_attempts; any other key (for example target_qps) is rejected. The same six keys are also accepted under [resources], which is where the veri deployments create scaling flags (--min-replicas, --max-replicas, and friends) land. Setting a key in both tables with different values is an error: set it in one place.

Price a job before submitting

veri jobs estimate prices a kind="train" config without submitting it. It prints the resolved GPU config, a cost estimate, and, on the line under it, the duration it assumed (illustrative values):
The duration is an assumption, not a measurement of your job: about 6 minutes of startup (instance boot, environment setup, model and dataset download) plus max_steps at 18 seconds per step. Both numbers come from the measured GRPO run in Training examples. Step time grows with model size, rollouts_per_prompt, response length and, for harness jobs, how long your agent takes per rollout, so treat the estimate as a floor for bigger runs. Without max_steps it assumes 100 steps (the GRPO default); an sft_text or dpo run without max_steps runs num_epochs over the dataset, which the estimate does not count. Once you know your job’s real duration (from a short run, or the wall time of a previous one), price that instead with --minutes:
Add --format json for the same fields as a JSON object (gpu_type, gpu_count, provider, duration_minutes, rate_usd_per_hour, estimated_cost_usd), plus duration_assumption with the sentence printed under the table. --minutes and the step-based duration need veri-sdk 0.2.45 or later; older CLIs priced max_steps as minutes. The estimate covers GPU time only, not the monthly storage of the checkpoints and the final model a job keeps (see Checkpoint storage and Model storage). The estimate does not check the GPU shape or the dataset: submitting is what validates them. A submit that fails validation is rejected before anything is created or billed.

What’s next

Datasets

Upload, connect HuggingFace, validate.

Training

Jobs + reward files end-to-end.