litmus-cli - Command-Line Interface for Litmus
You are reading this at
https://api.litmus.io/cli.md(HTML version athttps://api.litmus.io/cli).
litmus-cliis the standalone command-line client for Litmus Edge, Litmus Edge Manager, and Litmus Unify. It exposes the full Litmus SDK surface (~1250 functions) as shell commands with JSON output, and is the preferred method for AI agents and agentic tasks: no code to write, install, or run.
Ecosystem Context
| Layer | Guide |
|---|---|
| MCP Server (curated tools, no code needed) | https://api.litmus.io/mcp-agents.md |
| litmus-cli (this document) | https://api.litmus.io/cli.md |
| Language SDKs (Python today; Go and Rust in the works) | https://api.litmus.io/sdk-agents.md |
| Raw API Collection (full 3,310 endpoints) | https://api.litmus.io/agents.md |
| API Portal (human-readable workspace) | https://api.litmus.io |
What it is
litmus-cli is the standalone command-line client for the Litmus APIs: the full SDK surface (~1250 functions) as shell commands with JSON output, covering Litmus Edge, Litmus Edge Manager, and Litmus Unify. It is the preferred method for AI agents and agentic tasks.
- A single statically linked binary, no runtime dependencies, built from the Litmus Go SDK (whose public source release is in the works).
- Released under
cli-v*tags athttps://github.com/litmusautomation/litmus-sdk-releases/releases(latest: cli-v1.0.0). Prebuilt for macOS arm64, Linux amd64/arm64, and Windows amd64. - Results are JSON on stdout, errors on stderr, so output pipes cleanly into
jq, scripts, and agent tool calls. - Covers Litmus Edge (including the DataHub data plane), Litmus Edge Manager, and Litmus Unify, including all mutations.
- Supported versions (cli-v1.0.0+): Litmus Edge 4.4.x and Litmus Edge Manager 3.0.x
(LTS), Litmus Unify 2.0.x. Litmus Edge 4.0.x and Edge Manager 2.31.x work
best-effort: functions new in Litmus Edge 4.4 fail on 4.0 with a clear "requires
Litmus Edge 4.4 or later" error, and functions new in Edge Manager 3.0 fail on
2.31 with the server's 404 (
unexpected status 404 (expected 200)). Litmus Edge 3.x and Edge Manager releases older than 2.31 are no longer supported. - Stable from cli-v1.0.0:
runpaths and--argsnames do not change within 1.x, so scripts and agent prompts written against one 1.x release keep working. - Not part of the
litmussdkPython package. Until June 2026 a Python console script namedlitmus-sdk-clishipped with the wheel; see the migration table inhttps://api.litmus.io/sdk-agents.mdif you are moving from it.
What's new in cli-v1.0.0
First stable release. Litmus Edge 4.4.x and Litmus Edge Manager 3.0.x are the supported LTS releases, and the CLI follows semantic versioning from here on.
| Product | Supported | Best-effort | Dropped |
|---|---|---|---|
| Litmus Edge | 4.4.x | 4.0.x | 3.x |
| Litmus Edge Manager | 3.0.x | 2.31.x | older than 2.31 |
| Litmus Unify | 2.0.x |
- ~1250 functions, up from ~1000. 104 new Litmus Edge 4.4 operations (saved
templates and snapshots, system log query and log forwarding, analytics workspaces,
groups, component variables and AI Suite, OPC UA paged navigation and worker sync,
DeviceHub search tasks, Digital Twins asset hierarchy) and 134 new Edge Manager 3.0
operations (asset hierarchy, Asset Hub, device HA, device OAuth clients, edge logs,
platform rules, CA certificates, audit records v2, instance async tasks), in
lem.*andlem.admin.*. - Version-aware. Calls pick the right request shape from the device firmware, and
functions new in a release are marked
LE 4.4+orLEM 3.0+in their--help. - Security. Built with Go 1.26.9, which clears the Go standard library CVEs in
cli-v0.13.0. Run
litmus-cli update.
Breaking and behavior changes - check scripts that call:
lem.CreateTemplate,lem.admin.UploadEdgeDeviceTemplate,lem.admin.UpdateEdgeDeviceTemplateDescription: now takefriendlyName, which Edge Manager 3.0 requires.le.integrationsprovider IDs: these are the Litmus Edge 4.4 UUIDs.le.integrations.ResolveProviderIDandLookupProvidermap them to the 4.0 slugs on 4.0 devices.le.analytics.GetAnalyticsParametersandSetAnalyticsParameter: deprecated, and they fail on Litmus Edge 4.4, which removed global parameters.ExportGroupreturnsComponentVariablesinstead ofParameterson 4.4.le.devicehub.CreateBrowseTask: always sendsDeviceBrowseParamsandTaskParams, which Litmus Edge 4.4 requires.- Deprecated: Edge Manager Sites (removed in 3.0), and
lem.admin.ListAuditLogs/ListAuditLogContexts(useListAuditRecords/ListAuditCategories).
Known issues in cli-v1.0.0:
lem.admin.PullRegistryImagestill sends the 2.31 query-string form; Edge Manager 3.0 expects a JSON body.lem.EnableDisableForwardingstill uses GET; Edge Manager 3.0 documents POST.
Install and update
# macOS / Linux: detects platform, verifies SHA256, installs to ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/litmusautomation/litmus-sdk-releases/main/install.sh | sh
# Windows: download litmus-cli-windows-amd64.exe from the latest cli-v* release at
# https://github.com/litmusautomation/litmus-sdk-releases/releases and put it on PATH.
litmus-cli version # print CLI version and build details
litmus-cli update # self-update in place to the latest cli-v* release
Command overview
| Command | Purpose |
|---|---|
litmus-cli list [prefix] |
Browse the SDK function catalog (~1250 functions) with parameter names |
litmus-cli run <dotted.path> |
Call any SDK function by dotted path with JSON arguments |
litmus-cli le <shortcut> |
Curated Litmus Edge shortcuts (devices, tags, flows, containers, ...) |
litmus-cli le data <cmd> |
Data plane: provision credentials (setup), live tag values and tag writes (NATS), time-series history (InfluxDB) |
litmus-cli le exec\|cp\|logs |
Marketplace containers: shell or command, file copy in and out, newest logs with tail, since, grep and follow (cli-v0.12.0+) |
litmus-cli lem <shortcut> |
Curated Edge Manager shortcuts (companies, projects, devices) |
litmus-cli login [le\|lem\|unify] |
Browser-based sign-in; no argument shows all three product cards |
litmus-cli config set/show |
Manage saved connection profiles (~/.litmus/<profile>.json) |
litmus-cli completion <shell> |
Shell completion (bash, zsh, fish, powershell); completes run/list paths too |
litmus-cli version / update |
CLI version / self-update |
Every command and SDK package has built-in docs via --help.
Discover and run any SDK function
The list / run pair is the core workflow, and the reason the CLI works so well
for AI agents: discover the exact function path and arguments, then call it.
# Discover - lists every callable path with argument names
litmus-cli list # top-level packages
litmus-cli list le.devicehub # functions in one package
litmus-cli list lem.Get # filter by any dotted-path prefix
# Read the docs before calling
litmus-cli list le.devicehub --help # full docs for that SDK package
litmus-cli run le.devicehub.ListDeviceTags --help # signature + ready-to-fill --args skeleton
# Run - result is JSON on stdout, errors on stderr
litmus-cli run le.devicehub.ListDevices
litmus-cli run lem.ListIncidents --args '{"projectID": "my-project"}'
litmus-cli run unify.GetNamespace
Litmus Edge packages live under the le. prefix: le.devicehub, le.system,
le.analytics, le.digitaltwins, le.flows, le.integrations, le.marketplace,
le.opc. Edge Manager and Unify paths are lem.* and unify.* with no extra
prefix; the LEM Admin Console (installation-wide settings) is lem.admin.* (cli-v0.13.0+).
Live streams and subscriptions (events, device status, processor output)
take maxEvents/seconds style bounds and return what arrived (cli-v0.13.0+).
Argument keys are camelCase; list <pkg> shows the exact names.
Recommended agent loop: list <prefix> to find the function, run <path> --help
for the argument skeleton, then run <path> --args '{...}'.
Curated shortcuts
Common reads are one short command, no dotted path needed.
Litmus Edge (litmus-cli le ...)
| Shortcut | What it returns |
|---|---|
version |
Device firmware version, API major version, bridge status |
apps |
Installed Edge Applications (from a marketplace catalog) with status and image |
versions |
Every component's version and git commit in one call (DeviceHub, Flows, Analytics, Marketplace, Integrations, OPC UA, Digital Twins, device management, auth, licensing, FTP, UI) |
system-info |
Full firmware build information |
devices |
DeviceHub devices with IDs, driver, running state |
drivers [limit] |
Driver definitions |
tags <deviceID> [limit] |
A device's tags/registers |
users |
Local user accounts |
dt-models / dt-instances |
Digital Twins models / instances |
analytics-groups |
Analytics processor groups |
processor-library |
Analytics processor types (live, falls back to embedded catalog) |
flows |
Node-RED flow services |
containers / images |
Marketplace containers / images |
providers / provider-catalog / instances |
Integration providers and connector instances |
opc-config |
OPC UA server configuration |
processor-library-defaults / provider-catalog-defaults / driver-cache-versions |
Embedded offline catalogs, no connection required |
Litmus Edge Manager (litmus-cli lem ...)
| Shortcut | What it returns |
|---|---|
companies |
Companies visible to the API token |
projects <companyName> |
A company's projects |
devices <projectID> [status] |
A project's devices, optionally filtered (e.g. ACTIVE) |
Anything not covered by a shortcut is reachable through run - the shortcuts and
the dotted paths hit the same SDK underneath.
Data plane: live and historical tag data
litmus-cli le data reaches past the REST API to the device data plane: live tag
values and tag writes through the DataHub broker (NATS, port 4222), and historical values from the
device time-series database (InfluxDB, port 8086, database tsdata). Both
authenticate separately from the REST API; litmus-cli le data --help explains the
credentials.
On a device you administer, le data setup creates those credentials for you and
saves them to the profile, so nothing has to be set up by hand in the LE UI. It
creates or adopts a broker access account, grants it read on the topics you name
(> by default), switches on the device-wide external NATS proxy, and creates or
adopts a time-series DB user with READ on tsdata - then connects to both ports to
prove the credentials work.
# provision everything and save NATS_TOKEN / INFLUX_* to the profile
litmus-cli le data setup
# report what it would create or adopt, changing nothing
litmus-cli le data setup --dry-run
# check whether the credentials currently in effect still work
litmus-cli le data status
Rerunning setup is safe: it adopts the account and DB user it made last time
rather than replacing them, and never resets a credential unless you pass
--reset-key or --reset-db-password. One consequence worth knowing: the device
cannot report an existing DB user's password, so an adopted user leaves
INFLUX_PASSWORD untouched - pass --db-password or --reset-db-password when
you need it rewritten. Secrets are masked in the output unless --show-secrets.
# stream live tag values from the DataHub broker (NATS wildcards work)
litmus-cli le data subscribe 'devicehub.alias.MyDevice.*' --limit 5
# long-running: reconnect after dropped connections or broker restarts
# (cli-v0.11.0+; --limit 0 and --wait 0 mean no limit; values published while disconnected are lost)
litmus-cli le data subscribe 'devicehub.alias.MyDevice.*' --reconnect --limit 0 --wait 0
# list time-series measurements (one per device: <DeviceName>.<DeviceID>)
litmus-cli le data measurements
# query historical rows, newest first, with an optional InfluxQL filter
litmus-cli le data poll 'MyDevice.<deviceID>' --last 15m --filter "\"tag\" = 'Temperature'"
Writing tags
Requires cli-v0.11.0 or later. Run
litmus-cli versionto check andlitmus-cli updateto upgrade; older releases have nole data writeor--write-topics.
le data write <device> <tag> <value> writes a value to a DeviceHub tag and prints
the device's reply. <device> and <tag> are names, as in the tag's
devicehub.write.<device>.<tag> topic (listed in the tag's Topics). <value> is
parsed as JSON when it can be (42, 1.5, true, "text"), otherwise sent as a
string.
# grant the broker account write access once (read on '>' already covers the replies)
litmus-cli le data setup --write-topics 'devicehub.write.>'
litmus-cli le data write MyDevice Setpoint 42.5
# {"success": true, "status": "Good", "statusCode": 0, "timestamp": ..., "writeID": "..."}
The command publishes {"value": ..., "writeID": ...} to
devicehub.write.<device>.<tag> and waits for the matching reply on
devicehub.write_response.<device>.<tag>. It exits non-zero when the device reports
success: false, when no reply arrives within TIMEOUT_SECONDS, or when the broker
refuses the topic (permission denied ... no access), which means the access account
lacks the write or read grant.
Containers: exec, cp, logs
Since cli-v0.12.0 the CLI works inside Marketplace containers on Litmus Edge, the
way docker exec, docker cp and docker logs would. <container> is a name or
a unique ID prefix from litmus-cli le containers.
# interactive shell (bash if the image has it, else sh)
litmus-cli le exec my-app
# one command with its own arguments; exits with the command's status
litmus-cli le exec my-app -- sh -c 'ls -la /data | head'
cat dump.sql | litmus-cli le exec my-db -i -- psql -U postgres
# copy one file in or out; '-' is stdin/stdout; a trailing '/' copies into a directory
litmus-cli le cp ./app.conf my-app:/etc/app/app.conf
litmus-cli le cp ./app.conf my-app:/etc/app/
litmus-cli le cp my-app:/var/log/app.log ./app.log
# newest log output, filtered and as JSON lines
litmus-cli le logs my-app --tail 100
litmus-cli le logs my-app --since 15m --grep '(?i)error|warn'
litmus-cli le logs my-app --since 2026-10-08T09:00:00Z --json
litmus-cli le logs my-app -f
Limits set by Litmus Edge:
- Exec and cp run through
/bin/shin the container, and cp also needsbase64. Distroless and scratch images cannot be exec'd into;le logsstill works. - Exec runs on a TTY, so stdout and stderr arrive merged.
- cp moves one regular file at a time (tar directories first), at roughly 5 to 7 MB/s on a LAN, with flat memory use, and checks the written size.
- Ctrl+C, SIGTERM or a timeout stops the remote command too, and the CLI exits
- If the connection drops instead, the command may keep running in the container.
- Each Litmus Edge log response holds at most 1 MiB and keeps the oldest part.
le logssearches for the newest output that fits and warns on stderr when older output was left out. There are no per-line timestamps and no end time. -fpolls once per second and is best effort: more than 1 MiB between polls is skipped with a warning.
Every one of these commands lists the errors it can return, and what each one
means, under "If something goes wrong" in its --help. Read that before running
them, especially in an agent.
The same operations are callable through run, for scripts and the MCP fallback
tools:
| Path | Arguments | Returns |
|---|---|---|
le.marketplace.ExecOutput |
container, command (argv array) |
{exitCode, output} |
le.marketplace.CopyToContainer |
container, path, content (base64) |
nothing |
le.marketplace.CopyFromContainer |
container, path |
the file, base64 |
le.marketplace.ContainerLogs |
container, since (RFC 3339; omit the key for all) |
{entries: [{stream, text}], since, truncated} |
le.marketplace.ContainerLogTail |
container, lines |
{entries: [{stream, text}], since, truncated} |
le.marketplace.ContainerLog (the single raw response) now returns plain text,
without Docker's stream-frame bytes; it is still the OLDEST 1 MiB.
Configuration
Settings resolve in this order (later overrides earlier):
profile (~/.litmus/<profile>.json) < .env file < environment < flags
# sign in via the browser (writes a profile), or save one by hand
litmus-cli login
litmus-cli config set --EDGE_URL https://10.0.0.5 \
--EDGE_API_CLIENT_ID abc --EDGE_API_CLIENT_SECRET xyz
litmus-cli config show # print a saved profile, secrets masked
# multiple devices via named profiles
litmus-cli run le.devicehub.ListDevices --profile staging
# one-off connection via flags (--insecure for self-signed device certs)
litmus-cli --edge-url https://10.0.0.5 --client-id abc --client-secret xyz --insecure le version
Connection variables
| Connection | Required variables |
|---|---|
| Direct to a Litmus Edge device | EDGE_URL, EDGE_API_CLIENT_ID, EDGE_API_CLIENT_SECRET |
| Edge via the LEM bridge | USE_LEM_BRIDGE=true, EDGE_MANAGER_URL, EDGE_API_TOKEN, EDGE_MANAGER_PROJECT_ID, EDGE_MANAGER_DEVICE_ID |
Edge Manager (lem ...) |
EDGE_MANAGER_URL, EDGE_API_TOKEN |
Unify (unify.*) |
UNS_URL plus UNS_USERNAME/UNS_PASSWORD |
Data plane, live (le data subscribe, le data write) |
NATS_TOKEN (or NATS_USER/NATS_PASSWORD); optional NATS_SOURCE, NATS_PORT, NATS_TLS |
Data plane, historical (le data poll) |
INFLUX_USERNAME, INFLUX_PASSWORD; optional INFLUX_HOST, INFLUX_PORT, INFLUX_DB_NAME, INFLUX_SSL |
Common optional variables: VALIDATE_CERTIFICATE=false (self-signed certs; per-product
overrides exist), TIMEOUT_SECONDS (default 30), LITMUS_CONFIG_DIR (profile
directory, default ~/.litmus). Each variable has a matching flag; run
litmus-cli -h for the full list.
To get Edge credentials: in the Litmus Edge UI navigate to System -> Access Control -> Tokens, create an OAuth 2.0 Client with Admin permissions, and copy the Client ID and Client Secret.
Profiles share the Python SDK CLI's format, so existing ~/.litmus/<profile>.json
files carry over unchanged.
Notes for AI agents
- Prefer this CLI over writing SDK code for one-off operations, diagnostics, and
automation: one command per API call, JSON out,
--helpdocs built in. - Use the MCP server (
https://api.litmus.io/mcp-agents.md) when the user has it configured; its SDK fallback tools are backed by this same CLI. - Never guess dotted paths:
listandrun --helpgive exact paths and camelCase argument keys. - The CLI's dotted paths (
le.devicehub.ListDevices) are NOT the Python import paths. When writing Python, use the snake_case modules documented athttps://api.litmus.io/sdk-agents.md. - Class-based builders such as the air-gap template builder are not exposed by the CLI; use the Python SDK for those.
- Mutations are included (create, update, delete, restart, deploy). Confirm with the user before running destructive commands.
le data setupwrites to the device (an access account, a DB user, and the device-wide NATS proxy switch) and to the local profile. It is idempotent, but run--dry-runfirst when you are not sure what already exists.le data writechanges a live value on the connected equipment (a PLC register, a setpoint). Treat it as a destructive command: confirm the device, tag, and value with the user first.le execandle cpinto a container run as the container's user, usually root, and can change or delete anything inside it. Confirm the container and the command with the user first.le logsis read-only.- Before
le exec,le cporle logs, read the "If something goes wrong" section of its--help: it maps each error message to its cause.
Cross-References
| Need | Go to |
|---|---|
| Download the binary | https://github.com/litmusautomation/litmus-sdk-releases/releases (cli-v* tags) |
| CLI and SDK navigation guide for LLMs | https://api.litmus.io/sdk-agents.md |
| MCP server (tool calls, no shell) | https://api.litmus.io/mcp-agents.md |
| Raw API collection | https://api.litmus.io/agents.md |
| Report a bug or request a feature | https://github.com/litmusautomation/litmus-sdk-releases/issues |
| Product docs | https://docs.litmus.io |