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.
configs/train.toml trains on a dataset named gsm8k-train. Register it once, then price the job before submitting it:
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 requiredkind 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:
--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):
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:
--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.

