Skip to content

qubithub.toml Reference

The qubithub.toml file is the single source of truth for every circuit on QubitHub. You write the TOML; the platform generates metadata.json from it. Never hand-author metadata.json.

TOML is a configuration format designed for humans — like YAML but without implicit typing gotchas, and like JSON but with comments and less boilerplate. It’s the same format used by Rust (Cargo.toml), Python (pyproject.toml), and Julia (Project.toml).

QubitHub manifests follow a progressive model — start simple and add sections as needed.

Every circuit needs at least this:

[project]
name = "bell-state"
title = "Bell State"
type = "circuit"
framework = "qiskit"
entry_point = "circuit.py"
qubits = 2

Adds description, tags, gates, execution config (including a named entry function), educational metadata, and reference output:

schema_version = "1.0.0"
[project]
name = "vqe-h2"
title = "VQE for H2 Ground State"
type = "circuit"
framework = "pennylane"
framework_version = "0.38.0"
entry_point = "circuits/main_circuit.py"
qubits = 4
depth = 24
gates = ["H", "CNOT", "RY", "RZ"]
category = "chemistry"
difficulty = "intermediate"
tags = ["vqe", "chemistry", "variational"]
[execution]
default_backend = "default.qubit"
default_shots = 4096
timeout_seconds = 60
entry_function = "build_vqe_h2_ansatz"
[educational]
level = "intermediate"
concepts = ["variational-algorithms", "hamiltonian-simulation"]
prerequisites = ["bell-state", "single-qubit-gates"]
learning_outcomes = [
"Understand the VQE hybrid classical-quantum loop",
"Implement a hardware-efficient ansatz",
]
estimated_time = "45 minutes"
next_circuits = ["vqe-lih", "qaoa-maxcut"]
[expected_output]
dominant_states = ["0011", "1100"]
probability_range = [0.35, 0.65]

Adds parameters, hardware requirements, reproducibility, multi-framework implementations, and references:

schema_version = "1.0.0"
[project]
name = "qaoa-maxcut"
title = "QAOA for MaxCut"
type = "circuit"
framework = "qiskit"
framework_version = "1.3.0"
entry_point = "circuits/main_circuit.py"
qubits = 6
depth = 42
gates = ["H", "CX", "RZ", "RX"]
category = "optimization"
difficulty = "advanced"
tags = ["qaoa", "optimization", "maxcut", "combinatorial"]
[execution]
default_backend = "aer_simulator"
default_shots = 8192
timeout_seconds = 120
entry_function = "build_qaoa_maxcut"
[hardware]
connectivity = "heavy-hex"
min_qubits = 6
required_gates = ["h", "cx", "rz", "rx"]
backend_compatibility = ["aer_simulator", "ibm_brisbane", "ibm_kyoto"]
noise_model = "ibm_brisbane_2026q1"
[parameters]
gamma = { default = 0.785, range_min = 0.0, range_max = 3.14159, description = "Problem unitary angle" }
beta = { default = 0.393, range_min = 0.0, range_max = 3.14159, description = "Mixer unitary angle" }
[reproducibility]
backend_used = "aer_simulator"
shots_used = 8192
seed = 42
transpilation_level = 3
framework_version_tested = "1.3.0"
last_verified = "2026-03-01"
[implementations]
qiskit = "circuits/qiskit/main_circuit.py"
pennylane = "circuits/pennylane/main_circuit.py"
[educational]
level = "advanced"
concepts = ["qaoa", "combinatorial-optimization", "mixer-hamiltonian"]
prerequisites = ["vqe-h2", "grover-search"]
learning_outcomes = [
"Implement QAOA for graph optimization problems",
"Understand the relationship between circuit depth and approximation quality",
]
estimated_time = "90 minutes"
next_circuits = ["qaoa-tsp", "qaoa-portfolio"]
[expected_output]
dominant_states = ["101010", "010101"]
probability_range = [0.25, 0.45]
[[references.papers]]
title = "A Quantum Approximate Optimization Algorithm"
authors = ["Farhi, E.", "Goldstone, J.", "Gutmann, S."]
year = 2014
arxiv = "1411.4028"
[files]
readme = "README.md"
source = "circuits/qiskit/main_circuit.py"
tests = "tests/"
results = "results/"

