CLI Reference
Vaibify provides two equivalent entry points: vaibify and the shorthand
vaib. All commands accept a --config flag to specify an alternate
vaibify.yml path.
Global Options
Flag |
Description |
|---|---|
|
Path to |
|
Port for the hub server. Defaults to the port the last hub used, so a bookmarked tab keeps working; an explicit port is used verbatim and fails loudly if taken |
|
Serve without opening a browser. The process still runs in the foreground until you stop it – this does not make it a daemon |
|
Print the installed version and exit |
|
Show the help message and exit |
When invoked with no subcommand, Vaibify starts in hub mode – a browser-based dashboard for managing multiple projects.
Driving a hub on another machine
vaibify remote compute-machine
vaibify remote researcher@compute-machine
vaibify remote compute-machine --port 18050
Opens one SSH connection, forwards a loopback port, starts or adopts a hub beside your projects on that machine, and opens a signed-in browser tab locally. The remote hub keeps running if your tunnel drops, and a session is held for fifteen minutes so you can come back to it.
Two things to check before the first attempt: both machines need the
same vaibify version, and ssh <host> vaibify --version must print
one – a pip --user install, a virtualenv, or a conda environment
activated by your shell profile is invisible to a non-interactive SSH
command. SSH options themselves belong in ~/.ssh/config.
There is no --project flag: a project name may contain a space, and
the remote command reaches a login shell, so the project is chosen in
the dashboard once the tunnel is up.
See Working on a remote machine for what a dropped connection does to a run and to an open terminal, how the three file actions differ once the backend is elsewhere, and troubleshooting.
vaibify remote-helper is the far-end counterpart. It is invoked by
vaibify remote over SSH and is not meant to be run by hand.
Troubleshooting log
Every CLI invocation attaches a rotating log at
~/.vaibify/vaibify.log (10 MB per file, five backups kept). Warnings
and errors from the hub, the pipeline runner, and the Docker layer land
there, each tagged with the container id it concerns
([cid:<container-id>]), so when something misbehaves the log is the
first place to look. vaibify doctor (below) is the other first stop.
Project Targeting
Note: When you are in a directory containing
vaibify.yml, the--projectflag defaults to that project. When only one project is registered globally, the flag can be omitted entirely. When multiple projects exist,--projectis required unless you are in a project directory. Projects are registered automatically when you runvaibify init.
Project Setup
Host installer agent defaults
The host installer can select which in-container agent CLIs a later
vaibify init enables by default:
sh vaibify/install/installVaibify.sh --agent=OpenCode --install-pi
Accepted provider names are claude, codex, gemini, antigravity,
opencode, cline, openhands, and pi; each also has a matching
--install-<provider> flag.
These choices are defaults only: each new project’s vaibify.yml remains the
authority, and can enable or disable any provider independently.
vaibify init
Create a new project, from a template or from nothing.
vaibify init [--template NAME] [--name NAME] [--minimal] [--force]
Option |
Description |
|---|---|
|
Template name: |
|
Project name; scaffolds without a template when given alone |
|
Smallest config that still builds: no optional features, no extra packages |
|
Overwrite existing configuration files |
With --template, this copies the template’s files and creates
vaibify.yml in the current directory. With --name alone it writes
only vaibify.yml, which is what a script wants:
mkdir myProject && cd myProject
vaibify init --name myProject --minimal
Run with neither option, it lists the available templates and exits.
vaibify register
Register an existing project directory in the global registry so it
can be targeted with --project/-p from any directory. Unlike
vaibify init, this does not create or overwrite any files.
vaibify register [DIRECTORY]
Argument |
Description |
|---|---|
|
Path to the project directory (default: |
The directory must contain a vaibify.yml file.
vaibify setup
Launch the interactive setup wizard in a browser (port 8051). The wizard
walks through configuration fields and writes the result to vaibify.yml.
vaibify setup
vaibify config
Edit, export, or import configuration.
vaibify config edit # Open vaibify.yml in $EDITOR
vaibify config export [-p NAME] <file> # Write current config to a file
vaibify config import <file> # Load config from a file
Container Lifecycle
vaibify doctor
The command to run when something is wrong. It DIAGNOSES and changes
nothing — no container is started, stopped, removed or restarted by any
check it performs. When a finding has a fix vaibify itself can apply,
the finding names the command (see vaibify repair below).
Three scopes:
Scope |
What it examines |
|---|---|
|
This machine: Docker context and endpoint, daemon reachability, the runtime (Docker Desktop / Colima / rootful or rootless Engine), architecture, daemon storage and memory, what vaibify will request against what the daemon has, and room for an environment deposit |
|
Inside the running container: network attachments and default route, the resolver configuration, name resolution compared against this host’s, the effective proxy path, and (with |
|
Vaibify’s own record of the project: journal quarantine, whether the environment envelope pins the image the container runs, workspace ownership, and what the entrypoint observed at the last start |
Four states, and not checked is one of them:
State |
Meaning |
|---|---|
|
Assessed and correct |
|
Assessed, and something is worth acting on |
|
Assessed, and something is broken |
|
Could not be assessed, with the reason. Never counted as |
Every warn and fail names a next step, and the command it names is
correct for the runtime this host is actually using — colima start --profile <yours>, systemctl --user start docker for a rootless
daemon, open -a Docker for Docker Desktop. When the runtime cannot be
identified, doctor says so and names the diagnostic step rather than
guessing at a command that does not apply to your machine.
vaibify doctor [--quiet] [--build] [--start] [--container] [--online]
[--json] [--explain CHECK] [--project/-p NAME]
Option |
Description |
|---|---|
|
Suppress |
|
Run only the build-relevant subset |
|
Run only the start-relevant subset |
|
Run only the checks inside the running container and against this project’s records |
|
Permit connection attempts to the host this project already depends on |
|
Emit the results as JSON instead of a report |
|
Print how one named check decides its answer, and nothing else |
|
Target project name (optional if only one exists) |
With no scope flag, every scope runs. The report ends with an
N ok / M warn / K fail / J not checked summary line.
Exit codes.
Code |
Meaning |
|---|---|
0 |
Everything applicable in the requested scope was assessed, and nothing failed |
1 |
At least one check failed |
2 |
A scope you asked for by name contains a check that could not be assessed |
Code 2 fires for any unassessed applicable check inside an explicitly
requested scope — not only when the whole scope was unassessable.
Without a scope flag nothing is explicitly requested, so a laptop with
no container running does not turn an ordinary vaibify doctor run
non-zero.
What doctor does over the network. By default it resolves exactly one name, and it is a name your project already depends on: your first configured repository’s host, or the API host of the agent provider you enabled. It introduces no third party of its own, and with neither configured it falls back to inspecting the resolver configuration and says so.
Connection attempts happen only with --online, and they follow the
path your project actually uses rather than a fixed one: the port
its remote is reached on (443 for https://, 22 for ssh:// and for
the git@host:path form, 9418 for git://, or whatever the URL
names), TLS only where the transport carries it, and through the
container’s own proxy with a CONNECT when HTTPS_PROXY /
HTTP_PROXY is set and NO_PROXY does not exempt the host. Nothing
vaibify probes is ever authenticated to: no request bytes are sent to
the destination and no Proxy-Authorization is sent to the proxy — a
proxy that answers 407 is reported as exactly that, which is the
diagnosis rather than a thing to work around.
vaibify repair
The acted-on half of vaibify doctor. One subject exists today.
vaibify repair dns [--recreate] [--yes] [--project/-p NAME]
vaibify repair dns clears a container’s stale resolver state. It
reads the resolver configuration first and branches on it, because the
three configurations do not have the same remedy:
a default bridge or Docker’s embedded resolver clears on a restart, so the repair restarts the container;
an explicit
HostConfig.Dnsis baked into the container and no restart can change it. Vaibify never sets that field, so finding one means the container’s specification drifted from its vaibify configuration — introduced from outside vaibify. The repair refuses to restart (which would succeed and change nothing, and read as the fix failing) and points at--recreate, which recreates the container from the vaibify configuration.
A repair tells you what it is about to do before it does it: a restart
re-runs the entrypoint and kills every shell, agent and pipeline step
inside the container. It refuses over live work, naming what is busy;
it routes a restart through the live hub when one owns the
container; it is journaled, so a crash mid-repair reconciles like any
other interrupted operation; and a recreation pins the image
identity the container is running rather than the project’s
latest tag, which may have moved.
A recreation is refused while a vaibify hub holds the container, on both sides. Recreating gives the container a new id, and the hub’s session, workflow cache and file paths are all bound to the old one — so the session would stay authorized and cached against a container that no longer exists. Close the dashboard session for that project and run the command again; it then takes the direct lane.
Afterwards it re-probes and reports the state it actually found.
Code |
Meaning |
|---|---|
0 |
The repair ran and the re-probe confirmed the container resolves names again |
1 |
The repair was refused, failed, or ran and the container still does not resolve |
2 |
The repair ran and nothing was verified — this project names no host vaibify may resolve, or the container could not answer a lookup |
Exit 2 is not a success. It is the command saying it changed something and cannot tell you whether that helped.
vaibify build
Build the Docker image from vaibify.yml and container.conf.
vaibify build [--no-cache] [--project/-p NAME]
Option |
Description |
|---|---|
|
Force a clean rebuild of all layers |
|
Target project name (optional if only one exists) |
vaibify start
Start the container. By default it attaches a terminal and holds the
shell; --detach leaves it running in the background instead, which is
what a script or a CI job needs.
vaibify start [--detach/-d] [--gui] [--jupyter] [--project/-p NAME]
Option |
Description |
|---|---|
|
Start in the background and return |
|
Launch the pipeline viewer after starting |
|
Start JupyterLab inside the container |
|
Target project name (optional if only one exists) |
A detached container runs idle so you can vaibify connect into it; a
COMMAND argument is refused with --detach rather than silently
dropped.
vaibify stop
Stop the running container. The workspace volume persists.
vaibify stop [--project/-p NAME]
vaibify destroy
Delete the project’s workspace volume, after confirming, and then offer to remove the image as well.
Warning
This deletes the workspace volume — every file the container holds that
is not committed and pushed. The volume is the only copy: /workspace
is Docker-managed storage, not a directory on your machine. There is no
--volumes flag to opt in; deleting the volume is what the command
does, and the prompt is the only guard.
vaibify destroy [--project/-p NAME]
Option |
Description |
|---|---|
|
Target project name (optional if only one exists) |
Two things it does not remove: the container itself (stop it with
vaibify stop), and the credential volume, which persists until you
remove it with docker volume rm.
vaibify status
Report the state of the container, image, and workspace volume — and, on request, the project’s PROOF level and everything blocking the next one.
vaibify status [--proof] [--json] [--project/-p NAME]
Option |
Description |
|---|---|
|
Also print the PROOF level and its blockers |
|
Emit environment and PROOF status as one JSON object |
The level and the blockers come from the same gates the dashboard renders, read straight from the container, so no browser and no running hub is needed:
vaibify status --json | python -c \
"import json,sys; print(json.load(sys.stdin)['dictProof']['iProofLevel'])"
One criterion is honestly absent. The dashboard polls file modification
times and therefore also evaluates script-stale; a single read of the
container has no mtime history, so that criterion is not evaluated here.
The payload says which criteria were skipped in
listUnevaluatedCriteria rather than letting the silence read as a
pass.
Working with the Container
These commands work from any directory on the host. If you have multiple
projects, specify which one with --project/-p. If only one project is
registered, the flag can be omitted.
vaibify connect
Open an interactive shell inside the running container.
vaibify connect [--project/-p NAME]
Option |
Description |
|---|---|
|
Target project name (optional if only one exists) |
vaibify push
Copy files from the host into the container workspace.
vaibify push [--project/-p NAME] <source> <destination>
Option |
Description |
|---|---|
|
Target project name (optional if only one exists) |
vaibify pull
Copy files from the container workspace to the host.
vaibify pull [--project/-p NAME] <source> <destination>
Option |
Description |
|---|---|
|
Target project name (optional if only one exists) |
vaibify verify
Run the isolation security audit inside the container. The audit checks for Docker socket access, privilege escalation paths, exposed ports, and mounted secrets.
vaibify verify [--project/-p NAME]
vaibify ls
List files in the container workspace. The path defaults to
/workspace; relative paths are resolved against /workspace/.
vaibify ls [--project/-p NAME] [--json] [PATH]
Option |
Description |
|---|---|
|
Target project name (optional if only one exists) |
|
Emit a JSON array instead of one filename per line |
|
Directory to list (default: |
vaibify cat
Print the contents of a file inside the container. Relative paths are
resolved against /workspace/.
vaibify cat [--project/-p NAME] PATH
vaibify run
Execute pipeline steps inside the container. Without options, runs every
step from the beginning. Use --step to run one step in isolation, or
--from to resume from a specific step. The two are mutually exclusive.
vaibify run [--project/-p NAME] [--step N | --from N]
Option |
Description |
|---|---|
|
Run only step N (1-based) |
|
Run step N and every step after it |
|
Target project name (optional if only one exists) |
Step progress, per-step pass/fail, and pipeline outcome are printed to stdout as the run progresses.
vaibify workflow
Print a summary of the current project, or details for a single step.
Without --step, emits a table of all steps with their last verification
status and run timestamp. With --step N, emits the step’s name,
directory, run flags, and verification block.
vaibify workflow [--project/-p NAME] [--step N] [--json]
Option |
Description |
|---|---|
|
Show details for step N (1-based) only |
|
Emit JSON instead of a human-readable table |
|
Target project name (optional if only one exists) |
vaibify test
Run the test commands attached to one or all pipeline steps. Without
--step, every step’s tests run in order. The exit code is non-zero if
any step’s tests fail.
vaibify test [--project/-p NAME] [--step N] [--json]
Option |
Description |
|---|---|
|
Run tests for step N only (1-based) |
|
Emit JSON results instead of a summary table |
|
Target project name (optional if only one exists) |
vaibify verify-step
Set the user-verification status for a single pipeline step. This is the CLI counterpart to clicking your sign-off row in a step’s Verification section in the GUI: a researcher records their judgment that a step’s outputs look correct (or don’t).
vaibify verify-step --step N --status STATUS [--project/-p NAME]
Option |
Description |
|---|---|
|
Step number (1-based, required) |
|
One of |
|
Target project name (optional if only one exists) |
vaibify generate-standards
Refresh or generate a step’s tests/quantitative_standards.json from
live data files. If a curated standards file already exists, only each
entry’s value is recomputed and the schema is preserved; otherwise a
fresh file is generated from the data files found under the step
directory.
vaibify generate-standards --step-dir PATH [--rtol X] [--detect-stochastic]
vaibify generate-standards --workflow JSON --step-label A09
Option |
Description |
|---|---|
|
Path to a step directory containing |
|
Path to a workflow JSON (alternative to |
|
Step label like |
|
Default relative tolerance when generating a fresh standards file (default: |
|
Scan the step’s |
Reproducibility
vaibify reproduce
Verify a project’s PROOF L3 reproducibility envelope: manifest
integrity, hash-pinned dependency install, pinned container image,
the seven L3 artifact-coherence checks, and — with --rerun — a full
re-run of the workflow with a post-run hash compare and an L3
attestation written to .vaibify/l3_attestation.json.
vaibify reproduce [--repo PATH] [--rerun] [--workflow NAME] [--skip-tier N]
vaibify reproduce --from SOURCE [--workflow NAME] [--prepare | --rerun] [--allow-emulation]
Option |
Description |
|---|---|
|
Path to the project repo (default: current directory) |
|
Also re-run the workflow (tier 5), re-hash its outputs, and write an attestation (default: off) |
|
Name (or container path) of the workflow to re-run; required when the container hosts more than one |
|
Skip tier 1, 2, 3, or 4; may be repeated |
|
Reproduce a published project: stage an exact snapshot of one commit from a clone URL or a clean local clone and validate it as reproduction-ready (six staging rules, not the author’s Level 3 gate). Alone it describes and discards the snapshot. Takes |
|
With |
|
Obtain the image, re-run the snapshot in a shadow container, compare the bytes there, and write a reproduction report under |
|
With |
Exit codes: 0 when every selected tier passed, 1 when any tier
failed, 2 on a usage error (missing required file, malformed
environment.json). The five tiers, the printed output, and the
attestation files are documented in
Reproducibility.
Credentials
vaibify revoke
Remove a stored credential from the local keyring and best-effort revoke it upstream. Supports the three services vaibify pushes to. Prints what was and was not revoked; exits non-zero when the local keyring slot could not be cleared.
vaibify revoke {github|overleaf|zenodo} [--keyring-slot SLOT] [--instance {sandbox|production}]
Option |
Description |
|---|---|
|
One of |
|
GitHub only: per-repo keyring slot to clear (e.g. |
|
Zenodo only: target the |
GUI and Pipeline
vaibify gui
Launch the pipeline viewer in a browser. The port is fixed at 8050 —
there is no --port flag on this subcommand (hub mode, vaibify [--port N], is the invocation that accepts a port). When run without
a project, the landing page opens and displays all registered
containers. Use the + button to add an existing project or create
a new one. See The Dashboard for details.
vaibify gui [--project/-p NAME]
Multiple sessions
Several vaibify instances can run on the same host. Typing
vaibify twice in two terminals does not collide — the second
invocation auto-shifts to the next free port (8051, 8052, …) and
announces the fallback on stderr. Pass --port N to pin an
explicit port. Any given container may be accessed by only one
browser session at a time: the hub landing page greys out
containers already held by another session, a second tab that tries
to open a held container is refused “In use in another browser
session”, and a second vaibify start -p X on the same project
refuses to attach. The exclusivity mechanism — the per-claim lease,
the owner-of-record map, the one-live-connection invariant, and the
release triggers — is specified once in the
architecture reference;
that section is the normative source of truth, including the
holder-payload field table.
The New vaibify window button on the container hub, project
picker, and Admin menu spawns a detached hub on a free port and
opens it in a new browser tab.
Session management
Vaibify hub and viewer servers run in the foreground of the terminal
that launched them. Closing a browser tab does not stop them, and
closing the terminal orphans the server, which keeps holding its
session slot and per-container locks until it is reaped. These
commands let you see and stop live sessions. They are the host-side
analog of jupyter server list and jupyter server stop, and like
those, they run on the host only – they are not invokable from
inside a container.
vaibify sessions
List every live hub and viewer session on the host, with its PID, role, port, start time, and the container(s) it holds.
vaibify sessions
Each line reports pid, role (hub or viewer), port, started
(the ISO start time), and containers (the names locked on that
port). When nothing is running it prints No live Vaibify sessions.
vaibify sessions stop
Gracefully stop a session by PID, or every session with --all.
vaibify sessions stop <PID>
vaibify sessions stop --all
Option |
Description |
|---|---|
|
The session PID to stop (from |
|
Stop every live session except the current one |
Stopping sends SIGTERM, which lets the server run its graceful
shutdown – releasing its session slot and any container locks it
holds. stop refuses any PID that is not a known live Vaibify
session, so it can never signal an unrelated process, and --all
excludes the current session so a session never stops itself.
Dashboard actions from the host: vaibify do
Everything a researcher can do from the dashboard has a name in the
agent-action catalog (vaibify/gui/actionCatalog.py), and every one of
those names is a vaibify do subcommand, generated from the catalog
itself. The CLI therefore cannot drift from the dashboard: a new
dashboard action is a new CLI command, and an action the CLI could not
dispatch fails CI
(testArchitecturalInvariants.py::testEveryCatalogActionHasCliCommand).
vaibify do # list every action, grouped by category
vaibify do <action> --help # one action's arguments
vaibify do run-step A09 # run one step through the dashboard's own path
vaibify do push-to-github \
listFilePaths='["Step/out.csv"]'
vaibify do check-l2-readiness --json
Option |
Description |
|---|---|
|
Target project name (optional if only one exists) |
|
Port of the vaibify session to drive (required when several are live) |
|
Container path of the |
|
Emit one JSON object per line |
|
Print the call that would be made; send nothing |
|
Seconds to wait on the hub (0 disables the limit) |
Path parameters become positional arguments (vaibify do run-test-category A09 sCategory=integrity); request-body fields are
key=value pairs, coerced to numbers, booleans, and JSON by shape. A
whole JSON object also works: vaibify do declare-ai-model '{"sVendor": "...", "sModelId": "..."}'.
A hub must be running. These commands drive the same backend the
browser drives, so the dashboard sees every one of them; they are not a
second, parallel way to change a project. Start one with vaibify in
another terminal.
One session per container still holds. The CLI claims the container’s lease for the duration of one command and releases it afterwards — including when the action fails, so a failed command never strands the claim. A container currently open in a dashboard tab is therefore refused rather than taken over:
Error: Container 'myProject' is held by another vaibify session: In use
in another browser session. Vaibify allows one session per container, so
this command cannot take it from a live dashboard. Either close the
dashboard tab holding it (or release the container from the picker) and
run this again, or run the same action from inside the container with
'vaibify-do', the in-container agent lane, which acts within the session
that is already open.
That is the deliberate answer, not a limitation to work around: taking the container would mean revoking a session someone is working in.
The CLI is the researcher lane. It authenticates exactly as the
browser does — with a per-browser credential — obtaining it headlessly:
it mints a one-time launch capability over the hub’s host control
socket (a 0700 Unix socket, peer-authenticated to the user who
started the hub, unreachable from any container or remote peer) and
redeems it at /api/bootstrap. The bAgentSafe flag in the catalog
governs what a compromised in-container agent may invoke; it does not
restrict the person at their own terminal, so user-only actions like
clean-outputs are available here and are marked in --help.
Publishing
The vaibify publish subcommands are not implemented, and the
publish group is not registered on the CLI at all — vaibify publish
is an unknown command, not a command that reports its own absence. The
sections below describe intended behaviour only.
There is no Settings → Publish pane. This section previously said the
publishing machinery was “already available” through one; it never
existed, and vaibify/reproducibility/githubWorkflow.py — the GitHub
Actions generator behind that claim — has no caller anywhere in the
product. Zenodo archiving is real and reachable, but through the PROOF
Level 2 workflow in the dashboard, not a publish pane.
vaibify publish workflow (coming soon)
Generate a GitHub Actions workflow from project.json and vaibify.yml.
The output will be written to .github/workflows/vaibify.yml.
vaibify publish workflow
vaibify publish archive (coming soon)
Package pipeline outputs and upload them to Zenodo (or the Zenodo sandbox). Will return a DOI on success.
vaibify publish archive