Command Reference
Thequmod CLI follows standard POSIX conventions:
Global Flags
These flags can be provided to anyqumod command:
Prompts
In a terminal, a command asks for what you didn’t pass instead of failing: which organization or project (picked from a list), which key to revoke, which member to remove, a name or an email. Before something that can’t be undone (keys revoke, members remove, members uninvite) it asks you to confirm,
with No as the default.
With --yes, --json, or no terminal (a script, CI, a coding agent), it never
asks: a missing argument is a usage error (exit code 2), and confirmations are
skipped, as they always were.
Version Warnings
Whenqumod is invoked, it checks if a newer version is available (cached in ~/.qumo/version-cache.json for 24 hours with a 1.5s timeout). Outdated warnings are sent to stderr (in text or as a JSON object with {"warning": "..."} under --json), leaving stdout intact. Set QUMOD_NO_VERSION_CHECK=1 to suppress this check.
qumod login
Initiates the OAuth 2.0 Device Flow to authorize a workstation in the browser.
Usage
Options
-
--api-url <url>: Specify a private control plane or local development cluster. -
--json: Writes one JSON object per line, each with astatus, and does not open the browser:Read stdout line by line: the first line arrives as soon as the code is issued, the second when the sign-in is approved.expires_inon the pending line is the seconds left to approve it.
qumod logout
Ends the qumod login session on the control plane and removes the token from ~/.qumo/config.json. A personal access token is not ended by logout; revoke it in the console.
With --json, revoked says whether the control plane ended the session:
Usage
qumod whoami
Displays the signed-in user, the active organization, the IAM role in it, the API URL, and every organization the user belongs to.
With a personal access token (qumo_pat_…) the control plane does not say whose token it is, so the user is not shown. In --json, auth is "personal_access_token" ("session" after qumod login), user is null, and organization and role are set only when the token’s user belongs to exactly one organization.
Usage
Examples
qumod network
A qumo network you run yourself, for your organization’s dev project. This is how
you use Qumo on the Free plan. (Prod projects use Qumo’s managed relay network
instead; nothing here creates a managed relay.)
start downloads the qumo release the network is
pinned to and checks it. To keep them apart from the rest of your machine, run
qumod itself in a container or VM.
Every subcommand but create acts on the network in the current directory, or
the one --dir <path> names. qumod network help lists the subcommands, the
endpoints and the files.
Subcommands
qumod network create [directory] [--organization <id|name>] [--prefix <path>] [--nodes <list>]
Sets up a network in a new directory. It uses the organization’s dev project
(creating it if there is none), registers a new signing key with it, and writes
the settings of the relay and of the nodes you chose to run beside
it:
start writes each node’s log (.qumod/<node>.log) and run state to .qumod/.
In a terminal, it asks for the directory name, which organization to use if you
belong to several, and which nodes should run beside the relay (a checkbox
list: Space ticks a node, Enter confirms). When you tick rtsp, it also asks
for the camera’s URL. With --yes, --json, or no terminal, it asks nothing
and uses the defaults: the relay alone.
[directory]: where to set up the network. It must be new, or empty apart from files like.git. Default:qumo-network.--organization <id|name>: the organization whose dev project to use. Default: your only organization, or the active one afterqumod login.--prefix <path>: confine the signing key to this path under the project’s root. Default: the whole project.--nodes <list>: the nodes to run beside the relay, comma-separated:hls,rtmp,rtsp-push,rtsp,funnel; ornone. Default: ask in a terminal, otherwise none.
rtsp needs a camera to pull from. Unless you gave one when asked, rtsp.env
holds a placeholder (QUMOD_RTSP_SOURCE=rtsp://SET-YOUR-CAMERA/stream), and
start won’t run rtsp until you set it.
With --json, stdout carries the directory, the project, the registered key,
the nodes and the file paths; the private key itself is never printed.
qumod network start [node...] [-d] [--dir <path>] [--qumo-bin <path>]
Runs the network’s nodes, in this terminal (Ctrl-C stops them) or with -d in
the background. Without arguments it starts them all, the relay first and the
others once the relay answers on /health; name nodes (qumod network start hls) to start only those. A node other than the relay needs the relay running.
In the terminal, each line of output is prefixed with its node ([hls]) when
several run.
The first time, it downloads the qumo release named in network.json into your
cache directory and checks its SHA-256 against the release’s checksums.txt:
If
certs/ holds no certificate, it makes a self-signed ECDSA one for
localhost, 127.0.0.1 and ::1, valid for 14 days, and remakes it after 12; the running nodes then restart, since each reads the certificate only when it starts. Its SHA-256 hash is in
certs/server.crt.sha256, for a browser to pin over WebTransport
(serverCertificateHashes). To use your own certificate, such as one from
mkcert, put it in certs/ and delete
certs/self-signed; qumod then leaves it alone:
-d,--detach: run in the background.--qumo-bin <path>: run this qumo binary instead of downloading the release (also theQUMO_BINenvironment variable).
qumod network stop [node...] [--dir <path>]
Stops the running nodes, the relay last, or only the ones named.
qumod network status [--watch] [--dir <path>]
Shows each node’s state (running, starting or stopped), pid and port, and every
node’s endpoints; for the relay, its uptime, sessions, broadcasts and
subscribers, how many credentials it admitted and refused, its traffic, the
paths it carries, and the certificate’s age. --watch redraws it every 2
seconds; with --json, stdout carries the same as JSON.
qumod network logs [node] [-f] [-n <lines>] [--dir <path>]
Prints a node’s log (.qumod/<node>.log), the relay’s by default. -f follows it; -n sets how many
lines to print (default 100). When the relay refused a credential, it prints a
hint to stderr about what to check.
qumod network token --publish <patterns> | --subscribe <patterns> [--root <path>] [--ttl <duration>] [--key <file>] [--dir <path>]
Signs a test credential with a signing key, for a client to connect with
(?jwt=<credential>). Run it in the network directory, or pass --dir,
and it uses that network’s signing-key.jwk:
TOKEN=$(qumod network token --subscribe /)
works; what it grants goes to stderr. Your app signs its own credentials the
same way, with the key on its server (see Signing Keys).
Flags:
--publish <patterns>,--subscribe <patterns>: what the credential grants, as comma-separated patterns relative to the root:/camis that broadcast,/cam/every broadcast beneath it,/everything. At least one is needed.--root <path>: the directory the patterns are relative to, within the key’s prefix. Default: the key’s prefix.--ttl <duration>: how long it lasts, such as90s,15mor1h. At most1h. Default:15m.--key <file>: the signing key. Default:signing-key.jwk.
--json, stdout carries the credential, its kid, root, patterns and
expires_at.
Endpoints
The relay listens on port 4433 and admits only credentials signed by a key inconfig/keys.json:
The plain-HTTP routes share the relay’s TCP port.
RELAY_ADDR in relay.env
moves them all.
Nodes
Beside the relay, a network can run qumo’s other nodes, each as its own process with its settings in<node>.env, reaching the relay on localhost. Choose them
with create (--nodes); qumod network help lists them too. The ports are
the defaults; each .env file moves its node’s.
<prefix> is the signing key’s prefix (--prefix), the directory these nodes
publish beneath.
- The publishing nodes (
rtmp,rtsp-push,rtsp,funnel) connect to the relay as clients and sign their own credentials withsigning-key.jwk, granting publish beneath the key’s prefix (RELAY_PUBLISH). Those that listen admit only credentials signed by a key inconfig/keys.json, as the relay does.funnelkeeps records in memory, and loses them when it stops, unless you setLEDGER_URIinfunnel.env. - The HLS egress serves a broadcast once something opts it in (below);
players need a credential (
?jwt=). It reads every announcement under/.hls/, which a credential confined to one project can’t grant, so it joins as a relay peer instead:createmakes a local CA (certs/peer-ca.crt) and a peer certificate for it, and points the relay at the CA (CA_FILEinrelay.env, set only when you choosehls).
Serving a stream over HLS
The stream stays at its own path, such as<prefix>/cam. To have the hls
node serve it, announce the same path beneath /.hls/ (/.hls/<prefix>/cam).
That announcement carries no media; it is a pointer, and the egress follows it
to the real broadcast. So publishing a stream and opting it into HLS are
separate rights: the opt-in needs a credential rooted at the key’s HLS mirror,
which your app signs with the same key.
http://localhost:8080/<prefix>/cam/master.m3u8?jwt=<viewer credential>. The playlists carry the credential on to every URL they name.
qumod project
Manage the projects in an organization. Both subcommands take --organization <id|name>. Without it they use your only organization, or, after qumod login, the active one that qumod whoami shows. A personal access token whose user belongs to several organizations must pass --organization.
Subcommands
qumod project list [--organization <id|name>] (alias: qumod project ls)
Lists the organization’s projects.
qumod project create <name> [--env <environment>] [--organization <id|name>]
Creates a project.
--organization <id|name>: the organization to create it in (see above).--env <prod|dev>:produses the managed relay network and needs the Pay as you go or Enterprise plan;devis for a relay you run yourself (one per organization, and every organization starts with one). Default: asked in a terminal; otherwiseprod.
qumod keys
Manage the Ed25519 keys your app signs relay credentials with. See
Signing Keys. Every subcommand takes --project <id>
(from qumod project list).
Subcommands
qumod keys create <name> --project <id> [--prefix <path>] [--out <file>]
Generates a signing key on this machine, registers its public half with the
project, and writes the private key to a file. The private key is never sent
anywhere, and the file is its only copy: keep it on your app’s server.
--prefix <path>: confine the key to this path under the project’s root. Default: the whole project.--out <file>: where the private key is written (owner-only). Default:signing-key.jwk. An existing file is never overwritten, and then nothing is registered.
--json, stdout carries the registered key and private_key_file; the private key itself is never printed.
qumod keys list --project <id> (alias: qumod keys ls)
Lists the project’s keys, newest first, revoked ones included.
qumod keys revoke <kid> --project <id>
Revokes a key. This is final: within about a minute it ends every session the
key admitted, however old. Before rotating, read
Rotation and revocation.
qumod keys export --project <id> [--out <file>]
Writes the project’s active keys as the key set a relay you run trusts (its
QUMO_AUTH_KEYS file), replacing the file in one step. Run it after you create
or revoke a key; a running relay picks the change up within 30 seconds. In a
directory qumod network create made:
--out <file>: where the key set is written. Default:keys.json.
qumod members
Manage who belongs to an organization. Every subcommand takes --organization <id|name>,
resolved as for qumod project. Managing members needs the Organization Admin role (organization.admin).
Subcommands
qumod members list [--organization <id|name>] (alias: qumod members ls)
Lists the organization’s role bindings: its members, and any identities granted an
organization role. Each row’s Binding id is what remove takes.
qumod members invitations [--organization <id|name>]
Lists invitations that have not been accepted yet.
qumod members invite <email> [--role <role>] [--organization <id|name>]
Emails an invitation, valid for 7 days, and prints its link so you can send it
yourself too.
--role <role>: the role the invitee receives, by id (roles/project.editor) or short name (project.editor). The CLI checks it against the organization’s roles before inviting. Default:project.viewer.
qumod members remove <binding-id|email> [--organization <id|name>] (alias: rm)
Takes away a member’s organization role. With an email, the member’s binding is
looked up first; if they hold several roles, pass the binding id instead.
qumod members uninvite <invitation-id|email> [--organization <id|name>]
Withdraws a pending invitation.
qumod usage
Shows usage over time: the organization’s across all its projects, or one
project’s with --project <id>. By hour it covers the last 24 hours; by day,
the last 30 days.
--project <id>: one project’s usage.--metric <name>:gateway.ingress_bytesorgateway.egress_bytes. Default: ingress and egress bytes side by side. Only egress is billed; ingress is shown for information.--granularity <hour|day>: the bucket size. Default:day.--organization <id|name>: the organization, when not--project.
--json,
stdout carries one series per metric with its raw values.
qumod billing
Subcommands
qumod billing summary --project <id> (the default)
Shows the organization’s plan and the current billing period: egress so far (the
billed direction; qumod usage shows ingress too), organization-wide and the
project’s share, and the metered cost (no plan has a monthly fee).
qumod billing invoices [--organization <id|name>]
Lists the organization’s invoices, newest first, with a link to each PDF.
Changing the plan or the payment method happens in the console.
qumod audit
Shows who changed what, newest first: the organization’s audit log, or one
project’s with --project <id>.
--project <id>: one project’s entries.--action <action>: only this action, e.g.project.create.--actor <id>: only entries by this user or identity.--type <resource-type>: only entries about this kind of resource, e.g.project,signing_key,identity,organization.--since <time>,--until <time>: an age such as30m,24hor7d, or an RFC 3339 time.--limit <n>: at most this many entries, up to 1000. Default: 100.--organization <id|name>: the organization, when not--project.
qumod update
Updates the installed CLI to the latest release. It reads
https://dl.qumo-deploy.com/qumod/latest, downloads this platform’s binary,
verifies it against the release’s SHA256SUMS, and replaces the running
executable. A failed download or a checksum mismatch installs nothing, and a
binary that is already the latest is left alone.
--json, stdout carries one object with previous_version, version,
updated (false when it was already latest) and path.
QUMOD_DOWNLOAD_URL points it at a mirror. The install directory must be
writable by your user. On Windows the replaced executable is held until the
process exits; it remains as qumod.exe.old-<pid> and the next update removes
it.
qumod version
Displays the installed CLI version and platform. qumod --version is the same.