Skip to content

Kernel API overview

The Nuclei kernel is a standalone WebSocket service. The desktop frontend is just its first client — anything that can open a WebSocket and speak JSON can parse circuits, run simulations, and submit hardware jobs. This section documents that protocol as a public API.

PropertyValue
URLws://localhost:9742
Port fallbackIf 9742 is taken, the kernel scans upward through 97429761 (range of 20) and binds the first free port
FramingJSON text frames — one request or response object per frame
Max inbound message1 MiB (1_048_576 bytes); larger frames close the connection
HeartbeatWebSocket ping every 30 s; connection dropped after a 20 s pong timeout
AuthNone — the kernel binds to localhost only

Requests on one connection are processed strictly in order: the handler fully finishes (and sends every response for) request N before reading request N + 1. For concurrent work, open multiple connections — each connection gets its own isolated Executor (parse/execute state never bleeds between clients), while hardware state (provider connections, job registry) is shared process-wide.

Terminal window
cd kernel && python server.py

On success the kernel prints exactly one ready line to stdout:

Nuclei kernel ready on ws://localhost:9742

This line is the port-discovery contract: when the default port was taken, the chosen port appears in this line, on its own line, flushed — parse it rather than assuming 9742.

A request does not get a reply. It produces an ordered sequence of response messages on the same connection, ending with a request-specific final message (result for execute, python_result for run_python, snapshot for parse — though a failed parse appends one error after it — and a single reply for every hardware_* request). Streamed output / stderr messages may interleave before the terminal message, so a robust client loops until it sees the terminal type — see client examples.

The canonical example — execute on a Bell circuit produces two messages, snapshot then result:

execute_bell_qiskit.request.json
{
"type": "execute",
"code": "from qiskit import QuantumCircuit\n\nqc = QuantumCircuit(2, 2)\nqc.h(0)\nqc.cx(0, 1)\nqc.measure([0, 1], [0, 1])\n",
"shots": 1024,
"language": "python"
}
execute_bell_qiskit.responses.json
[
{
"type": "snapshot",
"data": {
"framework": "qiskit",
"qubit_count": 2,
"classical_bit_count": 2,
"depth": 3,
"gates": [
{ "type": "H", "targets": [0], "controls": [], "params": [], "layer": 0 },
{ "type": "CNOT", "targets": [1], "controls": [0], "params": [], "layer": 1 },
{ "type": "Measure", "targets": [0], "controls": [], "params": [], "layer": 2 },
{ "type": "Measure", "targets": [1], "controls": [], "params": [], "layer": 2 }
]
}
},
{
"type": "result",
"data": {
"state_vector": [
{ "re": "<approx:0.70710678:0.0000001>", "im": "<approx:0:0.0000001>" },
{ "re": "<approx:0:0.0000001>", "im": "<approx:0:0.0000001>" },
{ "re": "<approx:0:0.0000001>", "im": "<approx:0:0.0000001>" },
{ "re": "<approx:0.70710678:0.0000001>", "im": "<approx:0:0.0000001>" }
],
"probabilities": {
"00": "<approx:0.5:0.000001>",
"11": "<approx:0.5:0.000001>"
},
"measurements": "<any>",
"bloch_coords": [
{ "x": "<approx:0:0.000001>", "y": "<approx:0:0.000001>", "z": "<approx:0:0.000001>" },
{ "x": "<approx:0:0.000001>", "y": "<approx:0:0.000001>", "z": "<approx:0:0.000001>" }
],
"execution_time_ms": "<any>",
"shot_count": 1024,
"metrics": {}
}
}
]

Values like "<any>" and "<approx:0.5:0.000001>" are matcher markers, not protocol values: every example in this section is a fixture file that the kernel test suite replays against the real handler (kernel/tests/test_docs_fixtures.py), and markers absorb nondeterminism (sampled counts, timings). The shapes and orderings you read here are machine-checked on every CI run.

Request typeTerminal responseReference
parsesnapshot (an error follows it on failure)Execution messages
executeresultExecution messages
run_pythonpython_resultExecution messages
environmentenvironmentExecution messages
hardware_connecthardware_connectedHardware messages
hardware_set_credentialshardware_connectedHardware messages
hardware_clear_credentialshardware_connectedHardware messages
hardware_connected_providershardware_connected_providersHardware messages
hardware_list_jobshardware_jobsHardware messages
hardware_list_backendshardware_backendsHardware messages
hardware_submithardware_job_submittedHardware messages
hardware_statushardware_job_updateHardware messages
hardware_resultshardware_resultHardware messages
hardware_cancelhardware_job_cancelledHardware messages

Any other type (and any frame that is not valid JSON) produces a bare error message — see errors. Payload schemas are in schemas. The TypeScript mirror of the whole protocol — the types the frontend itself compiles against — lives at src/types/quantum.ts.