---
title: cmp command-line tool
description: Install and use the cmp CLI served by your own panel: browser login with a one-time code, commands generated from the API, output and exit codes, CI use and signed updates.
url: https://nexcmp.com/docs/developers/cmp-cli/
applies_to: NexCMP 1.6.1
updated: 2026-11-02
---

# `cmp` command-line tool

> **Where in the portal:** the install commands are on the API reference (`https://<your-domain>/apidoc`, section Command-line interface). Approving a login: `https://<your-domain>/link`. Connected devices: API keys (`/api-keys`) › Connected apps & devices.

## What it does

`cmp` is a small command-line program for your customers (and for you) that turns **every API operation into a command**: `cmp vm list`, `cmp vm start <id>`, `cmp billing invoice list`. It is built from the OpenAPI document of **your** installation at release time, so the commands match the features you have enabled. It is one static binary for Linux, macOS and Windows (amd64 and arm64) with nothing else to install.

## Requirements

| Item | Requirement |
|---|---|
| Server | Nothing extra. The release packages are inside the NexCMP release and served by the panel at `https://<your-domain>/cli/`. |
| Customer machine | Linux, macOS or Windows (PowerShell 5.1+). `ssh-keygen` (OpenSSH 8.0+) is needed only to verify the signature. |
| Credentials | A browser login with a one-time code, or an [API key](https://nexcmp.com/docs/developers/api-keys/). |
| Network | HTTPS to your panel. The CLI refuses to send a key over plain `http://` except to `localhost`. |

## Prepare the infrastructure

Nothing. The panel serves these files from `/cli/` (no build or upload needed):

| File | Purpose |
|---|---|
| `install.sh`, `install.ps1` | Installers for Linux/macOS and Windows; they contain your panel's address. |
| `latest.json` | Current version, file list, sizes, sha256. |
| `v<version>/cmp_<version>_<os>_<arch>.tar.gz` or `.zip` | The programs: linux amd64/arm64, darwin amd64/arm64/universal, windows amd64/arm64. |
| `v<version>/SHA256SUMS`, `SHA256SUMS.sig` | Checksums and their ed25519 signature. |
| `cmp-cli.pub` | The release public key. |

## Install (customer)

macOS and Linux:

```bash
curl -fsSL https://cloud.example.com/cli/install.sh | sh
```

Windows PowerShell:

```powershell
irm https://cloud.example.com/cli/install.ps1 | iex
```

The installer picks the package for the OS and CPU, downloads `SHA256SUMS` and its signature, verifies the signature with the key embedded in the script, verifies the package hash, and installs `cmp` into `/usr/local/bin` (as root) or `~/.local/bin`; on Windows into `%LOCALAPPDATA%\cmp\bin` (added to the user `PATH`). If a check fails nothing is installed.

| Variable | Meaning |
|---|---|
| `CMP_VERSION` | Install this version instead of the latest. |
| `CMP_INSTALL_DIR` | Installation folder. |
| `CMP_REQUIRE_SIGNATURE` | `1` = abort when the signature cannot be verified. |
| `CMP_BASE_URL` | Download base (for mirrors). |

Manual download and verification:

```bash
curl -fsSLO https://cloud.example.com/cli/latest.json
sha256sum --check --ignore-missing SHA256SUMS
```

![API reference section with the cmp install command for macOS and Linux](https://nexcmp.com/docs/images/developers/cmp-cli-01-install.webp)

## Log in

```bash
cmp login
```

1. The CLI prints a one-time **code** and a link (`https://cloud.example.com/link?code=WDJB-MJHT`), opens the browser and waits.
2. In the browser sign in to the portal, check the client name, device, IP and country, tick the permissions (scopes) and choose how long the key lives (default 90 days). Permissions that cost money or delete data start unticked. Click approve.
3. The CLI receives **its own key**, separate from keys the customer created by hand, and stores it in `~/.config/cmp/config.json` (mode `0600`; `%APPDATA%\cmp` on Windows). It appears under **API keys › Connected apps & devices** and can be revoked there.

The code expires after 10 minutes. The approval needs a real signed-in portal session with a verified e-mail — not another key and not an impersonated session.

Useful flags: `--scopes vm:read,billing:read`, `--name "build server"`, `--no-browser`, `--profile`, `--api-url`.

For CI or servers without a browser, use a key from the portal:

```bash
printf %s "$KEY" | cmp login --with-token
export CMP_TOKEN=vk_XXXX      # nothing is written to disk
cmp whoami
```

## Using commands

```text
cmp <group> [subgroup] <action> [<id> ...] [flags]
```

- Path parameters are positional arguments; query parameters and body fields become kebab-case flags (`--start-port 443`).
- `--data '{"a":1}'`, `--data @file.json` or `--data -` sends a whole JSON body; flags override its fields.
- `cmp help vm firewall add` (or `--help`) shows the details of any command.

```bash
cmp catalog plans
cmp vm list --state active --per-page 50
cmp vm get 3f2a1c9e-0000-4000-8000-000000000000
cmp vm start 3f2a1c9e-0000-4000-8000-000000000000
cmp vm firewall add 3f2a1c9e-... --protocol tcp --start-port 22 --cidr-list 203.0.113.0/24
cmp billing wallet
cmp api GET /v1/vm --query page=2      # raw call to any endpoint
```

Built-in commands: `login`, `logout`, `whoami`, `config`, `api`, `completion`, `version`, `update`, `help`. Everything else comes from the API document.

Global flags:

| Flag | Meaning |
|---|---|
| `-o, --output json\|table\|yaml` | Format. Default `table` on a terminal and `json` when piped. |
| `--profile`, `--api-url` | Which stored login and which site. |
| `-y, --yes` | Skip confirmation for destructive or paid commands. |
| `--idempotency-key <k>` | Choose the key of a paid command. |
| `--retry <n>` | On HTTP 429 wait for `Retry-After` and retry up to n times. |
| `--timeout <s>` | Seconds to wait for response headers (default 60). |
| `--debug` | Show the HTTP exchange on stderr, with keys masked. |

Commands that **charge the wallet or delete data** ask for confirmation and, if paid, send an automatically generated `Idempotency-Key` (printed on stderr, so you can retry safely with `--idempotency-key`). Without a terminal they refuse unless `--yes` is given.

### Exit codes

| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Other error (network, HTTP 4xx/5xx not listed) |
| 2 | Usage error |
| 3 | Not authorized (401/403) |
| 4 | Not found (404) |
| 5 | Rate limited (429) |
| 6 | Confirmation required or declined |
| 130 | Interrupted |

### Profiles and environment

`cmp config` lists profiles; `cmp config use <name>` switches; a reseller's customers use their own domain: `cmp login --api-url https://shop.example.net --profile shop`. Precedence: flag, environment, config file. Variables: `CMP_TOKEN`, `CMP_PROFILE`, `CMP_API_URL`, `CMP_OUTPUT`, `CMP_CONFIG_DIR`, `CMP_ALLOW_HTTP`, `CMP_UPDATE_URL`.

GitHub Actions:

```yaml
- name: Install cmp
  run: |
    curl -fsSL https://cloud.example.com/cli/install.sh | CMP_INSTALL_DIR="$RUNNER_TEMP/bin" sh
    echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
- name: List running VMs
  env:
    CMP_TOKEN: ${{ secrets.CMP_TOKEN }}   # a read-only key
  run: cmp vm list -o json | jq -r '.items[] | select(.cs_state=="Running") | .hostname'
```

Shell completion: `cmp completion bash|zsh|fish|powershell`.

## Update and uninstall

```bash
cmp version
cmp update --check
cmp update
```

`cmp update` downloads `latest.json`, `SHA256SUMS` and the signature, verifies the signature with the public key **built into the running binary**, verifies the package hash and only then replaces itself. A downgrade needs `--force`. When you update NexCMP, the panel serves the CLI release that ships with the new version.

To uninstall delete the `cmp` binary and the config directory (`cmp config path` shows it). Revoke the key under **API keys** if the machine is lost.

## Verify

1. `cmp version` prints the version and the API document version.
2. `cmp login`, approve in the browser, then `cmp whoami` shows the profile and your panel's URL.
3. `cmp vm list` returns your VMs; `cmp vm list -o json | jq .` shows the raw JSON.

## Limits & notes

- The command list depends on your build: the packages are generated from your installation's OpenAPI document when the release is built, so a product that is disabled in your release has no command. Use `cmp api` for a path the CLI does not know.
- The CLI is under the MIT license.
- Each package is signed with an ed25519 key; the signature key is pinned inside the installer and the binary, not fetched at update time.
- Keys are limited per key and per account (see [REST API](https://nexcmp.com/docs/developers/api/#rate-limits)).

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| `curl .../cli/install.sh` returns 404 | The release on the server has no CLI folder, or the host is not on the license | Check `https://<domain>/cli/latest.json` and the domain; update NexCMP. |
| "signature could not be verified" | `ssh-keygen` missing or too old | Install OpenSSH 8.0+, or set `CMP_REQUIRE_SIGNATURE=0` only if you accept the risk. |
| `cmp login` says the code expired | 10 minutes passed | Run `cmp login` again. |
| Exit code 3 | Key lacks a scope, expired or revoked | `cmp whoami`; create or re-approve with more scopes. |
| Exit code 6 in a script | Paid or destructive command without a terminal | Add `--yes` (and your own `--idempotency-key`). |
| "refuses to send a key over http" | Plain http API URL | Use `https://`, or `CMP_ALLOW_HTTP=1` only for a lab. |
| Browser opens the wrong site | `--api-url` not set for a reseller | `cmp login --api-url https://<reseller-domain>`. |


