Command line reference

Read this if you run laidline commands and need the exact options, defaults and exit codes. You will find every command, grouped as the CLI groups them, with its options and one example. Skip if you want a first marked image (Quickstart) or a configuration key (Configuration). Time: 2 minutes to find a command. Needs: pip install laidline (the server, ingest, kms and evidence extras for the commands that name them).

In short

  • laidline --help lists the eight commands and seven command groups below; laidline GROUP --help lists a group's commands.
  • Every command that reads a configuration takes --config FILE, else LAIDLINE_CONFIG, else ./laidline.yaml, else /etc/laidline/config.yaml.
  • laidline serve binds 127.0.0.1:8080 unless you pass --host.
  • A command that fails prints error: <reason> on stderr and exits 1, unless its section names another code.
  • laidline bench needs the separate laidline-bench package.

Check your install with laidline --version, which prints the version and exits. The other global options are --install-completion and --show-completion, which install or print shell completion for your current shell.

laidline --version
1.0.1

Before you use a command

  • Configuration. laidline init writes the file the other commands read. See Configuration for every key.
  • Model weights. Marking and detecting images, audio and video download their pinned weights on first use into $LAIDLINE_HOME/models. laidline models fetch does it ahead of time.
  • Errors. A failed command writes one line, error: <reason>: <detail>, to stderr. The exit code is 1 unless the command's section lists another.

Commands at a glance

Command What it does
laidline init Write a starter configuration, a payload key and a development certificate chain
laidline serve Run the HTTP sidecar
laidline ingest Run the storage-hook worker
laidline mark Mark one image, audio or video file
laidline detect Grade a file
laidline verify-result Check a signed detect result offline
laidline bench Run a watermark robustness benchmark
laidline register Register this deployment with the issuing service
laidline keys Signing keys and certificates: dev-cert, csr, rotate, list
laidline evidence Export and verify evidence: export, verify, check-slots, init-db
laidline models Download model weights: fetch
laidline payload-keys Watermark payload keys: generate, list, fingerprint, retire
laidline licence Licences: fetch, install, status
laidline issuer Issuer certificate and directory snapshot: install, refresh
laidline usage Usage statement and the monthly usage report: usage, usage report

The --config FILE option (environment variable LAIDLINE_CONFIG) is left out of the option tables below. Every command that reads a configuration takes it.

init

laidline init [OPTIONS]

Writes a starter laidline.yaml, a payload key file payload-k1.key (mode 0600) and, unless you pass --no-certs, a development certificate authority and signing certificate in ./certs/. It draws a random trial issuer number. It refuses to overwrite an existing file.

Option Default Meaning
--path FILE laidline.yaml The configuration file to write
--system-name TEXT my-ai-system Your AI system's name (system.name)
--system-version TEXT 1.0 Its version (system.version)
--org TEXT Example Org Organisation for the development certificate and the evidence log
--certs / --no-certs --certs Also write a development certificate chain

Example:

laidline init --system-name my-image-model --org "Yourcompany Inc"
wrote laidline.yaml and ./certs/ (development only; use your KMS and a C2PA trust-list certificate in production)
One usage report a month (counts only, no media) is sent to your issuer; set issuer.usage_report: false to turn it off
issuer 35443 is a trial number, so marks are shared marks (grade D, provider not identified).
laidline register --email <you@yourdomain> --display-name "<Your Company Inc>" --plan registered_free gets a registered number, a private key bound to your name and attributable marks (https://laidline.com/docs/licensing).

Your trial number differs: it is random. The development certificate is for trying Laidline out. Production uses your KMS and a certificate from the C2PA trust list (Certificates).

serve

laidline serve [OPTIONS]

Runs the sidecar: the native mark and detect routes, the OpenAI-compatible proxy, health checks and metrics. Every route is in the HTTP API reference. It needs the server extra.

Option Default Meaning
--host TEXT 127.0.0.1 The address to bind. 0.0.0.0 listens on all interfaces
--port INTEGER 8080 The port to bind

The default bind is loopback only. To reach the sidecar from other hosts, pass --host 0.0.0.0 (the Docker entrypoint does) and set server.mark_token_env so the mark routes need a bearer token (HTTP API reference). The start-up log names the bind:

laidline serve
2026-10-26 08:55:52,623 INFO laidline.cli listening on 127.0.0.1:8080 (loopback only)
...
INFO:     Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)