FieldTypeRequiredDefaultDescription
schema_versionstringno"1.0.0"Manifest schema version (semver). Current supported value: "1.0.0"
FieldTypeRequiredDefaultDescription
namestringyesURL slug: lowercase, hyphens, 1–100 chars
titlestringyesHuman-readable display name
typestringyes"circuit", "dataset", "space", or "benchmark"
frameworkstringyes"qiskit", "pennylane", "cirq", "braket", or "openqasm3". Qiskit, PennyLane, and Cirq circuits execute natively on the QubitHub sandbox; Braket and OpenQASM 3 can be described, versioned, and shared but are not yet executable in-platform (see FAQ)
entry_pointstringyesPath to main file, relative to repo root
qubitsintegeryesNumber of qubits used
descriptionstringnofrom READMEShort description (1–2 sentences)
framework_versionstringnoFramework version the circuit targets
depthintegernoCircuit depth
gatesstring[]no[]Gate names used in the primary framework’s notation (Qiskit: CX, PennyLane: CNOT, Cirq: CNOT). Migrated from an integer count in an earlier schema — string-array shape is canonical
categorystringnoPrimary category (see below)
difficultystringno"beginner""beginner", "intermediate", or "advanced"
tagsstring[]no[]Searchable tags
is_publicbooleannotruePublic visibility

Controls how qubithub execute runs the circuit.

FieldTypeDefaultDescription
default_backendstringframework-dependentQiskit: "aer_simulator", PennyLane: "default.qubit", Cirq: "cirq.Simulator", Braket: "local", OpenQASM 3: "aer_simulator"
default_shotsinteger1024Measurement shots (1–100,000)
timeout_secondsinteger30Max execution time, in seconds (1–300)
entry_functionstringName of a zero-arg factory function in the entry point to call. When declared, takes precedence over the default circuitqcmain() chain. Must match ^[a-z_][a-z0-9_]*$; dunders are rejected. See Python entry-point contract below
sample_inputsarray[]PennyLane runner only — positional arguments passed to the QNode on each invocation. Qiskit and Cirq runners ignore this field. Per-run parameters that vary by call should live in [parameters], not here

When project.entry_point points to a .py file, the platform runs it in a hardened sandbox (network-isolated, read-only filesystem, capability-dropped Docker) and extracts the resulting circuit. The runner resolves the entrypoint using this chain, stopping at the first hit:

  1. Declared [execution].entry_function — the named factory in your TOML, called with zero arguments. Authoritative: if declared but missing or broken, the runner hard-fails rather than falling through to the defaults below.
  2. A top-level circuit variable bound to a qiskit.QuantumCircuit (or framework equivalent), or
  3. A top-level qc variable (the Qiskit-tutorial alias), or
  4. A main() function that returns the circuit object.

Per-run parameters (a theta vector for a variational circuit, edges for a QAOA problem) belong in the [parameters] section, not in the entry call. The entry function must be callable with zero arguments — provide domain-meaningful defaults in the factory signature, or declare a zero-arg wrapper alongside the parameterized version.

# ✅ Preferred — declared entry_function factory
# qubithub.toml: [execution] entry_function = "create_bell_state"
from qiskit import QuantumCircuit
def create_bell_state() -> QuantumCircuit:
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
return qc
# ✅ Fallback — top-level `circuit` variable (canonical default)
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])

Most authored circuits in the curated library use a create_<name>() -> QuantumCircuit factory idiom — the default chain can’t resolve those without the declaration. Use entry_function when:

  • your circuit ships a named factory (create_bell_state, build_vqe_ansatz) rather than a module-scope binding
  • there are multiple factories in the file and you need to disambiguate which one is the canonical entrypoint
  • you want the execution contract to travel with the circuit in its git repo — the same discipline as pyproject.toml [project.scripts] or Cargo.toml [[bin]]

Keep the default chain (Options 2–4) when your circuit is short and declarative — a bare module-scope binding is the simplest contract and doesn’t need a manifest entry.

Quantum hardware requirements.

