Skip to main content

qcheck

AI writes quantum code. qcheck reviews it.

qcheck is a lightweight review layer for AI-generated Qiskit, OpenQASM, PennyLane and Cirq snippets. It catches common issues early - removed-in-1.0 APIs, unsafe patterns, missing measurements, parse errors - so agents and developers can improve quantum code before it reaches humans, CI, or simulators. Tiny, dependency-free, and it reviews code without ever executing it.

Why it matters: LLMs write quantum code that fails to run 40-70% of the time one-shot (QuanBench+ 2026: Qiskit 59.5% / PennyLane 42.9% pass; QCoder 2026: ~70% one-shot failure). qcheck catches the avoidable share of that early.

qcheck verify circuit.qasm
qcheck verify snippet.py --json

Why this exists

An LLM agent (or a developer pasting from a chat assistant) produces a Qiskit/QASM snippet. Will it run? Is it using an API that was removed in Qiskit 1.0? Does it measure? Is it even safe to touch? Today you find out by running it - wasting time, and in an agent loop, running untrusted model output. qcheck answers in milliseconds, statically.

Install

pip install qcheck-quantum

The PyPI distribution name is qcheck-quantum (the bare qcheck name is taken on PyPI); the installed command and the import package are both qcheck. v0 has zero runtime dependencies (standard library only).

To work on qcheck itself, install from source:

git clone https://github.com/JCQuankey/qcheck && cd qcheck
pip install -e ".[dev]"     # editable install + pytest

Release process: docs/RELEASING.md.

Quickstart

qcheck verify examples/broken_qiskit_execute.py   # one file
qcheck verify examples/                            # a whole directory (recursive)
qcheck verify a.py b.qasm circuits/                # several paths at once
cat snippet.py | qcheck verify -                   # stdin (for agents)

Example output:

qcheck 0.10.1  [FAIL]  examples/broken_qiskit_execute.py  (qiskit)
  [error] QISKIT-REMOVED-IMPORT: 'from qiskit import execute' was removed in Qiskit 1.0
  [warning] QISKIT-DEPRECATED-GATE: QuantumCircuit.cnot() is deprecated; use .cx().
  fix -> Replace execute() with a primitive (Sampler/Estimator) or backend.run().

Reviewing multiple files prints a per-file summary and exits with the worst result found (unsafe > failed > passed). Directory recursion skips virtualenvs, VCS, caches, and build output (.venv, node_modules, .git, site-packages, build, dist, ...) so it reviews your code, not your dependencies. To review a file inside one of those, pass it explicitly.

JSON output (for agents & CI)

qcheck verify snippet.py --json

For a single file, returns {status, framework, syntax_valid, unsafe, static_checks, errors, warnings, suggested_fixes, confidence, runnable_in_simulator, qcheck_version}. For multiple files or a directory, returns an envelope {qcheck_version, results: [<per-file object + "path">...], summary: {files, passed, failed, unsafe, read_errors}}. Designed to be parsed by an LLM agent that just generated the code, or by a CI gate. Exit codes: 0 pass, 1 verification failed, 2 unsafe/unsupported, 3 internal error.

Use it in CI (GitHub Action)

qcheck ships a composite GitHub Action. In your repo's .github/workflows/qcheck.yml:

- uses: actions/checkout@v4
- uses: JCQuankey/qcheck@v0.10.1
  with:
    paths: "."     # or a folder, e.g. "circuits/"

For paths containing spaces, pass one path per line:

- uses: JCQuankey/qcheck@v0.10.1
  with:
    paths: |
      my circuit.py
      openqasm sample.qasm

The step fails the job when qcheck finds errors or unsafe code. See examples/github-action.yml.

SARIF output (GitHub Code Scanning)

qcheck can emit SARIF 2.1.0 so findings show up as code scanning alerts on the Security tab and inline on pull requests, instead of only in the log:

qcheck verify . --format sarif --output qcheck.sarif

In a workflow, generate the SARIF and let the caller upload it (upload needs security-events: write, best granted by the consuming repo):

permissions:
  contents: read
  security-events: write
steps:
  - uses: actions/checkout@v4
  - uses: JCQuankey/qcheck@v0.10.1
    with:
      format: sarif
      output: qcheck.sarif
  - uses: github/codeql-action/upload-sarif@v3
    with:
      sarif_file: qcheck.sarif

SARIF reports static qcheck findings (rule id, level, file, line). stdin input uses a synthetic stdin URI and is not meant for code-scanning upload.

Rule catalog (explain your findings)

qcheck ships 50 rules, and every finding carries a stable rule id (for example QISKIT-REMOVED-IMPORT). Each id is backed by catalog metadata - a title, category, default severity, a plain-language summary, why it matters, and a recommended next step - so a developer or an agent can act on a finding right away and triage faster.

Browse the catalog from the CLI:

qcheck rules            # table: id, level, category, summary
qcheck rules --json     # full metadata, for agents and CI

The same metadata enriches SARIF driver.rules[], so code-scanning alerts show each rule's description, severity and guidance inline. Rule ids are stable across releases, which keeps CI gates and agent loops consistent as qcheck grows.

qcheck's JSON, qcheck rules --json, SARIF and exit codes are documented as stable output contracts for agents and CI in docs/CONTRACTS.md. For agent/CI consumption examples, see docs/AGENTS.md.