laidline serve exits 1 with error: <reason> when the configuration is invalid. curl localhost:8080/readyz reports whether the start-up self-test mark succeeded.

ingest

laidline ingest [OPTIONS]

Runs the storage-hook worker against the configured S3 with SQS, R2 with Queues or local directory source. It needs the ingest extra. See S3 and SQS for the setup.

Option Default Meaning
--max-batches INTEGER run forever Stop after this many polls

Example:

laidline ingest --max-batches 1

The command polls the source once and exits.

mark

laidline mark [OPTIONS] PATH

Marks one image, audio or video file: the watermark, the Content Credentials where the container carries them, and an evidence entry. The bytes decide the kind of file; the extension only settles what they cannot. Audio keeps its container unless you name another with --fmt. Raw PCM has no sample rate, so the command refuses it. Video (MP4 or MOV) is written as MP4.

Option Default Meaning
--out FILE NAME.marked.EXT beside the input Where to write the marked file
--fmt TEXT the input's format The output format, for example png, jpeg or mp3

Example:

laidline mark photo.png
{
  "out": "photo.marked.png",
  "asset_id": "ast_01M5W4M2TAEKG2PCHJYP8XRGH6",
  "manifest_id": "urn:c2pa:ee943d64-d701-4dba-ae20-3a1bae7430f4",
  "entry_hash": "c58129c5820548902596507903dc23cd61f6a02a3ad5dac6d43b20691dce248e",
  "warnings": []
}

If the timestamp server does not answer, the command exits 1 and the message says to set signing.tsa.required: false or point signing.tsa.url at a server this host can reach (Production setup).

detect

laidline detect [OPTIONS] PATH

Prints evidence-graded detection for a file. It never asserts human origin: a result of none means no signal was found, not that a person made the file. The grades are in Grading.

Option Default Meaning
--json off Print the full laidline.detect/1 result as JSON
--text off Treat the file as UTF-8 text and check the text watermark
--model TEXT none The tokenizer id, or a local directory, for --text
--confirm off Ask the checker the signed directory lists for the file's issuer, and verify its signed reply
--save-result FILE none With --confirm: write the checker's signed reply to this file

Example:

laidline detect photo.marked.png
verdict: marked_by_this_system   grade: A
  c2pa       present=True grade=A status=valid_trusted
  watermark  present=True grade=D status=shared mark
             issuer: shared mark, provider not identified
  note: Absence of a signal is not evidence that content is human-made.
  note: Revocation status was not checked (OCSP disabled in this deployment).

The command exits 0 whatever the grade. With --confirm it exits 0 only when the issuer's checker confirmed the mark in this file. Keep the signed reply with --save-result reply.json and check it later with verify-result.

verify-result

laidline verify-result [OPTIONS] RESULT.json --file FILE

Checks a signed detect result, a checker's reply, offline. The signing key must be one the signed directory binds to the issuer the result names, the signature must verify, and the statement must be about FILE and name that issuer's checker. It prints the issuer line and exits 0 when the signature verifies (confirmed or not), 1 otherwise.

Option Default Meaning
--file FILE required The file the result is about; its SHA-256 must match the statement
--directory FILE the configured snapshot, else the shipped one A directory snapshot file to check against

Example:

laidline verify-result reply.json --file photo.marked.png
verify-result: confirmed by issuer 1234 (Example Org, operator of example.org) at https://example.org/detect on 2026-10-26T09:12:44Z
verify-result: verdict marked_by_this_system, grade B, tier public, issued 2026-10-26T09:12:44Z

The issuer number, name and times are those in your result. Other issuer lines are listed in Grading. A result that carries no signature prints verify-result: unsigned result; it is not a confirmation and exits 1. Unreadable inputs exit 2.

bench

laidline bench [OPTIONS] [SUITE]

Runs a watermark robustness benchmark on your own media: embed, transform and decode for image, audio and video; generate, transform and detect on a C4 shard for text. It needs the separate laidline-bench package (pip install laidline-bench). Without it the command prints laidline bench needs the laidline-bench package: pip install laidline-bench to stderr and exits 2. Benchmarks lists the suites and the figures each one reproduces.

SUITE is image (TrustMark), audio (AudioSeal), video (VideoSeal and the keyframe scheme) or text (SynthID and KGW). The default is image.