FieldTypeDefaultDescription
connectivitystring"any"Topology: "any", "linear", "grid", "heavy-hex", "sycamore", "all-to-all"
min_qubitsintegerproject.qubitsMinimum hardware qubits
required_gatesstring[][]Required gate set (lowercase)
backend_compatibilitystring[]["aer_simulator"]Compatible backends
noise_modelstringNoise model identifier

For variational circuits. Each parameter is an inline table:

[parameters]
theta = { default = 0.785, range_min = 0.0, range_max = 6.283, description = "Rotation angle" }

Fields: default (number), range_min (number), range_max (number, optional), description (string).

Execution context for reproducing results.

FieldTypeDescription
backend_usedstringBackend used for reference results
shots_usedintegerShot count for reference results
seedintegerRandom seed for reproducible simulation
transpilation_levelintegerQiskit transpilation level (0–3)
framework_version_testedstringFramework version used
last_verifiedstringISO date of last successful run

Multi-framework support. Maps framework name to entry point:

[implementations]
qiskit = "circuits/qiskit/main_circuit.py"
pennylane = "circuits/pennylane/main_circuit.py"
FieldTypeDescription
levelstring"beginner", "intermediate", or "advanced"
conceptsstring[]Quantum concepts demonstrated
prerequisitesstring[]Circuit slugs to complete first
learning_outcomesstring[]What the learner will understand
estimated_timestringStudy time estimate (e.g., "45 minutes")
next_circuitsstring[]Suggested follow-up circuits

Reference measurement results for verification.

FieldTypeDescription
dominant_statesstring[]Most probable measurement outcomes
probability_rangenumber[]Expected probability range [min, max]

Academic citations using TOML array-of-tables:

[[references.papers]]
title = "Paper Title"
authors = ["Author, A."]
year = 2014
arxiv = "1411.4028"
doi = "10.1038/..."
[[references.textbooks]]
title = "Textbook Title"
authors = ["Author, A."]
section = "§4.7"

Path overrides for non-standard file locations:

[files]
readme = "README.md"
source = "circuits/main_circuit.py"
params = "params.json"
tests = "tests/"
results = "results/"

Valid values for project.category:

CategoryDescription
entanglementBell states, GHZ, W states
algorithmGrover’s, Shor’s, Deutsch-Jozsa
optimizationQAOA, VQE, variational methods
chemistryMolecular simulation
machine_learningQuantum kernels, QNNs, classifiers
error_correctionSurface codes, repetition codes
communicationTeleportation, superdense coding
cryptographyQKD, BB84, random number generation
simulationHamiltonian simulation, trotterization
transformQFT, phase estimation
utilityHelper circuits, testing primitives
ansatzVariational circuit templates
researchPaper reproductions

  1. project.name must be lowercase, hyphens only, 1–100 characters
  2. project.type must be a recognized type (circuit, dataset, space, benchmark)
  3. project.framework must be one of: qiskit, pennylane, cirq, braket, openqasm3. Only qiskit / pennylane / cirq are executable on the platform today
  4. project.entry_point must reference an existing file in the repository
  5. project.qubits must be a positive integer
  6. execution.default_shots must be 1–100,000
  7. execution.timeout_seconds must be 1–300
  8. execution.entry_function, if present, must match ^[a-z_][a-z0-9_]*$ and must not be a Python dunder, keyword, or builtin
  9. [execution].entry_args is rejected with a parse-time error — use the top-level [parameters] section for per-run inputs instead
  10. project.difficulty must be one of: beginner, intermediate, advanced
  11. schema_version, if present, must be a supported version (currently "1.0.0" — the parser will reject any other value)
  12. hardware.connectivity recommended values: any, linear, grid, heavy-hex, sycamore, all-to-all — unrecognized values produce a warning but are not rejected

metadata.json is auto-generated by the platform from your qubithub.toml. The precedence chain:

  1. qubithub.toml (source of truth — what you author)
  2. Stored metadata.json (generated artifact — what API consumers read)
  3. Database synthesis (fallback for legacy circuits without a manifest)

Never hand-author metadata.json. It will be overwritten on the next push.


Terminal window
# Scaffold a new circuit with a template manifest
qubithub circuits init my-circuit --framework qiskit
# Push validates the manifest before upload
qubithub circuits push
# View the generated metadata
qubithub circuits metadata -f json