The CLI (leanctl)
leanctl is the LeanSignal command-line client. It authenticates with a
personal access token and acts with your own identity and role — what you
can do in the LeanSignal app is what you can do here, and nothing more. Actions
taken through it appear in the audit log
attributed to you, via CLI.
$ leanctl auth login --tenant acmeResolving tenant "acme"…Personal access token: ****Logged in to https://acme-api.eu11.leansignal.io as you@example.com (admin)
$ leanctl demand listNAME DESCRIPTION CREATED BY AGEhost-metrics node health and disk you@example.com 12dkubernetes cluster + workloads you@example.com 5d
$ leanctl demand export host-metrics > demands/host-metrics.jsonThe CLI is open source: github.com/LeanSignal/leansignal-cli.
Install
Section titled “Install”One-liner for macOS and Linux:
curl -fsSL https://raw.githubusercontent.com/LeanSignal/leansignal-cli/main/scripts/install.sh | shIt detects your OS and architecture, downloads the matching release, verifies
its checksum, and installs to /usr/local/bin — or ~/.local/bin when that is
not writable, so it never demands sudo. Options: --version vX.Y.Z,
--bin-dir DIR, --no-verify. Review the script before piping it to a shell.
Prefer a manual download? Releases carry leanctl_<version>_<os>_<arch>.tar.gz
for darwin and linux, amd64 and arm64, with cosign-signed checksums —
see the releases page
and the repo README for verification steps, building from source, and shell
completion.
To upgrade, repeat the install — it overwrites in place.
Authenticate
Section titled “Authenticate”- In the LeanSignal app, go to Preferences → Access tokens and mint a
token. Scopes are
read(always granted),write(create and update), andwrite:delete(delete; implieswrite). Write scopes need the editor or admin role. leanctl auth login --tenant <your-tenant>and paste it.
You name the tenant; the regional API endpoint is looked up for you and treated
as a cache, never a fact — if the tenant later moves regions, leanctl
re-resolves and retries transparently. --api-url pins an endpoint instead
(local development, air-gapped setups) and opts that profile out of resolution.
The token is stored at ~/.config/leanctl/config.yaml with mode 0600. There
is deliberately no --token flag — a command line is visible to every
process on the host and lands in shell history; use the login prompt,
--token-stdin, or the LEANCTL_TOKEN environment variable.
leanctl auth logout --revoke revokes the token server-side as well as
removing it locally.
In CI, skip login entirely — a pinned endpoint keeps CI free of the resolver:
export LEANCTL_TOKEN=lsp_…export LEANCTL_API_URL=https://<tenant>-api.eu11.leansignal.ioleanctl demand import --file demands/host-metrics.json --dry-runMultiple tenants — profiles
Section titled “Multiple tenants — profiles”Each login saves its own profile (the command also answers to context,
kubectl-style — same thing):
leanctl auth login --tenant acme # saves profile "acme"leanctl auth login --tenant globex # and "globex"leanctl profile use globex # switch the defaultleanctl demand list --profile acme # or override per commandLEANCTL_PROFILE selects one from the environment. Each profile carries its
own token and its own cached endpoint.
Stored vs Available
Section titled “Stored vs Available”LeanSignal stores only demanded telemetry, so every query command has two sides — the same Stored/Available split as the app’s Metrics, Logs, and Traces pages:
| default | --available | |
|---|---|---|
| Reads | the central store | the connected agent’s local store |
| Holds | only demanded data | everything the agent collects |
| Retention | 30 days | ~1 day metrics, ~1 hour logs and traces |
| Answers | ”what are we keeping?" | "what could we demand?” |
An empty result from the central store is usually a demand gap, not an outage —
leanctl says so and hands you the next command to check both sides
(leanctl filter list, then the same query with --available).
Commands
Section titled “Commands”| Command | Does |
|---|---|
auth | login, logout, status, tokens list|create|revoke |
profile / context | list, use, delete, current |
demand | list, get, create, update, delete, export, import |
dashboard | list, get, apply, delete, versions |
agent | list, get, create, update, delete, diagnose, config get|apply |
alert | list, get, create, update, delete, pause, resume, mute, unmute, test |
channel | list, get, create, update, delete, test |
synthetic | list, get, create, update, delete, pause, resume, test, results |
rule | ingestion rules: list, get, create, update, delete, enable, disable |
filter | demand set: list, purged, sync, sweep |
metrics | names, query, query-range, series, labels, label-values |
logs | query, labels, label-values, stats |
traces | search, get, tags |
status | what this tenant is storing |
audit | list (admin) |
settings | get, set (admin) |
search | find anything by name |
Run leanctl <command> --help for flags and examples.
User management, invitations, and support cases are not here, by design. Those live in the control center and need a real browser session, which a token does not carry — use the LeanSignal app.
Output and scripting
Section titled “Output and scripting”-o json prints the server’s own JSON, unreshaped; -o yaml, -o wide
(extra columns, including ids), and -o name (bare ids) round out the set,
plus --no-headers. Tables are space-padded text — never box-drawing — so
awk and cut keep working. Empty-result explanations go to stderr,
leaving stdout clean for pipelines. Exit codes are a contract: 0 success,
2 usage, 3 auth, 4 not found, 5 validation, 6 server, 7 unreachable
(1 for everything else). Destructive commands prompt, and refuse to run
unattended without --yes.
Demands in git
Section titled “Demands in git”Export and import round-trip a whole demand — dashboards and alert rules included, UUIDs stripped, channels referenced by name — which makes a demand bundle a reviewable artifact:
leanctl demand export host-metrics > demands/host-metrics.json # commit itleanctl demand import --file demands/host-metrics.json --dry-run # PR checkleanctl demand import --file demands/host-metrics.json # on merge--dry-run validates and reports without writing. Missing notification
channels are warnings, not errors, and any rule left without a channel is
imported paused.
Editing an agent’s collector config
Section titled “Editing an agent’s collector config”agent config reaches the collector configuration on the agent host itself,
over the agent’s control stream — admin role, connected agent required:
leanctl agent config get my-agent # what sources existleanctl agent config get my-agent --path /etc/leansignal-agent/config.yaml > c.yaml$EDITOR c.yamlleanctl agent config apply my-agent --file c.yamlThe agent validates the write — YAML parse plus a full collector dry-run — and applies it only if it passes; a rejected config changes nothing on the host. See Agent configuration for how applying works and which installs are editable.
Thanks for your feedback!
Report sent — thank you!