Option Default Meaning
--corpus DIR none A directory of unmarked media; for text, a C4 shard or a JSON-lines file
--n INTEGER 50; 20 for video and text Images, clips or prompts to sample (seeded)
--workers INTEGER 2 Worker processes, each with its own watermark models
--modes TEXT both Audio only: batch, streaming or batch,streaming
--transforms TEXT the suite's set Comma-separated transform names, or all
--out FILE SUITE-robustness-DATE.json Where to write the JSON result
--device TEXT the harness's own cpu, cuda or auto (video also cuda:N); for text, where the generating model runs while detection stays on the CPU
--schemes TEXT both Video only: videoseal, trustmark_keyframes or both
--model TEXT none Text only: the generating model, a Hugging Face id or a local directory
--music-bed FILE none Audio only: the music file the music_bed_10db transform mixes in (the row is not run without one)
--sweeps / --no-sweeps image off; video and text on; audio on the first --sweep-n clips Run the parameter sweeps
--sweep-families TEXT all Image and video only: comma-separated sweep families
--sweep-n INTEGER the harness's own How many items of the sample run the sweeps
--resume off Continue the interrupted run checkpointed next to --out (same arguments)
--gen-batch INTEGER 1 on CPU, 8 on CUDA Text only: prompts per generate call

Example:

laidline bench image --corpus ./photos --n 50 --out image-run.json

The command embeds, transforms and decodes 50 photos and writes the per-transform results to image-run.json.

register

laidline register --email ADDRESS --display-name NAME [OPTIONS]

Registers this deployment with the issuing service. Registration gets a registered issuer number, a licence and an issuer certificate bound to your signing key and the active payload key. A free plan issues once you follow the link in the email; Laidline verifies and installs the documents, then prints a summary. Plans and prices are at https://laidline.com/licensing.

You must accept the Laidline Customer Licence Agreement: pass --accept-terms, or answer y at the prompt on a terminal. The acceptance is signed into the request.

Option Default Meaning
--email ADDRESS required An address at your organisation's domain; it receives the link
--plan TEXT registered_free registered_free, lite, starter, growth or scale
--interval month|year month How a paid plan is billed. A free plan accepts it and ignores it (a free licence runs 12 months)
--display TEXT public Always public: the directory shows your name and domain beside your number
--display-name TEXT required The public name; it must contain your verified domain's label, as Acme Inc does for you@acme.com. The command stops before sending anything when it is missing
--country TEXT none ISO 3166-1 alpha-2 country code
--detect-url URL none Your public /detect URL (https)
--disclosure-url URL none Your AI disclosure page (https)
--name TEXT system.provider_legal_name Your legal name
--usage TEXT none A note on your intended use, sent in the request
--accept-terms off Accept the Laidline Customer Licence Agreement
--wait / --no-wait --wait Wait for the email link to be followed
--timeout TEXT 30m How long to wait: 90s, 30m, 2h

Example:

laidline register --email you@yourcompany.com --display-name "Yourcompany Inc" --accept-terms
check you@yourcompany.com for the link (registration reg_...)
waiting for the link to be clicked
...
installed /var/lib/laidline/licence/licence-....json
licence ...: plan registered_free, valid until 2027-10-26
issuer 1234: display public as Yourcompany Inc
issuer: registered 1234 as Yourcompany Inc
reload: send SIGHUP to laidline serve or restart it

Your registration id, issuer number and dates differ.

If the command stops waiting before you follow the link, it prints resume with: laidline licence fetch REGISTRATION_ID; run it with laidline licence fetch. A running laidline serve picks up the new documents on SIGHUP or restart.

The issuing service hands out the documents only with a documents proof signed by the signing key the registration binds (the documents proof): register, licence fetch and automatic renewal sign a new one with the active signing key for each fetch. A rotated key must be bound, by running register again, before it can fetch.

keys

Signing keys and certificates. dev-cert, csr and rotate take the same options to name the key they act on.

Key selection options

