Skip to main content
Values in NiceEval have exactly two homes:
  • Configuration lives in code — CLI flags, experiment files under experiments/, and niceeval.config.ts at the root. How many attempts, how long before timeout, how much concurrency, which judge model, which report to show by default: all of it lives here, with no environment variable counterpart.
  • Secrets live in environment variables — API keys and provider tokens, plus facts like NO_COLOR that describe which terminal you are printing to.
So every value has exactly one source. What niceeval exp --dry prints is what actually takes effect; no environment variable is quietly changing it behind your back. CLI and runtime copy is English; the browser view has its own English and Chinese switch.

Configuration: pick the layer by how long the value should last

When the same value appears in more than one layer, resolution is CLI flag → experiment → config → built-in default, stopping at the first one present. Just this once — put it on the command:
Always, for this experiment — put it in the experiment file:
agent, model, and flags can only be written here — there is no flag for them. Switching agent or model means copying an experiment file, which is what keeps “what did this run go against” recorded in the snapshot and reproducible afterwards. Shared by the whole project — put it in niceeval.config.ts:

What niceeval.config.ts holds

Types and full descriptions are in the defineConfig reference; the full flag table is in the CLI reference.

Environment variables: secrets and terminal facts only

These are all the environment variables NiceEval reads. Each agent, sandbox, and the judge recognizes exactly one name and never goes hunting for another key in the environment. To keep the judge’s key under a different variable name, point at it from the config:
When the gateway address itself is not something you want committed, NiceEval doesn’t need to offer a variable for it — configuration is code, so read it yourself (.env is already loaded by then):
The difference is only this: the variable name belongs to your project, instead of NiceEval baking in a name and going looking for it in the environment. Locally, put secrets in .env in the current directory — the CLI loads it at startup (without overwriting variables that already exist), so no export every time:
.env is how secrets get delivered, not a second config file — putting something like NICEEVAL_TIMEOUT in it has no effect. In CI, pass only secrets the same way:

Seen these in an old script? Move them into configuration

The judge also no longer borrows a key from CODEX_API_KEY / OPENAI_API_KEY or guesses its endpoint from OPENAI_BASE_URL. When the app under test repurposes the standard OPENAI_* names for something else, the judge no longer gets dragged along.

Next

defineConfig reference

Type and full description of every config field.

CLI reference

Commands, the full flag table, and exit codes.

Write an experiment

Which values belong to one concrete run.

CI integration

Passing secrets in CI.