---
title: Litmus CLI Reference
slug: sdk/litmus-cli-reference
description: litmus-cli is the standalone command-line client for Litmus Edge, Edge Manager, and Unify. It exposes the full Litmus SDK surface of about 570 functions as shell commands with JSON output, ideal for AI agents, CI pipelines, scripting, and API exploration.
docTags: 
createdAt: 2026-05-08T21:27:20.325Z
---

`litmus-cli` is a standalone command-line binary that exposes the full Litmus SDK surface (more than 600 functions, including all mutations, Litmus Edge Manager, and Litmus Unify) without writing Python. Useful for AI agents, CI pipelines, and interactive exploration.

The CLI is no longer installed with the `litmussdk` Python package. It is built from the Litmus Go SDK and released on [litmus-sdk-releases](https://github.com/litmusautomation/litmus-sdk-releases/releases) under `cli-v*` tags, with binaries for macOS arm64, Linux amd64/arm64, and Windows amd64, plus a `SHA256SUMS` file.

New to the CLI? Start with [Getting started with the CLI](#). Driving it from an AI agent? See [Using the CLI with AI agents](#).

## Install

There are two ways to run the CLI. Both run the same binary and accept the same commands.

|                | Option 1: on your machine          | Option 2: Litmus CLI Web on Litmus Edge                                           |
| -------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
| Where it runs  | your laptop, a server, a CI runner | a container on the Litmus Edge device                                             |
| How you use it | your own terminal                  | a browser, at `http://<device>:4004`                                              |
| Install        | one command, or download a binary  | launch from the Litmus Edge Marketplace                                           |
| Best for       | scripts, CI pipelines, AI agents   | quick access with nothing to install, devices only reachable on the plant network |

### Option 1: install on your machine

### macOS / Linux (recommended)

```bash
curl -fsSL https://raw.githubusercontent.com/litmusautomation/litmus-sdk-releases/main/install.sh | sh
```

The script detects your OS and architecture, downloads the latest `cli-v*` release, verifies the SHA256 checksum, and installs to `~/.local/bin`. Make sure `~/.local/bin` is on your `PATH`.

Note for macOS: install via curl as shown above. Binaries downloaded through a browser are quarantined by Gatekeeper and will refuse to run; if that happens, clear the flag with `xattr -d com.apple.quarantine <path-to-binary>`.

### Manual install (and Windows)

1. Download the `litmus-cli-<os>-<arch>` asset for your platform from the [latest cli-v\* release](https://github.com/litmusautomation/litmus-sdk-releases/releases) (`litmus-cli-windows-amd64.exe` on Windows), or from the solution page on [litmus.io/solutions/litmus-cli](https://litmus.io/solutions/litmus-cli).
2. Verify it against the `SHA256SUMS` file from the same release.
3. Rename it to `litmus-cli` (`litmus-cli.exe` on Windows), make it executable, and move it into a directory on `PATH` (e.g. `~/.local/bin`).

### Option 2: Litmus CLI Web on Litmus Edge

A browser terminal with `litmus-cli` and `jq` preinstalled, deployed as a Marketplace app on the Litmus Edge device itself.

1. In Litmus Edge, open **Applications > Marketplace** and launch **Litmus CLI Web**. Keep the ports at **4004** (terminal) and **4005** (sign-in page).
2. Open `http://<device-address>:4004`.
3. Run `litmus-cli login`, open the printed `https://<this-machine>:4005/...` address with `<this-machine>` replaced by the device address, accept the one-time certificate warning, and sign in.

Sign-in state survives redeploys. Full details: [Litmus CLI Web](#).

### Updating

Once installed, either way, the CLI can update itself in place with `litmus-cli update`.

If you previously used the pip-installed CLI, note that older `litmussdk` versions leave a `litmus-sdk-cli` entry point in the environment's `bin/` directory. It does not conflict with the downloaded `litmus-cli` binary, but you can remove it by upgrading the `litmussdk` package.

## Migrating from the pip-installed CLI

The command was renamed from `litmus-sdk-cli` to `litmus-cli`, and this is a clean break on the invocation contract: function paths and JSON argument keys differ.

| Old (Python CLI)                                                       | New (Go CLI)                                         |
| ---------------------------------------------------------------------- | ---------------------------------------------------- |
| `run devicehub.devices.list_devices`                                   | `run le.devicehub.ListDevices`                       |
| `run lem.lifecycle.alerts.list_incidents --args '{"project_id": "X"}'` | `run lem.ListIncidents --args '{"projectID": "X"}'`  |
| `run uns.namespace.get_namespace`                                      | `run unify.GetNamespace`                             |
| nested snake\_case module paths                                        | flat `<product>.<package>.<PascalCaseMethod>`        |
| snake\_case JSON arg keys                                              | camelCase JSON arg keys (see `list <pkg>` for names) |

Litmus Edge packages are grouped under the `le.` prefix (`le.devicehub`, `le.system`, `le.analytics`, `le.digitaltwins`, `le.flows`, `le.integrations`, `le.marketplace`, `le.opc`). `lem.*` and `unify.*` paths are unchanged.

`litmus-cli list [prefix]` browses every callable path with its argument names. If you pass an old-style path to `run`, the CLI prints a pointer to the migration guide and a suggested new path (e.g. `lem.lifecycle.alerts.list_incidents` suggests `lem.ListIncidents`), so old scripts fail with an explanation rather than silently.

Saved connection profiles are unaffected: existing `~/.litmus/<profile>.json` files written by the old CLI load unchanged.

## Setup

### 1. Configure a connection

Sign in via the browser (writes a profile), or save one by hand:

```bash
# Browser-based sign-in; no argument shows all three product cards
litmus-cli login [le|lem|unify]

# Direct connection (OAuth2)
litmus-cli config set \
  --EDGE_URL https://<device-ip> \
  --EDGE_API_CLIENT_ID <client-id> \
  --EDGE_API_CLIENT_SECRET <client-secret>

# LEM bridge
litmus-cli config set \
  --EDGE_MANAGER_URL https://<lem-url> \
  --EDGE_API_TOKEN <token> \
  --EDGE_MANAGER_PROJECT_ID <project-id> \
  --EDGE_MANAGER_DEVICE_ID <device-id> \
  --USE_LEM_BRIDGE true
```

Profiles are saved to `~/.litmus/<profile>.json`. The default profile is named `default`. To use multiple devices, pass `--profile <name>` to any command.

Environment variables take precedence over profiles: set `EDGE_URL`, `EDGE_API_CLIENT_ID`, `EDGE_API_CLIENT_SECRET` (or the LEM bridge variables) in the shell to override any saved profile.

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.

For full env var details and the three connection modes, see [Managing Connections](#).

Supported keys for `config set`:

| Flag                        | Description                                               |
| --------------------------- | --------------------------------------------------------- |
| `--EDGE_URL`                | Litmus Edge device URL                                    |
| `--EDGE_API_CLIENT_ID`      | OAuth 2.0 Client ID                                       |
| `--EDGE_API_CLIENT_SECRET`  | OAuth 2.0 Client Secret                                   |
| `--EDGE_MANAGER_URL`        | Litmus Edge Manager URL                                   |
| `--EDGE_MANAGER_ADMIN_URL`  | LEM admin URL (optional)                                  |
| `--EDGE_API_TOKEN`          | LEM API token (used by direct LEM and LEM bridge)         |
| `--EDGE_MANAGER_PROJECT_ID` | LEM project ID (for bridge mode)                          |
| `--EDGE_MANAGER_DEVICE_ID`  | LEM device ID (for bridge mode)                           |
| `--USE_LEM_BRIDGE`          | `true` to route LE calls through LEM                      |
| `--VALIDATE_CERTIFICATE`    | `false` to disable TLS verification                       |
| `--TIMEOUT_SECONDS`         | Request timeout in seconds                                |
| `--NATS_TLS`                | `false` when the device's DataHub broker does not use TLS |

### 2. (Optional) Enable tab completion

```bash
litmus-cli completion bash   # or zsh, fish, powershell
```

Add the printed setup line to `~/.bashrc` or `~/.zshrc` to persist across sessions. Completion also completes `run` and `list` dotted paths.

## Commands

### litmus-cli run

Call any SDK function by its dotted path. Result is JSON on stdout.

```bash
# No arguments
litmus-cli run le.devicehub.ListDevices

# With arguments (JSON object, camelCase keys)
litmus-cli run lem.ListIncidents --args '{"projectID": "X"}'

# Named profile
litmus-cli run le.devicehub.ListDevices --profile staging

# Function signature and docs, with a ready-to-fill --args skeleton
litmus-cli run le.devicehub.ListDevices --help
```

Litmus Edge SDK packages live under the `le.` prefix (`le.devicehub`, `le.system`, `le.analytics`, `le.digitaltwins`, `le.flows`, `le.integrations`, `le.marketplace`, `le.opc`); `lem.*` and `unify.*` paths have no prefix.

Results are printed as JSON on stdout; errors go to stderr. Run `litmus-cli run -h` for the full flag list.

### litmus-cli list

Browse available packages and functions. This is the canonical way to discover what the SDK can do (more than 600 functions).

```bash
# List all packages
litmus-cli list

# List functions in a package, with argument names
litmus-cli list le.devicehub
litmus-cli list lem

# Print a package's SDK docs
litmus-cli list le.devicehub --help
```

### litmus-cli config

Manage saved connection profiles.

```bash
litmus-cli config set --EDGE_URL https://10.0.0.1 --EDGE_API_CLIENT_ID id --EDGE_API_CLIENT_SECRET secret
litmus-cli config show
litmus-cli config show --profile staging   # secrets masked
```

### Curated product commands

Beyond the generic dispatcher, common operations are grouped under product subcommands:

```bash
litmus-cli le devices        # DeviceHub devices
litmus-cli le tags <id>      # one device's tags
litmus-cli le versions       # every component running on the device
litmus-cli lem companies     # Litmus Edge Manager companies
```

Run `litmus-cli le -h` or `litmus-cli lem -h` to browse each group.

### litmus-cli le data

Live and historical tag values travel on the DataHub broker (NATS) and the time-series database (InfluxDB), which authenticate separately from the REST API.

```bash
# provision a broker account and a DB user once, saved to the profile
litmus-cli le data setup
litmus-cli le data setup --dry-run      # report what it would create, changing nothing
litmus-cli le data status               # check the saved credentials still work

# stream live tag values (NATS wildcards work)
litmus-cli le data subscribe 'devicehub.alias.<DeviceName>.*' --limit 10

# history: one measurement per device, named <DeviceName>.<DeviceID>
litmus-cli le data measurements
litmus-cli le data poll '<DeviceName>.<DeviceID>' --last 15m --filter "\"tag\" = '<TagName>'"

# write a tag and wait for the device's reply (needs write topics, see --help)
litmus-cli le data write <DeviceName> <TagName> <value>
```

`le data write` changes a live value on connected equipment. Treat it as a destructive command.

### litmus-cli le exec, cp and 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 container name or a unique ID prefix from `litmus-cli le containers`.

```bash
# interactive shell (bash if the image has it, else sh)
litmus-cli le exec <container>

# one command with its own arguments; the CLI exits with the command's status
litmus-cli le exec <container> -- sh -c 'ls -la /data | head'
cat dump.sql | litmus-cli le exec <container> -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 <container>:/etc/app/
litmus-cli le cp <container>:/var/log/app.log ./app.log

# newest log output
litmus-cli le logs <container> --tail 100
litmus-cli le logs <container> --since 15m --grep '(?i)error|warn'
litmus-cli le logs <container> --since 2026-10-08T09:00:00Z --json
litmus-cli le logs <container> -f
```

What to expect:

- Exec and cp run through `/bin/sh` inside the container, and cp also needs `base64`. Images without a shell (distroless, scratch) cannot be exec'd into, but `le logs` still works for them.
- Exec runs on a terminal, so a command's normal output and its errors arrive together.
- cp copies one regular file at a time (tar a directory first), at roughly 5 to 7 MB/s on a local network. It checks the size of the file it wrote, and a failed or interrupted copy leaves no partial file on your machine.
- Ctrl+C on a command stops it inside the container too. If the network connection drops instead, the command may keep running in the container.
- Litmus Edge returns at most 1 MiB of log per request. `le logs` finds the newest output that fits and prints a warning when older output was left out; narrow it with `--since` or `--tail`. Log lines carry no timestamps of their own, so log them in your application if you need them.
- `le logs -f` checks for new output once per second and is best effort: a burst of more than 1 MiB between checks is skipped, with a warning.

Each of these commands lists the errors it can return, and what each one means, under "If something goes wrong" in its `--help`.

:::BlockQuote
**Safety.** `le exec` and `le cp` act inside the container as its own user, which is usually root. They can change or delete anything in the container, including the configuration of an application that is running production work. Prefer `le logs` for diagnosis, rehearse on a test device, and confirm the container and the command before running either on a production Litmus Edge.
:::

### litmus-cli version and litmus-cli update

`litmus-cli version` prints the CLI's own version and build details; `litmus-cli update` self-updates in place to the latest `cli-v*` release. To get the Litmus Edge device firmware version, use `litmus-cli le version`.

### litmus-cli completion

Print the shell completion script (bash, zsh, fish, powershell).

Run `litmus-cli -h` for full usage. Every command and SDK package has built-in docs via `--help`.

## Using With AI Agents

`litmus-cli` is designed for use by AI agents and is the preferred method for agentic tasks. Key properties:

- **Structured output**: results are always JSON on stdout, errors on stderr.
- **Discoverable**: `litmus-cli list` enumerates every callable function.
- **Self-describing**: `litmus-cli list <package>` shows argument names, and `run <path> --help` prints the signature with a ready-to-fill `--args` skeleton.
- **Composable**: pipe JSON output to `jq` or any other tool.

Typical agent workflow:

```bash
# 1. Discover what's available
litmus-cli list

# 2. Inspect a package
litmus-cli list le.devicehub

# 3. Read the function docs
litmus-cli run le.devicehub.ListDevices --help

# 4. Call the function and parse the JSON result
litmus-cli run le.devicehub.ListDevices | jq '.[0].ID'
```

Setup, permissions and example prompts: [Using the CLI with AI agents](#). The full agent guide (with package mappings and patterns) lives at [api.litmus.io/cli.md](https://api.litmus.io/cli.md).

Scope note: the air-gap template builder (`litmussdk.airgap_features.AirGapTemplate`) is class-based and Python-only; it is not exposed by the CLI. Drive it from Python and use the CLI for the surrounding live-data fetches.

## DeviceHub Driver Records (Python package)

These helpers manage the Python SDK's own driver-record cache and still ship with the `litmussdk` pip package (they are unrelated to `litmus-cli`):

```bash
download_dh_record   # download for current EDGE_URL version
list_dh_versions     # list available cached versions
get_dh_cache_dir     # show where records are cached
```

`litmus-cli` handles driver-record downloads internally; no manual step is needed when using it.

## License

Copyright (c) Litmus Automation Inc.