Option Default Meaning
--key-path FILE none A local EC P-256 private key (PEM). Development only
--kms-key-id TEXT none An AWS KMS key (key spec ECC_NIST_P256)
--region TEXT $AWS_DEFAULT_REGION The AWS region of the key
--vault-key TEXT none A Vault or OpenBao Transit key (type ecdsa-p256)
--vault-addr TEXT $VAULT_ADDR The Vault or OpenBao address
--vault-mount TEXT transit The Transit mount path
--vault-key-version INTEGER the latest The Transit key version (1 or higher)
--vault-namespace TEXT none The Vault Enterprise namespace (hvac ignores VAULT_NAMESPACE)
--vault-ca-cert FILE none A CA bundle (PEM) that Vault's TLS certificate chains to, for private CAs
--vault-token-env TEXT VAULT_TOKEN The environment variable that holds the Vault token

keys dev-cert

laidline keys dev-cert [OPTIONS]

Mints a development certificate authority and signing certificate. Validators report "valid, not trusted" unless you load the authority as an anchor. With a key selection option the certificate covers that key and no private key file is written.

Option Default Meaning
--out-dir DIR ./certs Where to write dev-chain.pem, dev-ca.pem and, without a key option, dev-key.pem
--org TEXT Example Org Organisation (O) of the certificate and the authority
--cn TEXT laidline dev Common Name (CN) of the certificate

Plus the key selection options.

laidline keys dev-cert --out-dir ./certs2 --org "Example Org"
wrote ./certs2/dev-key.pem, dev-chain.pem, dev-ca.pem

keys csr

laidline keys csr --out FILE --org TEXT --cn TEXT [OPTIONS]

Creates a certificate signing request (CSR) for a certificate authority on the C2PA trust list. The key itself signs the request (KMS, Vault Transit or a local key; the default is the configured signing key). Only the public key leaves the KMS or Vault. See Certificates for what to send the authority.

Option Default Meaning
--out FILE required The CSR (PEM) to write
--org TEXT required Organisation (O); C2PA validators need it in the certificate subject
--cn TEXT required Common Name (CN)
--country TEXT none Country (C), a two-letter code
--eku email|document-signing|both email The requested ExtendedKeyUsage: emailProtection, id-kp-documentSigning (1.3.6.1.5.5.7.3.36) or both
--force off Overwrite --out

Plus the key selection options.

laidline keys csr --kms-key-id arn:aws:kms:<region>:<account>:key/<id> --out signing.csr \
  --org "Example Org" --cn "Example Org image service"

The command writes signing.csr; the private key never leaves the KMS.

keys rotate

laidline keys rotate --id TEXT --backend BACKEND --cert-chain FILE [OPTIONS]

Adds a signing key to the file named by signing.keys_file and reloads the server. It checks the chain against the key at --not-before, appends the entry under a lock with an atomic replace, prints the keyring, then reloads the server with --pid or --admin-url. A new file is seeded with the current key as id default.

Option Default Meaning
--id TEXT required The new key's id: letters, digits, ., _, -
--backend local|aws-kms|vault-transit required The key's backend
--cert-chain FILE required The new key's certificate chain (PEM, leaf first)
--not-before ISO now When the new key takes over
--retire-previous-at ISO none Set not_after on the key that is active now
--pid INTEGER none Send SIGHUP to this laidline serve process afterwards
--admin-url URL none POST URL/admin/reload afterwards, with the bearer token from admin.token_env
--dry-run off Validate and print the result; write nothing

Plus the key selection options.

--admin-url must be an https URL, or http to localhost, 127.0.0.1 or ::1. The admin token travels in the request, so the command refuses plain http to any other host and exits 2.

laidline keys rotate --id k2 --backend aws-kms --kms-key-id arn:aws:kms:<region>:<account>:key/<id> \
  --cert-chain k2-chain.pem --pid 4242

keys list

laidline keys list [OPTIONS]

Lists the configured signing keys with their status now. It reads the configuration only and makes no KMS or Vault call.

Option Default Meaning
--json off Print the rows as JSON
laidline keys list
id       backend  ref                        not_before  not_after  status  cert_sha256
default  local    local:./certs/dev-key.pem  -           -          active  c9ae231262dee584d865e87d688aab8a0b6fba06592b9df211cc5cd69b5f9b99

evidence

Evidence log export and verification. See Evidence for what a bundle holds.

evidence export

laidline evidence export --out FILE [OPTIONS]

Exports an evidence bundle (a zip). It holds the log, the checkpoints, the certificates, the compliance texts, a signed manifest, a standalone verify.py and, unless you pass --without-records, every keyed audio entry's fingerprint record (fp/). A date range extends to the checkpoint that anchors it. --tenant narrows the counts; the streams stay whole.

