The qsolve command line
Reference for every qsolve command, argument and option: init, validate, lint, run, estimate and test, with defaults, exit codes, output formats, environment variables, error messages and examples.
Updated 13 November 2026 View as markdown
On this page
qsolve is installed with qsolve-sdk (pip install "qsolve-sdk[ibm]"). It is a Typer application with six commands, all working on a workflow directory on your machine. The platform runs the same SDK code, so these are the checks it applies. The Python behind each command is documented in the SDK reference.
| Command | Purpose |
|---|---|
init |
Scaffold a working Qiskit workflow (a QUBO solved with QAOA) to start from. |
validate |
Check the manifest, schemas and example inputs. |
lint |
Static checks the platform applies before running anything. No code is executed. |
run |
Run a workflow locally on one input. |
estimate |
Size a run (qubits, circuits, shots) without executing it. |
test |
Run the validation gates and benchmark cases, the same ones the platform runs. |
Global options
qsolve [OPTIONS] COMMAND [ARGS]...
| Option | Meaning |
|---|---|
--version |
Print the SDK version (for example 1.0.0) and exit 0. |
--install-completion |
Install shell completion for the current shell. |
--show-completion |
Print the completion script, to copy or customise. |
--help |
Show help and exit 0. Also available on every command: qsolve run --help. |
Running qsolve with no command prints the help and exits 2 (the usage-error code of the Click library under Typer).
Targets
The --target option of run, estimate and test takes one of:
| Value | Runs on |
|---|---|
sim-cpu |
Qiskit Aer on the CPU. The default. Noise-free. |
sim-gpu |
Qiskit Aer on a GPU; needs qiskit-aer-gpu. |
fake:<device>[@scale] |
Aer with an IBM device's published noise model (fake:fez), optionally with every error rate multiplied by scale, from 1 to 10 (fake:fez@1.6). Free. Needs the ibm extra. |
ibm:<device> |
IBM Quantum hardware, with your own token (ibm:ibm_fez). Needs the ibm extra. Spends your IBM quota. |
See Backends and targets. estimate does not run anything, so its --target is only passed to your workflow's estimate(); it is not checked.
Environment variables
| Variable | Used by | Purpose |
|---|---|---|
QSOLVE_IBM_TOKEN |
--target ibm:<device> |
Your IBM Quantum token. Required for that target. Never put it in workflow code or the repository. |
QSOLVE_IBM_INSTANCE |
--target ibm:<device> |
Optional IBM instance. |
QSOLVE_SIM_THREADS |
simulators | Threads a simulation may use. A positive integer; otherwise every core available to the process. |
QSOLVE_EXECUTOR_ADDR, QSOLVE_EXECUTOR_TOKEN |
the platform's sandbox | Set by the platform, not by you. When QSOLVE_EXECUTOR_ADDR is set, every run uses the platform's executor whatever --target says. Leave it unset locally. |
Exit codes
| Code | Meaning |
|---|---|
0 |
The command succeeded. |
1 |
The command ran and found a problem (see each command below), or an unexpected exception: Python prints a traceback and exits 1. A missing or invalid qsolve.yaml, an unreadable input file and a bad target are never tracebacks: they print Error: or Invalid workflow: and exit 1. |
2 |
A usage error caught by the command-line parser: a missing required option or argument, an unknown option, or a malformed --param. |
| Command | 0 | 1 |
|---|---|---|
init |
the workflow was created | invalid name, or the destination exists |
validate |
manifest, schemas and examples are valid | any of them is invalid |
lint |
no errors; warnings allowed | at least one error |
run |
the run completed | a WorkflowError such as an invalid input, parameter or target; an unreadable input file; a missing or invalid qsolve.yaml |
estimate |
the estimate was printed | the same causes as run |
test |
every gate passed | a gate failed, or the workflow is invalid |
qsolve init
qsolve init NAME [--summary TEXT] [--directory PATH]
Creates a complete workflow in <directory>/<NAME> that solves a small QUBO with QAOA and passes every gate.
| Argument or option | Default | Meaning |
|---|---|---|
NAME |
required | 2 to 63 lowercase letters, digits and dashes, starting with a letter or digit (regular expression [a-z0-9][a-z0-9-]{1,62}). It becomes the workflow's name in qsolve.yaml. |
--summary |
My Qsolve workflow |
One-line description, written into qsolve.yaml (summary:) and the README. Whitespace runs, line breaks included, become single spaces. The value is written as a quoted YAML string, so colons, #, quotes and a leading dash are safe. |
--directory |
the current directory | The parent directory. Created if missing. |
Files created:
<NAME>/
qsolve.yaml the manifest, with name and summary filled in
README.md a short readme with the develop commands
benchmarks/cases.yaml three cases: two noise-free, one on fake:fez@1.6
examples/qubo_5.json a 5-variable example input
schemas/input.json
schemas/output.json
src/__init__.py
src/workflow.py the Qiskit workflow (class Qubo)
tests/test_workflow.py a pytest file that runs the example through run_workflow
It creates no LICENSE and no requirements.lock, so qsolve lint warns W051 until you add a license file. File meanings: Project layout. Walk-through: Your first workflow.
On success it prints:
Created <path>
Next: cd <NAME> && qsolve test . (edit src/workflow.py: it is plain Qiskit)
| Message (printed in red) | Exit | Cause |
|---|---|---|
Name must be lowercase letters, digits and dashes (2-63 chars). |
1 | NAME does not match the pattern (uppercase, underscore, one character, 64 or more). |
<path> already exists. |
1 | The destination exists, as a file or a directory. Nothing is overwritten. |
The summary and the name are written into qsolve.yaml as quoted YAML strings, so --summary "Pick: the depots # fast" is stored exactly as typed.
qsolve validate
qsolve validate [WORKFLOW]
| Argument | Default | Meaning |
|---|---|---|
WORKFLOW |
. |
The workflow directory. |
Loads qsolve.yaml, reads both schema files and checks every example input listed under inputs.examples against the input schema. Prints, in green:
OK depot-picker v0.1.0
| Message (red) | Exit | Cause |
|---|---|---|
Invalid workflow: <reason> |
1 | No qsolve.yaml (No qsolve.yaml in <dir>), invalid YAML, a manifest that breaks a rule (the reason is the pydantic error text), a schema file missing or not a JSON object, or a schema path that leaves the directory. |
Example <path>: <reason> |
1 | An example file is unreadable (cannot read <path>: ...), is not a JSON object, or does not match the input schema (Invalid input at <field>: <message>). It stops at the first bad example. |
validate does not check the schemas against Qsolve's restrictions and does not inspect your code; lint does that. It does not require that at least one example exists; lint and test do.
qsolve lint
qsolve lint [WORKFLOW]
| Argument | Default | Meaning |
|---|---|---|
WORKFLOW |
. |
The workflow directory. |
Runs the static checks the platform applies before it executes anything. None of your code runs. Each finding is one line: the severity (upper case, padded to 7 characters), the code, the message and, when there is one, the path (relative to the workflow, shown dim):
WARNING W051 no LICENSE file found
0 error(s), 1 warning(s)
With no findings it prints No problems found. Otherwise the last line is <n> error(s), <m> warning(s). Errors print in red, warnings in yellow. It exits 1 when there is at least one error; warnings alone exit 0. A missing or invalid manifest is reported as a finding (E001, E002), not as a crash. Every code is explained in Lint codes.
qsolve run
qsolve run WORKFLOW --input FILE [--target T] [--seed N] [--param key=value]... [--out FILE]
Runs the workflow once on one input, with every declared method.
| Argument or option | Short | Default | Meaning |
|---|---|---|---|
WORKFLOW |
required | The workflow directory. | |
--input |
-i |
required | Path to the input JSON file. It must contain a JSON object. |
--target |
sim-cpu |
Where to run; see Targets. | |
--seed |
0 |
The run's seed (an integer). The same input, parameters and seed give the same result. | |
--param |
-p |
none | A parameter override, key=value. Repeatable. The value is parsed as JSON where possible, so 500 is a number, 0.5 a float, true a boolean and [1,2] a list, while fast stays text. The key must be a parameter declared in the manifest. |
--out |
none | Write the full JSON output, the result and its provenance, to this file (UTF-8, indented). |
qsolve run . -i examples/qubo_5.json --seed 1 -p layers=1
depot-picker v0.1.0 on aer-cpu
┌───────────────────────────────┬─────────────────────┐
│ Metric │ Value │
├───────────────────────────────┼─────────────────────┤
│ Objective (quantum) │ -10 │
│ Objective (Exhaustive search) │ -10 │
│ Gap vs baseline │ 0.000% │
│ Uncertainty │ exact (stderr None) │
│ Shots │ 4000 │
│ Run time (s) │ 2.22 │
└───────────────────────────────┴─────────────────────┘
QAOA (quantum approximate optimisation): -10; Exhaustive search: -10 (accuracy 100.00%).
The table title is <workflow> v<version> on <device>. The row labelled with the reference is named after the reference method's manifest title. After the table it prints the result's summary sentence, and Wrote <path> when --out was given.
The --out file is the RunOutput as JSON: a result object (answer, objectives, gap, uncertainty, per-method results, metrics, quality measurements) and a provenance object (input hash, parameters, seed, target, device, shots, timings, result hash). Every field is described in Results and events.
| Message | Exit | Cause |
|---|---|---|
Error: <message> (red) |
1 | Any WorkflowError. Common ones below. |
Error: cannot read <file>: <reason> |
1 | The input file is missing or not valid JSON. |
Error: <file> must contain a JSON object |
1 | The input JSON is not an object. |
Error: unknown parameters: ['x'] |
1 | --param names a parameter the manifest does not declare. |
Error: parameter 'layers' must be <= 6.0 (or >= ..., must be an int, must be a number, must be one of [...]) |
1 | A parameter value is out of range or the wrong type. |
Error: Invalid input at Q: [[1]] is too short |
1 | The input does not match the input schema; the path names the field. |
Error: Unknown target 'foo'. Use sim-cpu, sim-gpu, ibm:<device> or fake:<device>[@scale]. |
1 | A bad target. |
Error: No qsolve.yaml in <dir> (or the manifest's validation message) |
1 | run and estimate on a directory with a missing or invalid qsolve.yaml: the same causes as validate's Invalid workflow:. |
Error: QSOLVE_IBM_TOKEN is not set |
1 | ibm: target without a token. |
Error: Install the ibm extra: pip install 'qsolve-sdk[ibm]' |
1 | ibm: or fake: target without the extra. |
Error: no fake device 'x' (e.g. fez, marrakesh, torino) |
1 | Unknown fake device. |
Error: noise scale must be between 1 and 10 |
1 | fake:<device>@<scale> out of range. |
Error: Problem has N variables; this workflow supports at most M (<notes>) |
1 | The input is bigger than the manifest's envelope. |
Error: the quantum method or the reference produced no result: <why> |
1 | A method was unavailable or raised MethodUnavailable. |
Error: Workflow produced an invalid answer: <message> |
1 | answer() returned something the output schema rejects. |
Error: --param expects key=value, got 'foo' |
2 | A malformed --param; printed by the usage-error formatter. |
An unexpected exception in your own code, or a workflow directory with no valid qsolve.yaml (use validate first), is not caught by run and prints a Python traceback, exit code 1.
qsolve estimate
qsolve estimate WORKFLOW --input FILE [--target T]
Validates the input and sizes the run without executing any method (no circuit runs), printing the estimate as JSON.
| Argument or option | Short | Default | Meaning |
|---|---|---|---|
WORKFLOW |
required | The workflow directory. | |
--input |
-i |
required | Path to the input JSON file (a JSON object). |
--target |
sim-cpu |
Passed to your workflow's estimate(target); not checked. |
{
"qubits": 5,
"circuits_on_target": 1,
"shots_on_target": 4000,
"classical_cost_class": "low",
"runtime_s": null,
"notes": [],
"by_default": false
}
by_default is true when the workflow gives no estimate() and Qsolve fell back to one circuit and params["shots"] shots. runtime_s, when the workflow predicts it, includes the fixed 20 s run overhead. There is no --param option, so the estimate uses the manifest defaults. Errors are the same Error: <message> lines as for run (invalid input, envelope, and so on), exit 1. The fields are explained in Metering and cost.
qsolve test
qsolve test [WORKFLOW] [--target T] [--out FILE]
Runs the validation gates and every benchmark case, as the platform does on submission.
| Argument or option | Default | Meaning |
|---|---|---|
WORKFLOW |
. |
The workflow directory. |
--target |
sim-cpu |
The target for cases that do not set their own target. |
--out |
none | Write the full JSON report here (UTF-8, indented). |
It prints a table of gates (name, pass or FAIL, detail), a table of cases titled Cases on <target> (name, result, relative gap, mitigated fidelity, seconds; - for a missing value; a failed case shows its reason after FAIL), then ALL GATES PASSED in green or FAILED in red. See Your first workflow for a real output and Benchmarks for each gate and expect key. The JSON report holds workflow, version, target, passed, gates, cases and total_time_s (BenchmarkReport).
| Message | Exit | Cause |
|---|---|---|
ALL GATES PASSED |
0 | Every gate passed. |
FAILED |
1 | At least one gate failed. |
Invalid workflow: <reason> (red) |
1 | No qsolve.yaml, an invalid manifest, a missing schema, or a malformed cases.yaml. No tables are printed. |
A target that cannot be used (for example ibm: without a token) does not stop the command; each affected case fails with the reason in its row. qsolve test runs every case once, then the first case again and an estimate, so with --target ibm:<device> it spends your own IBM quota. qsolve test does not run lint; run qsolve lint . too, because the platform runs both. Cases listed under hardware_cases: are never run by qsolve test.
A typical loop
qsolve validate . && qsolve lint . && qsolve test .
Because every command exits non-zero on failure, this stops at the first problem. Run it before every submission; see Validation and publishing.
The same checks from Python
| Command | Python |
|---|---|
qsolve run |
qsolve.run_workflow(dir, input, target=, params=, seed=) |
qsolve estimate |
qsolve.estimate_run(dir, input, target=) |
qsolve validate |
qsolve.load_workflow(dir) and qsolve.runner.validate_input |
qsolve lint |
qsolve.lint.lint_workflow(dir) |
qsolve test |
qsolve.benchmark.run_benchmarks(dir, target) |