Skip to main content

Verify LLM-generated quantum code (Qiskit / OpenQASM) statically and safely.

Project description

qcheck

AI writes quantum code. qcheck reviews it.

qcheck is a lightweight review layer for AI-generated Qiskit, OpenQASM and PennyLane 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.8.0  [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.8.0
  with:
    paths: "."     # or a folder, e.g. "circuits/"

For paths containing spaces, pass one path per line:

- uses: JCQuankey/qcheck@v0.8.0
  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.8.0
    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 46 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.

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

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.
  • Next: PennyLane + Cirq, more rules with a documented rule catalog, 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qcheck_quantum-0.8.0.tar.gz (46.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qcheck_quantum-0.8.0-py3-none-any.whl (34.1 kB view details)

Uploaded Python 3

File details

Details for the file qcheck_quantum-0.8.0.tar.gz.

File metadata

  • Download URL: qcheck_quantum-0.8.0.tar.gz
  • Upload date:
  • Size: 46.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qcheck_quantum-0.8.0.tar.gz
Algorithm Hash digest
SHA256 b27bcc0c745f7e7d3b51f4af13ced9fd5e38f6dd162180d628ae638006e26091
MD5 32dd0b783b80d7438490ecaa8b3e2ae5
BLAKE2b-256 b6d3d226aa73b354d2e0595bf61b844884a89b7f7bd7c22ac8ee9615bd87c9a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for qcheck_quantum-0.8.0.tar.gz:

Publisher: release.yml on JCQuankey/qcheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qcheck_quantum-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: qcheck_quantum-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 34.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qcheck_quantum-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 387a4d33629c01cee99123c099cc42eaf5dfd66eff8f4b839971da4a56e9d026
MD5 80efeffaf7f0dd9b340d95ca02358e1c
BLAKE2b-256 dd9e51707e75fa44169fa4e50414082e2e083f7486feb4ddb67d51e5c2da69e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for qcheck_quantum-0.8.0-py3-none-any.whl:

Publisher: release.yml on JCQuankey/qcheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page