Option Default Meaning
--out FILE required The bundle zip to write
--from TEXT no lower bound The first day (YYYY-MM-DD, inclusive) or an ISO 8601 UTC timestamp
--to TEXT no upper bound The last day (YYYY-MM-DD, inclusive) or an ISO 8601 UTC timestamp
--sink INTEGER 0 The index into evidence.sinks to read; 0 is the authoritative first
--without-records off Leave the keyed audio fingerprint records (fp/) out
--tenant TEXT none Count only this tenant's entries in the summary (needs the tenant_reports licence feature)

The export itself is never locked. A month over the free allowance that no licence unlocks exports with the compliance paperwork withheld (Licensing). The one refusal is --tenant without the tenant_reports feature: the command prints error: ... and exits 3.

laidline evidence export --out bundle.zip
{
  "out": "bundle.zip",
  "streams": 2,
  "entries": 6,
  "checkpoints": 1,
  "unanchored": 4,
  "signed": true,
  "records": {
    "included": true,
    "count": 0,
    "missing": 0
  },
  "warnings": []
}

evidence verify

laidline evidence verify [OPTIONS] BUNDLE

Verifies a bundle (a zip or its unpacked directory) with the same code as the bundle's own verify.py. Exit 0 means verified, 1 an integrity failure (or a skipped check with --strict), 2 unreadable input.

Option Default Meaning
--json off Print the laidline.verify/1 report as JSON
--strict off Fail when a check is skipped
--tsa-roots FILE the built-in roots Trusted timestamp root certificates (PEM)
laidline evidence verify bundle.zip
Laidline evidence bundle: bundle.zip
manifest: 11 files listed, signature ok
stream host-0ca3df: seq 1..4 (4 entries) ok; no anchoring checkpoint, 4 unanchored
stream host-242d81: seq 1..2 (2 entries) ok; anchored to seq 1, 0 unanchored
checkpoint host-242d81 [1, 1]: head ok, signature ok, tsa ok
licence: absent
  2026-10: private 0, shared 2, self-test marks: 1, absent
warnings:
  unanchored_tail:host-0ca3df:4
RESULT: OK

evidence check-slots

laidline evidence check-slots [OPTIONS]

Checks the keyed registry's stored slots and fingerprint records against the evidence chain. The slots (the S3 watermark pointers and the Postgres slot column) are not part of the hash chain: every one must match its entry, every marked entry must have one and every decoy must be the canonical one. A file sink stores no slot. Every keyed audio entry's fingerprint record must be stored with its committed length and hash, every decoy record must be canonical, and every record no entry names is listed as an orphan.

Exit 0 when nothing is found, 1 when something is (one line per finding), 2 when the store cannot be read.

Option Default Meaning
--sink INTEGER 0 The index into evidence.sinks to check
--records-sample N 0 (all) Check the fingerprint records of N keyed audio entries (seeded) instead of all; lists no orphans

evidence init-db

laidline evidence init-db [OPTIONS]

Creates the Postgres evidence schema as the migrator and grants the app role SELECT and INSERT only. It is idempotent. In one transaction it creates the schema, evidence_entries and evidence_checkpoints, their indexes and the append-only triggers (UPDATE, DELETE and TRUNCATE raise for every role). The triggers bind the app role. The role that owns the tables (the migrator) or a superuser can still disable or drop them, which the hash chain and the timestamped checkpoints make evident.

Your database administrator creates the app role first, for example CREATE ROLE laidline_app LOGIN PASSWORD '...', and gives the sink that role's DSN (evidence.sinks[].dsn_env). The migrator must be a different role. The command refuses an app role that is a superuser or a member of the migrator role.

Option Default Meaning
--dsn-env TEXT LAIDLINE_PG_MIGRATOR_DSN The variable that holds the migrator DSN, the role that owns the schema
--schema TEXT laidline The schema to create
--app-role TEXT laidline_app The existing role the sink connects as
laidline evidence init-db

The command creates the schema in the database the migrator DSN names and exits 0; running it again changes nothing.

models

models fetch

laidline models fetch [OPTIONS]

