kanros migrate

Translate an existing declarative eval configuration — the common YAML shape used by earlier-generation Node.js eval CLIs — into a kanros configuration.

kanros migrate <INPUT> [--output <PATH> | --stdout]
Flag / argDefaultMeaning
<INPUT>requiredPath to the legacy config to migrate.
-o, --output./kanros.yamlWrite to this path.
--stdoutoffPrint to stdout (mutually exclusive with --output).

What it does

kanros migrate reads the input file, parses the legacy schema, and emits an equivalent kanros YAML. The translator:

  • Maps providers: 1:1, preserving inline config: blocks.
  • Maps prompts: 1:1, converting any file:// / https:// URIs as-is.
  • Walks every tests[i].assert[j] and translates the assertion's type: to its kanros equivalent, normalising to kebab-case.
  • Translates defaultTestdefault_test, including its vars: and appended assert: list.
  • Inserts # TODO: comments wherever a legacy construct has no direct kanros equivalent.

The command prints a summary line on success:

✓ migrated → kanros.yaml  (3 providers, 5 prompts, 24 tests)

If TODOs were inserted, the line also notes the count:

✓ migrated → kanros.yaml  (3 providers, 5 prompts, 24 tests) (2 TODO comment(s) — review before running)

Examples

kanros migrate legacy-config.yaml
kanros migrate legacy-config.yaml --output configs/regression.yaml
kanros migrate legacy-config.yaml --stdout | less

What survives translation

Source conceptkanros equivalent
providers: listproviders: list (id passed through)
prompts: list (string)prompts: list (string)
prompts: list (file URI)prompts: list (string, URI preserved)
tests: listtests: list
vars: per testvars: per test
defaultTestdefault_test
assert: type: equalsassert: type: equals
assert: type: containsassert: type: contains
assert: type: regexassert: type: regex
assert: type: javascriptassert: type: javascript (runs in boa_engine)
assert: type: llm-rubricassert: type: llm-rubric with provider: block
assert: type: factualityassert: type: factuality
assert: type: model-graded-*model-graded-closedqa / answer-relevance
weight: on assertionsassert-set with op: weighted and threshold:

What needs human review

The migrator inserts a # TODO: comment above any construct that does not have a clean kanros equivalent. Look for these markers and resolve them before piping the file into kanros run:

  • Inline JavaScript graders that depend on Node.js built-ins (fs, path, http). kanros runs JS via embedded boa_engine, which exposes no Node APIs. Rewrite the grader as a pure function or port it to a WASM plugin (see WASM plugins).
  • Custom dataset loaders. kanros supports CSV, JSONL, and Hugging Face datasets via the kanros-datasets crate. Other loaders need a file:// URI plus a short pre-processing script.
  • Cloud-only features — team mode, remote run history. kanros does not have a server side; for run comparisons see kanros diff, for sharing see kanros share.
  • Cost / latency assertions with units other than USD / ms. kanros is strict on units.

Sanity workflow after migration

kanros migrate legacy-config.yaml
grep -n 'TODO:' kanros.yaml          # resolve all TODOs
kanros validate --config kanros.yaml # check shape
kanros run --config kanros.yaml --no-cache  # smoke test

Then start iterating.

Notes

  • The migrator is one-shot. It does not watch the source for changes; re-run it after any meaningful edit to the source config.
  • The output is deterministic given a fixed input. Diff-friendly.
  • If the input file cannot be read or the YAML parser rejects it, migrate exits with code 2 and prints the underlying error.