Running an application: vericue run
vericue run starts your Qt application with the veriCue Runtime already inside it. One command, no code changes, no rebuild, no linking:
vericue run ./your-qt-app
# VERICUE_ENDPOINT=/run/user/1000/vericue/vericue-4213.sockThat endpoint is a live veriCue server inside your application, exposing its object tree over the protocol with the full command surface - interaction, screenshots, model/view access, subscriptions, recording. Drive it with any client:
vericue --endpoint /run/user/1000/vericue/vericue-4213.sock list_objectsThis is the front door. It is deliberately the only thing you need to know: which mechanism gets the Runtime into the process, which probe matches your Qt, what has to be on LD_LIBRARY_PATH - all of that is the command's business, not yours.
Not serverless
veriCue Runtime code runs inside your application process. That is what makes full QObject / QWidget / QQuickItem introspection possible. vericue run changes how the Runtime gets there, not where it runs.
Install
vericue run ships with the Python client, which is where the vericue command lives:
pip install vericueThe Runtime it loads into your application comes from the platform package - see Installation. Keep that package's bin/ and lib/ together; put bin/ on $PATH, or point VERICUE_HOME at the package root:
export VERICUE_HOME=/opt/vericue
vericue run ./your-qt-appIf the package cannot be found, the command says so and lists every path it tried rather than failing somewhere inside your application.
Where it works today
| Supported | |
|---|---|
| Linux x64 | yes - dynamically linked Qt 5.15 / Qt 6 applications, Widgets and Qt Quick; local IPC by default, TCP on --port |
| Windows x64 | yes - dynamically linked Qt 5.15 / Qt 6 applications, Widgets and Qt Quick; TCP only. Uses a launch-time DLL load that endpoint security can block - read Windows launch path first |
| macOS | no - the hardened runtime blocks loading code into another process; embed |
The exact Linux compatibility envelope, and every case that is refused, is in Zero-source-change runs. On Windows the envelope and the security implications are in Windows launch path. vericue run uses each platform's preflight: there is one compatibility model per platform, and the command asks it before starting anything.
Windows uses TCP and a DLL-injection technique
On Windows the default transport is TCP (local IPC is not available), and the Runtime is loaded with CreateRemoteThread + LoadLibraryW, which antivirus and EDR products may block. This is a real constraint, not a footnote - see Windows launch path before relying on it in CI or on a managed fleet.
On an unsupported platform vericue run says so before starting anything and names the embedding fallback. Embedding is not a downgrade - it is the setup that works everywhere, can be compiled out of release builds, and is the recommended one for CI.
What Qt your application needs
The Runtime uses your application's Qt. veriCue does not put a second Qt into your process, and you should never copy veriCue's Qt libraries into your deployment to make injection work - two QtCore builds in one process abort on sight. (The Inspector is a different matter: it is a separate application, and its package carries its own Qt for its own process.)
That makes the Runtime's Qt modules a prerequisite your deployment has to satisfy:
| Module | Needed | Why |
|---|---|---|
| Qt Core | always | everything |
| Qt Gui | always | screenshots, the QPA boundary, input events |
| Qt Network | always | the Runtime's TCP transport, and licence checks |
| Qt Widgets | only if your application uses it | the Widgets backend is a separate plugin, loaded only when the module is already in your process |
| Qt Quick | only if your application uses it | likewise, a separate plugin - this is the module a QML application already has |
| Qt Qml / Qt QmlModels / Qt OpenGL | only if your application uses Qt Quick | Qt Quick is built on them, so an application that has Quick already has these. They are listed because the macOS build records them explicitly, and this table is checked against the shipped binaries rather than written from memory |
Qt Network is required even if your application never uses it
This is the one that surprises people. The Runtime links Qt Network for its own transport, so a deployment trimmed down to Core and Gui - common for a kiosk or an embedded target - cannot host the injected Runtime until QtNetwork is present. It is not optional and there is no build of the Runtime without it.
The two toolkit backends are independent. A Widgets application does not need Qt Quick installed because veriCue is injected, and a QML application does not gain a QtWidgets dependency. Each backend is loaded only after the Runtime finds that module already mapped in the process, which is also why a pure QML application never pulls QtWidgets in.
Check before you run
vericue run --check ./your-qt-appvericue-inject: preflight OK
target ./your-qt-app (ELF64 x86-64)
target Qt 6.7.1 [/opt/qt/6.7.1/lib/libQt6Core.so.6]
toolkits quick
probe /opt/vericue/lib/libvericue-inject.so
probe build veriCue 0.4.0, Qt 6.7.1
runtime /opt/vericue/lib
plugins libvericue-widgets.so libvericue-quick.so
transport local IPC (auto, announced as VERICUE_ENDPOINT)
docs https://vericue.dev/docs/guides/injectorThe report comes from the shared preflight, which is why it names the mechanism (vericue-inject on Linux). This is the first thing to attach to a support request.
Passing arguments to your application
Everything after -- belongs to your application and reaches it unchanged, including further -- and anything that looks like a veriCue option:
vericue run ./your-qt-app -- --config prod.ini --verbose# --port here is your application's, not veriCue's
vericue run --port 4242 ./your-qt-app -- --port 8080vericue inspect takes the tail the same way, because it starts your application too:
vericue inspect ./your-qt-app -- --config prod.iniExit status and Ctrl-C
On Linux, vericue run does not sit between you and your application: it replaces itself with the application process. So there is nothing to explain:
- the exit status you see is the application's own;
- Ctrl-C reaches the application, because it is the foreground process;
- an application killed by a signal is reported by your shell the usual way (
128 + signo), because it really did die that way.
vericue run ./your-qt-app -- --selftest; echo "exit $?"On Windows there is no execve that replaces the running image, so vericue run starts vericue-inject.exe, which starts your application and supervises it. The outcome you rely on is the same - the exit code you see is the application's own, and Ctrl-C reaches the application because it shares the console - but there is a supervising process in the chain rather than a single replaced one.
A vericue run that refuses to start exits 1 and explains why on stderr, before your application has been started at all.
Transports
Local IPC is the default for same-host runs: a user-private UNIX socket with no network presence at all. The endpoint is announced on stdout as VERICUE_ENDPOINT=<path>.
The endpoint, without reading stdout
In CI you usually do not want to scrape the application's output. --announce writes the endpoint to a file of your choosing, before the application starts:
vericue run --announce /tmp/ci/vericue.endpoint ./your-qt-app &
# /tmp/ci/vericue.endpoint contains: VERICUE_ENDPOINT=/tmp/ci/vericue.endpoint.sockThe file names where the endpoint will be, so wait for the socket itself before connecting:
ENDPOINT=$(sed -n 's/^VERICUE_ENDPOINT=//p' /tmp/ci/vericue.endpoint)
for _ in $(seq 1 60); do [ -S "$ENDPOINT" ] && break; sleep 0.5; done
vericue --endpoint "$ENDPOINT" pingPut the announce file in a directory only you can read. The socket beside it is always created owner-only, but a world-readable directory lets other users on the machine see that it exists - $XDG_RUNTIME_DIR is the obvious place, and the Runtime says so on stderr when the directory is more open than that.
--announce needs an endpoint that is knowable up front, so it pins one:
| what you passed | what is announced |
|---|---|
| nothing | VERICUE_ENDPOINT=<announce file>.sock - the launcher pins that path |
--endpoint PATH | VERICUE_ENDPOINT=PATH |
--port N (N > 0) | VERICUE_PORT=N |
--port 0 | refused: the port is chosen by the OS inside the application, so read the VERICUE_PORT=<n> line from stdout instead |
TCP
TCP is an explicit opt-in, because it is reachable from other hosts:
vericue run --port 4242 ./your-qt-app
vericue --port 4242 list_objects--port 0 lets the OS pick a free port, announced on stdout as VERICUE_PORT=<n>. --port and --endpoint are mutually exclusive.
TCP is plaintext on all interfaces
It is unauthenticated unless you also pass --token. See Transports for the full comparison.
Authentication and licensing
Identical to an embedded Runtime, because it is the same Runtime configured the same way:
vericue run --token s3cret --license /etc/vericue/license.json ./your-qt-app| Flag | Embedded equivalent |
|---|---|
--token T | setAuthToken("T") |
--license FILE | setLicenseFile("FILE") |
--license-server HOST:PORT | setLicenseServer(...) |
With none of them the run is a trial, exactly as for an embedded server that was never given a license. The licensed concurrent-session budget is one budget and is shared across transports; starting an application this way does not widen it. A licensing configuration you asked for and that cannot be applied refuses the run rather than quietly degrading to a trial - details in Authentication and licensing.
Options
| Option | Effect |
|---|---|
--endpoint PATH | pin the local IPC endpoint |
--port N | expose TCP on port N instead of local IPC (0 picks a free port) |
--token TOKEN | require this token in the client handshake |
--license FILE | load an RSA-signed license file |
--license-server HOST:PORT | check a session out of a floating license server |
--announce FILE | write the endpoint announcement to FILE before starting |
--check | run the compatibility checks, report, and exit |
--no-preflight | skip the compatibility checks (support will ask why) |
Environment: VERICUE_HOME (platform package root), VERICUE_INJECT (absolute path to the launch helper, overriding the search).
A CI job
set -euo pipefail
vericue run --check ./your-qt-app # fail fast on a bad runner
QT_QPA_PLATFORM=offscreen vericue run \
--token "$VERICUE_TOKEN" \
--announce "$PWD/vericue.endpoint" \
./your-qt-app > app.log 2>&1 &
APP=$!
ENDPOINT=$(sed -n 's/^VERICUE_ENDPOINT=//p' "$PWD/vericue.endpoint")
for _ in $(seq 1 60); do [ -S "$ENDPOINT" ] && break; sleep 0.5; done
[ -S "$ENDPOINT" ] || { cat app.log; exit 1; }
VERICUE_ENDPOINT="$ENDPOINT" pytest tests/See CI integration for the full picture.
Relationship to vericue-inject
On Linux, vericue run starts your application through vericue-inject, which owns the compatibility model: the preflight, the probe selection and every refusal message. vericue-inject remains a supported, documented interface - use it directly when you want the mechanism in front of you, or when you have no Python available on the machine that starts the application. Its guide is Zero-source-change runs.
The two are not alternatives with different capabilities. vericue run is the stable command; the mechanism behind it is free to differ per platform without your scripts changing.