Downloads and verifies the pinned watermark weights into $LAIDLINE_HOME/models. Use it to prepare an air-gapped host. Each file is checked against its pinned SHA-256 before it is kept. It does not yet fetch the TrustMark Q decoder's ONNX graph (decoder_Q.fp32.onnx) of the keyframe video reader; the reader fetches that on first use unless LAIDLINE_OFFLINE=1 (Install).

Option Default Meaning
--audio / --no-audio --audio The AudioSeal generator and detector (about 190 MB)
--video / --no-video --video VideoSeal 1.0 (about 230 MB)
--image / --no-image --image PixelSeal, the default image scheme (a 1.24 GB checkpoint, kept as its slimmed 309 MB weights)
laidline models fetch --no-audio --no-video
/home/you/.cache/laidline/models/pixelseal/model.pth (308952624 bytes, from dl.fbaipublicfiles.com)

Each line is a file the command wrote, its size and the host it came from (already present when the file was already in place). With LAIDLINE_MODELS_MIRROR set, the mirror is tried first and the upstream host is the fallback. $LAIDLINE_HOME/models is ~/.cache/laidline/models when LAIDLINE_HOME is unset. Set LAIDLINE_OFFLINE=1 on the host that serves to forbid any model download after this step.

payload-keys

Watermark payload keys. See Keys for what a key does and does not do.

payload-keys generate

laidline payload-keys generate [OPTIONS]

Generates a payload secret: 64 hex characters from 32 random bytes. With --out the file is created with mode 0600 (and never replaced) and the command prints only the key fingerprints.

Option Default Meaning
--out FILE none Write the secret here (mode 0600)
--stdout off Print the secret instead; it then reaches your terminal
--id TEXT k1 The key id the fingerprints are computed for
laidline payload-keys generate --out k2.key --id k2
wrote k2.key (mode 0600); key_fp for id k2: image=a0bc6fa1506cdc22 video=59f1ecefe488baaf audio=f493b030607d3144
warning: a new payload key is inert for marking until it is re-bound: run `laidline register` again (the issuer replaces the binding per medium on a renewal). The old key keeps marking while it is bound and live, and stays `verify` afterwards so earlier marks keep confirming.

payload-keys list

laidline payload-keys list [OPTIONS]

Lists the payload keys: id, state, media and the key fingerprint (key_fp) per medium. It resolves each secret and prints none.

laidline payload-keys list
id  state   media              key_fp
k1  active  image,video,audio  image=79efa0982b664112,video=1cfebef6882886fc,audio=ca389ea92e9fd17e

payload-keys fingerprint

laidline payload-keys fingerprint ID [OPTIONS]

Prints the key_fp of one payload key per medium, as medium=key_fp. ID is the key's id in watermark.payload_keys.

laidline payload-keys fingerprint k1
image=79efa0982b664112 video=1cfebef6882886fc audio=ca389ea92e9fd17e

payload-keys retire

laidline payload-keys retire ID [OPTIONS]

Acknowledges the retirement of a payload key. It does not retire the key. Marks made under a retired key stop verifying (grade B or C falls to D), so the command refuses a key with marked entries in the local evidence chain unless you pass --orphans-marks. It records a config_changed entry (retire_acknowledged, with the orphan count) and does not edit the configuration: set state: retired for the key in watermark.payload_keys, then restart laidline. A SIGHUP re-reads only the secrets, never the configuration. The restarted process records the retired event.

Option Default Meaning
--orphans-marks off Retire even though marks were made under the key; they stop verifying
laidline payload-keys retire k1
recorded the retirement of payload key k1 (0 marked entries orphaned); the key is still live: set state: retired for k1 in watermark.payload_keys and restart laidline

licence

Licences from the issuing service. See Licensing.

licence fetch

laidline licence fetch REGISTRATION_ID [OPTIONS]

Resumes a registration: polls until the documents are issued, then verifies and installs them. REGISTRATION_ID is the id register printed (also in its resume command).

Option Default Meaning
--timeout TEXT 30m How long to wait: 90s, 30m, 2h