What v0 checks

OpenQASM 2/3: missing header, undeclared, duplicate and zero-sized registers, index-out-of-range, malformed measurements, missing measurement, two-qubit gates on a single qubit, OpenQASM 2/3 syntax mismatches, unsupported includes, suspicious non-QASM content. Qiskit Python: Python syntax, missing QuantumCircuit import, zero-qubit circuits, qubit/classical-bit indices out of range, measure() with no classical bits, two-qubit gates on one qubit, missing measurement, get_counts() on an unmeasured circuit, and Qiskit-1.0 breaking changes LLMs still emit (execute(), assemble(), from qiskit import Aer/execute, deprecated gate aliases like cnot->cx).

PennyLane: qml used without import, zero/negative device wires, and QNodes with no return.

Cirq: cirq used without import, cirq.measure() with no qubits, two-qubit gates given the same qubit twice, and empty LineQubit.range(...) calls.

Run qcheck rules to see the full catalog with guidance for each rule.

Suppressing findings in CI

Waive a specific finding on the line it is reported, or disable a rule for a run - both are counted in every output, never silent:

qc.cnot(0, 1)  # qcheck: ignore[QISKIT-DEPRECATED-GATE]
qcheck verify src/ --disable UNSUPPORTED        # skip non-quantum .py files
qcheck verify snippet.py --no-inline-suppress   # agent loops: ignore in-code directives

Safety findings (PY-UNSAFE-*, QASM-SUSPICIOUS) can never be suppressed - inline comments live inside the code under review, so the safety screen cannot be waived from in-band. Details in docs/CONTRACTS.md.

Safety policy

qcheck never executes the input. Qiskit snippets are analyzed with the Python ast module (parse, don't run). Any filesystem/network/process/dynamic- exec construct (os, subprocess, eval, open, ...) marks the snippet unsafe and exits 2. QASM input is text-scanned. This is deliberate: an agent-facing verifier that ran untrusted model output would be a remote-code- execution vector (see Qiskit CVE-2025-2000 for the QPY/pickle precedent). See SECURITY.md for the full threat model.

Scope

qcheck v0 focuses on static review signals for Qiskit and OpenQASM: API usage (including Qiskit 1.0 removals), unsafe patterns, missing measurements, parse issues, and common LLM-generated mistakes. It reviews code without executing it, so it's safe to run on untrusted model output inside an agent loop or CI.

It's a fast first-pass reviewer - pair it with your tests and simulators for the rest. For methodology and scope details, see the leaderboard methodology.

Roadmap

  • v0 (shipped, on PyPI): CLI, Qiskit + OpenQASM static checks, JSON + SARIF output, safety screen, GitHub Action. Zero runtime deps.
  • Shipped since: PennyLane + Cirq static review surfaces, a documented rule catalog (50 rules).
  • Next: more rules per surface, LLM-powered fix suggestions, MCP server (verify_quantum_code), sandboxed simulation (opt-in).
  • Public static-check leaderboard for LLM-generated quantum code (see leaderboard/) + anonymized error dataset.

Leaderboard

qcheck includes a static review benchmark for AI-generated quantum code: it tracks how often model outputs pass qcheck's current review checks (static_pass_rate) on a small public Qiskit/OpenQASM task set - an early quality signal for agents and LLM workflows. The rows shown today are labelled SAMPLE/demo.

Contributing

Issues and PRs welcome - especially new failure fixtures (a real LLM-generated snippet that should fail but currently passes, or vice versa). Each fixture makes qcheck sharper and feeds the public error taxonomy.

Contact

Maintained by JCQuankey / qcheck contributors. qcheck runs locally, sends no telemetry, and reviews code without executing it.

License

Apache-2.0.

Metadata

Release files for qcheck-quantum 0.10.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qcheck-quantum 0.10.1
File Size Uploaded Provenance Actions
qcheck_quantum-0.10.1.tar.gz 57.4 kB With provenance Details for qcheck_quantum-0.10.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qcheck-quantum 0.10.1
File Interpreter ABI Platform Actions
qcheck_quantum-0.10.1-py3-none-any.whl Python 3 none any Details for qcheck_quantum-0.10.1-py3-none-any.whl

Total release size: 98.6 kB

Release files / qcheck_quantum-0.10.1.tar.gz

Download URL qcheck_quantum-0.10.1.tar.gz
Size 57.4 kB
Tags Source
SHA-256 checksum
How to use checksums
586b45a460b9002cb31631fa282aaf5cfc7dbb3a9a5216cefb65b865cbec9067
BLAKE2b-256 checksum
How to use checksums
953f9179b8980e9ae696ba4c38aa7097cd1ad39470f83ceac21fa98ecd933cd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 5, 2026.

Transparency log

Release files / qcheck_quantum-0.10.1-py3-none-any.whl

Download URL qcheck_quantum-0.10.1-py3-none-any.whl
Size 41.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
83af4a93e9d734d007f4885e148b9c41b4a517be48a36da975bf8fc0a6ca2ca2
BLAKE2b-256 checksum
How to use checksums
7bd21bbcf915e59c7ce3f6dfa8994e5d101ccb116cbd48fa1dc3c067baa973c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 5, 2026.

Transparency log

Security for qcheck-quantum 0.10.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for qcheck_quantum-0.10.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page