Manage the Pipelock license that unlocks paid features. Pipelock's detection,
enforcement, and verification are free and need no license; a license unlocks
the Pro (agents) and Enterprise (fleet) feature tiers.
The license command ships in official release builds. The paid features it
unlocks are gated at runtime by the license entitlement — installing a token
never weakens any free detection or enforcement.
| Subcommand | Who runs it | Purpose |
|---|---|---|
install TOKEN |
operator | Write a license token to disk for runtime use. |
status |
operator | Verify the configured license and show expiry/renewal status. |
inspect TOKEN |
anyone | Decode a token's claims (no signature verification). |
keygen |
issuer | Generate a license signing keypair. |
issue |
issuer | Sign a license token from a private key. |
intermediate issue |
issuer | Mint a root-signed intermediate signing certificate (offline root). |
Most customers only run install and status: you receive a signed token,
install it, and confirm it is active. keygen and issue are for license
issuers and for self-managed or unofficial enterprise builds that mint their own
tokens.
Validate a license token's format and write it to disk so the runtime can read it. The write is atomic (temp file + rename).
pipelock license install pipelock_lic_v1_...| Flag | Default | Description |
|---|---|---|
--path |
~/.config/pipelock/license.token |
File path to write the token. |
After installing, point your config at the file (license_file: <path>) or set
PIPELOCK_LICENSE_KEY. The command prints the license ID, customer email,
expiry, the written path, and a sample config line.
Verify the configured license — full signature check, plus optional revocation and intermediate-certificate checks — and report renewal/expiry status.
pipelock license status
pipelock license status --json| Flag | Default | Description |
|---|---|---|
--config, -c |
discovered config or built-in defaults | Config file to read the license source from. |
--crl |
(none) | Signed CRL file override. |
--json |
false |
Emit status as JSON. |
Text output reports the status (valid / missing / invalid / expired /
revoked), license ID, tier, subscription ID, expiry, renewal-band warning, CRL
expiry, whether an intermediate certificate is configured, and the reason on
failure. JSON output carries the same fields as machine-readable keys
(status, license_id, tier, subscription_id, expires_at,
days_remaining, warning_band, severity, crl_configured,
crl_expires_at, crl_sha256, intermediate_configured,
require_intermediate, reason).
When license_require_intermediate is on (config field or
PIPELOCK_LICENSE_REQUIRE_INTERMEDIATE), status enforces the full chain: a
configured intermediate is required, a missing or stale CRL is invalid, and a
token not signed through the intermediate fails. See the
intermediate-signing migration runbook.
Decode and print a token's claims without verifying the signature. Useful
for a quick look at what a token contains; it prints a warning that the
signature was not checked, so a token shown here may be forged. Use
status for a verified check.
pipelock license inspect pipelock_lic_v1_...Prints the license ID, email, org, tier, subscription ID, issued and expiry timestamps, and the feature list. No flags.
Generate an Ed25519 keypair for signing license tokens. Issuer-side: run this once to create the signing key, then keep the private key offline.
pipelock license keygen --out ~/.config/pipelock| Flag | Default | Description |
|---|---|---|
--out |
~/.config/pipelock |
Output directory for the keypair. |
Writes license.key (private) and license.pub (public), and prints the hex
public key for embedding into a build. Unofficial enterprise builds verify
tokens against PIPELOCK_LICENSE_PUBLIC_KEY; official builds may embed the key.
Sign a license token from a private key. Issuer-side.
# Free token (no paid feature) — allowed directly:
pipelock license issue --email customer@example.com --features "" \
--expires 2027-01-01
# Paid token — minted by the license service in normal operation; the
# standalone CLI requires --break-glass + --export (see the issuance gate):
pipelock license issue --email customer@example.com --tier enterprise \
--features fleet --features agents --expires 2027-01-01 \
--break-glass --export break-glass-export.json| Flag | Default | Description |
|---|---|---|
--key |
~/.config/pipelock/license.key |
Path to the signing private key. |
--email |
(required) | Customer email. |
--org |
(none) | Organization name. |
--expires |
(none, perpetual) | Expiration date, YYYY-MM-DD. Omit for no expiration. |
--features |
[agents] |
Feature list (repeat the flag for multiple). Pass --features "" for a featureless free token. |
--ledger |
alongside the private key | Ledger file path. |
--tier |
(none) | License tier (e.g. pro, founding_pro, enterprise). |
--subscription-id |
(none) | External billing subscription ID. |
--break-glass |
false |
Override the issuance gate to mint a paid token offline (emergency only; requires --export). |
--export |
(none) | Write a signed issuance export to this path so the service can import the break-glass token. |
Prints the signed token and appends a truncated hash of it to the issuance
ledger. The --features you sign decide what the token unlocks: agents for
Pro, fleet for the Enterprise fleet control plane (see the
tier-gating audit matrix).
A paid license is a revocable credential: the license service tracks every paid token it mints (in its database) so it can revoke a still-valid token via the signed CRL. A token minted by the standalone CLI is invisible to the service and therefore cannot be revoked — a popped signing host could mint perpetual paid tokens with no way to pull them back.
To close that gap, license issue refuses to mint a paid/revocable token
unless --break-glass is set. The gate keys on the capability itself, not on a
label flag:
- any non-free feature (every shipped feature —
agents,assess,fleet— is paid; the Free tier needs no license at all); - a non-empty
--tier; - a non-empty
--subscription-id; - a no-expiry (perpetual) token that carries any feature.
Omitting --tier/--subscription-id does not slip a paid token past the
gate — the feature alone trips it.
A genuinely free token (no features, no tier, no subscription) is issued directly, with or without an expiry.
--break-glass preserves the offline emergency-signing capability the
key-custody runbook depends on (e.g.
signing a replacement token directly from the offline root). To keep the token
revocable, a break-glass paid mint requires --export <path>: it writes a
signed issuance export that the license service imports into its durable
signed import table (keyed by license ID and the full token hash, with
replay and conflict rejection). The local issuance ledger stores only a
truncated, unsigned hash and cannot be the import source.
Import the export into the service after the emergency so the break-glass token
can be revoked like any other paid license — the service operator runs
license-service import-issuance --export <file> --issuer-pubkey <key> and can
review the import table with license-service list-imported-issuances. To
revoke it later, run
license-service revoke-imported-license --license-id <license-id> --reason <reason>;
the next signed CRL carries that license ID. See the full issue → export →
import → inspect → revoke flow in the
intermediate-key migration guide.
Mint a root-signed intermediate signing certificate from the OFFLINE root key. Issuer-side; run it on the air-gapped host that holds the root key.
pipelock license intermediate issue \
--root-key /path/to/offline/license.key \
--serial im-2026-001 \
--validity 2160h \
--out ./out| Flag | Default | Description |
|---|---|---|
--root-key |
~/.config/pipelock/license.key |
Path to the OFFLINE root private key. Used to sign; never copied or logged. |
--serial |
(required) | Unique serial / key id for this intermediate — the CRL revocation key. |
--out |
current directory | Output directory for intermediate.key + intermediate.json. |
--validity |
2160h (90 days) |
Validity window; capped by the library maximum (refused if too long). |
Generates a fresh intermediate keypair, signs the certificate over its public
half with the root key, and writes two 0600 files: intermediate.key (the
intermediate private key — deploy ONLY to the license service) and
intermediate.json (the root-signed certificate — distribute to consumers via
license_intermediate_file). It refuses to overwrite an existing
intermediate.key. This is the first step of the
intermediate-signing migration runbook.
Inspect and verify signed certificate/license revocation lists (CRLs). A CRL lets the runtime reject licenses (and revoked intermediate signing certificates) that have been pulled before their natural expiry.
CRLs are issued (signed) by the cluster license-service, which owns the canonical revocation list. The CLI deliberately does not sign CRLs: CLI issuance stays out because the license-service owns that canonical list, and a CRL generation number does not make it safe for an offline signer to issue an arbitrary subset of it. The CLI provides only the read side.
Decode a CRL and show what it revokes. Does not verify the signature.
pipelock license crl inspect crl.json
pipelock license crl inspect crl.json --jsonVerify a CRL's Ed25519 signature and check it has not expired. Exit code 0 on
a valid, unexpired CRL; 1 otherwise.
pipelock license crl verify crl.json --public-key /path/to/license.pub| Flag | Default | Description |
|---|---|---|
--public-key |
embedded key, then configured key | Public key as a file path or raw hex. |
--config / -c |
discovered config | Config file used to resolve the license public key when --public-key is omitted. |
The public key is resolved in order: --public-key, then the embedded build key
(if the binary was built with one), then the configured license public key
(config file or PIPELOCK_LICENSE_PUBLIC_KEY).
The time-boxed Enterprise Eval and Enterprise Trial tiers both grant the
full Enterprise feature set (agents + fleet) for 60 days with no renewal, and
both allow one active, unexpired entitlement per normalized customer email. They
differ in how they are obtained. Enterprise Eval is a paid one-time order that the
service validates against the provider before minting. Enterprise Trial is a
zero-dollar one-time order; after a trial's 60 days end, the same email may start
another. Both are fulfilled as hosted self-service flows: purchase the eval or
start the trial, receive a signed token by email, then pipelock license install TOKEN and confirm with pipelock license status. A refund revokes the
evaluation or trial through the signed revocation list and the runtime tears the
paid features back down to free; a refunded trial keeps its email's slot occupied
until the original 60 days would have ended.
The separate enterprise license-service binary can summarize its local JSONL audit ledger without daemon configuration, signing keys, or database access:
license-service audit-summary --ledger /data/audit.jsonl
license-service audit-summary --ledger /data/audit.jsonl --format json --fail-on-errorsUse --since and --until with RFC3339 timestamps to select a reporting window. The start is inclusive and the end is exclusive. Reports count known event types and group unfamiliar types under unknown_events; customer addresses, tokens, event details, and unfamiliar event names are omitted.
By default, recorded errors do not change the exit status. --fail-on-errors returns a nonzero status after printing the report when the selected window contains error or email_failed events. Unknown events are counted separately and do not trigger that flag. This is a summary of an unsigned local ledger, not a service-health check: an empty window does not prove the service is healthy.
Input and output failures return a nonzero status. The reader rejects malformed records, incomplete final lines, and lines exceeding its 1 MiB resource limit rather than printing a partial report. It reads up to the file size observed when opened. For a ledger receiving concurrent writes, use a stable, complete copy; an append observed partway through a record can otherwise produce an incomplete-line error. Keep the original ledger intact when investigating rejected input.
- Intermediate-signing migration runbook
— move from direct root signing to root → intermediate → token and turn on
require_intermediate. - Conductor — the Enterprise fleet control plane the
fleetfeature unlocks. - Tier-gating audit matrix — which feature gates which surface, with the deny cases.