Releases: keylight-dev/keylight-cli
Release list
v0.1.3
[0.1.3] - 2026-08-02
Added
keylight setup verify-license. A one-time terminal check that mints a
recognizableSetup checklicense, activates it through the real Rust SDK,
and verifies the returned lease against the tenant's Ed25519 keyset. The SDK
key is read fromKEYLIGHT_SDK_KEY, never from an argument.- Safe cleanup and retry reuse. Setup state is held in a separate
owner-only local file until--cleandeactivates the device and revokes the
test license. Non-interactive runs never delete it implicitly.
Changed
- Setup input errors exit
2. Missing SDK keys and an ambiguous app
selection are actionable setup failures; lease and activation failures still
exit1, and confirmation denial or expiry remains3.
v0.1.2
[0.1.2] - 2026-07-31
First release after running every command against production rather than
against a test double. The command surface was already complete; what had never
been checked was whether the output was right. Three commands were printing
the wrong thing, and one of them was losing a value that cannot be recovered.
Fixed
licenses createno longer discards the license key. The API returns the
plaintext key once, on mint, and never again.remintprinted it;create
printed only the masked form, so a key issued without--jsonor
--send-emailwas gone the moment the command returned. Both mint paths now
print it the same way.products key-types createandupdateprint the key type again. Both
read akeyTypefield that no route sends — the API wraps the object in
createdandupdated— so every field rendered as-and the output looked
like a failure. The write had always succeeded; only the display was wrong.test-purchase createandgetshow the key. They readdisplayKey,
which is the licenses routes' name for it; the test-purchase routes send
licenseKeyMasked. Every run printedKey: -, including completed ones.
Changed
-
A usage error now exits
1instead of2.2is documented as "not
authenticated, or the token lacks the required scope — re-runkeylight login", but argument parsing exited2as well, so a mistyped flag was
indistinguishable from an auth failure. An unattended caller following the
documented table would log in, retry the same broken command, and loop.2
now means only what it says.--helpand--versionstill exit0.This aligns the implementation with the published exit-code table rather than
changing that table. A script keying on observed behaviour rather than the
documented meaning may need adjusting.
Notes
Each fix is behind a small pure function with tests against real response
bodies captured from api.keylight.dev. The previous tests asserted the same
assumed shapes the code used, which is why all three renderer bugs passed a
green suite.
v0.1.1
[0.1.1] - 2026-07-30
Packaging only — no change to any command, flag, or output.
Added
- Homebrew.
brew tap keylight-dev/tap && brew trust keylight-dev/tap && brew install keylightinstalls a prebuilt binary: no Rust toolchain, and
nothing to clear past Gatekeeper. Bottles mean the install pours rather than
building, so it never runs Homebrew's build-environment checks — which reject
an Xcode older than the minimum for your macOS, an error about Xcode on a
machine that only wanted a licensing CLI. - An Intel macOS binary (
x86_64-apple-darwin), cross-compiled from the
arm64 runner. Previously Intel Macs had no published binary and fell through
to a source build.
Fixed
- Release builds now pass
--targetexplicitly. Artifacts were named for a
triple the build never specified — correct only while each runner happened to
be that architecture, and wrong the moment two targets shared a runner, which
is what adding Intel macOS does. - The
products listsample in the README showedfalseunder FREE TIER and
TEST MODE. The API omits those flags when they are off rather than sending
false, so the real output is-.
v0.1.0
0.1.0 - 2026-07-29
First release. Every endpoint the Keylight management API exposes is reachable
from a command, and a coverage test fails the build if that stops being true.
Added
Authentication
keylight login— browser approval over
RFC 8628 device authorization,
so it works over SSH and on headless machines.--scopenarrows the request;
dangeris never requested by default.keylight logout— revokes the token server-side and deletes the local
copy. If the revoke fails, the local copy is still removed and the output
says so, rather than leaving a credential on disk you believe is gone.keylight auth set-token/auth status— token read from stdin, never
argv.KEYLIGHT_API_TOKENtakes precedence over the stored file.
Resources
keylight products— list, get, create, update, free tier, Stripe test mode,
and per-provider price mapping.keylight products key-types— list, create, update, delete, verify-prices.keylight licenses— list, get, create, revoke, remint, deactivate-device,
bulk import, CSV export.keylight customers— list, get, create, entitlements, link-license.keylight integrations— list, status, connect, disconnect, rotate-secret.keylight webhook— get and set, including clearing it.keylight sdk-key— get and rotate.keylight usage— activation and validation volume, with a summary.keylight test-purchase— create and get.
Output
--jsonon every command, printing the raw API response.- Aligned tables for lists, key/value blocks for single items, and empty
results that name the command to run next. - Progress output — approval URLs, waiting notices — always goes to stderr, so
--jsonstdout stays parseable andlicenses export > out.csvwrites CSV.
Behavior worth knowing
- No command requires an interactive prompt. Every input is available as a
flag, so agents and CI can drive the whole surface. - Secrets are never flags.
--*-envflags name an environment variable
to read from, because argv lands in shell history and is visible to other
users viaps. - Pagination is explicit.
listcommands take--limitand--cursorand
print the next cursor; nothing auto-pages. - Confirm-gated operations block and poll. Seven operations need a human to
approve in a browser:licenses revoke,licenses export,products key-types delete,integrations rotate-secret,sdk-key get,sdk-key rotate,webhook set. - Mints are idempotent.
licenses createandlicenses importalways send
anIdempotency-Key, so a retry after a timeout cannot issue a second
license to the same customer. --duration-days 0means perpetual, which the API represents asnull.licenses remintprints the new plaintext key, which the API returns
exactly once.- Exit codes:
0success,1general failure,2not authenticated,
3confirmation denied or expired.
Known limitations
- Prebuilt macOS binaries are not code-signed or notarized, so Gatekeeper
blocks them on first run. Clear the quarantine flag with
xattr -d com.apple.quarantine ./keylight, or install with
cargo install keylight-cli, which builds locally and avoids it. - Only read paths have been exercised against production. Write and
confirm-gated paths are covered by tests written against the API's documented
request and response contracts, but have not been run live. - No shell completions or man pages yet.