The status polls carry no proof. Once the registration is issued, the command fetches the documents with a documents proof signed by the active signing key (the documents proof), so it needs the deployment's signing key (exit 1 when none can be built). When the issuing service does not accept that key as the registration's, the command exits 1 with error: registration REGISTRATION_ID is issued, but the issuer did not accept this deployment's signing key as the registration's; bind it by running laidline register again (a host clock more than five minutes off, or an issuer.registration_url that is not the issuing service's address, also causes this).

licence install

laidline licence install FILE [OPTIONS]

Verifies a laidline.licence file under the pinned roots and copies it into the licence directory. Use it on an air-gapped host. A licence that lapsed beyond its grace period is refused and nothing is installed.

laidline licence install licence.json
installed /var/lib/laidline/licence/licence-....json
licence ...: plan lite, valid until 2027-10-26
reload: send SIGHUP to laidline serve or restart it

licence status

laidline licence status [OPTIONS]

Prints the licence state, plan, allowance, credits used this month, the issuer number and the directory snapshot.

Option Default Meaning
--json off Print one JSON object
laidline licence status
state: free_within_cap
plan: none
allowance: none
credits this month: image 0, video 0, audio 0 (total 0)
suggested band: registered_free
marks this month: private 0, shared 0
self-test marks: 0
issuer: unregistered shared number 46958
directory: snapshot 2026-10-21 serial 10
licence: absent

issuer

Issuer certificate and the issuer directory snapshot.

issuer install

laidline issuer install FILE [OPTIONS]

Installs an issuer certificate or a directory snapshot, told apart by its type, after verifying it under the pinned roots. FILE is the JSON document.

issuer refresh

laidline issuer refresh [OPTIONS]

Fetches the issuer directory snapshot, verifies it and its serial (never backwards) and writes it. A refusal keeps the installed file and exits 1.

Option Default Meaning
--url TEXT issuer.directory.refresh_url Where to fetch the snapshot
laidline issuer refresh

The command prints the snapshot date and serial it installed, or error: <reason> and leaves the installed snapshot in place.

usage

laidline usage [OPTIONS]
laidline usage report [OPTIONS]

laidline usage prints the usage statement for a month as JSON: credits and marks by medium, the licence state and the issuer numbers, counts only.

Option Default Meaning
--month YYYY-MM this month The month to report
--tenant TEXT none Only this tenant (needs the tenant_reports licence feature; exits 3 without it)

usage report

Sends the signed monthly usage report (counts only, no media) to the issuing service. The issuer keeps the first report of each month. An empty usage-reported-MONTH file in the evidence directory records that it was sent.

Option Default Meaning
--month YYYY-MM the previous month A completed month
laidline usage --month 2026-10
{
  "v": 1,
  "type": "laidline.usage-statement",
  "month": "2026-10",
  "closed": false,
  "licence_state": "free_within_cap",
  ...
}

Exit codes

Code Meaning
0 The command did what you asked
1 The command failed, or (for evidence verify, evidence check-slots and verify-result) found a problem
2 An unreadable input: a bundle, a result file or a store that cannot be read; or an option the command refuses, such as a plain http --admin-url; or bench without the laidline-bench package
3 The licence lacks a feature the command needs: --tenant on evidence export or usage without tenant_reports

Troubleshooting

Message Cause Fix
error: laidline.yaml already exists; not overwriting init never replaces a file Pass --path for a new name, or delete the old file
error: add signing.keys_file: ./keys.yaml to ...; rotate creates it and seeds it with the current key as id 'default' keys rotate needs the key file named in the configuration Add the line it shows to laidline.yaml, then run the command again
error: --admin-url http://... is plain http to another host: the admin token would cross the network unencrypted; use https, or http only to localhost, 127.0.0.1 or ::1 The admin token travels in the request Use an https URL
error: network: [Errno 111] Connection refused issuer refresh or register cannot reach the service Check the network and issuer.registration_url, issuer.directory.refresh_url
error: unknown_key: the signing key is not bound to a registered customer usage report runs for a deployment that has not registered Run laidline register first
laidline bench needs the laidline-bench package: pip install laidline-bench The benchmark harness is a separate package; the command exits 2 pip install laidline-bench
the timestamp server did not answer: ... mark cannot reach signing.tsa.url Open egress to the timestamp server, or set signing.tsa.required: false and accept grade B at best

Reference

  • HTTP API reference: the routes laidline serve exposes.
  • Configuration: every key the commands read.
  • Grading: what laidline detect reports and how it grades.
  • Evidence: what laidline evidence export bundles and how verify checks it.
  • Keys: payload keys and the shared pool key.
  • Licensing: plans, credits and what each licence state allows.