Skip to main content

Documents ZigTSDB v1.5.0 · applies to the 1.5.x line

CLI Reference

zigtsdb-cli is the command-line client for a running Anzaran server: querying, ingestion, monitoring, and cluster operations.

Installation

The CLI ships inside the Docker image at /app/zigtsdb-cli — no separate install step. On a running deployment, invoke it with:

$ docker exec -it anzaran /app/zigtsdb-cli <command>

Replace anzaran with your container name. A native binary download is planned.


Synopsis

zigtsdb-cli <command> [args] [options]

Flags after the command name belong to the command (e.g. cluster preflight --peers ...); unknown flags before a command are an error.

Note. The CLI sends no Authorization header on data commands. Against a server with JWT auth enabled (TSDB_AUTH_SECRET set), gated commands return Error: HTTP 401. The exceptions are backup and license activate, which read an admin token from TSDB_AUTH_TOKEN when auth is on. The CLI speaks plain HTTP and presents no client certificate — behind the secure overlay, use curl or a client library against a node's sidecar.

Global Options

Option Short Description Default
--endpoint <url> -e Server endpoint URL http://localhost:8080
--format <fmt> -f Output format: table, json, csv table
--verbose -V Verbose output off
--help -h Show help
--version -v Show version

query

Execute a ZQL query via GET /query.

$ zigtsdb-cli query "SELECT avg(value) FROM cpu"
$ zigtsdb-cli query "SELECT avg(value) FROM cpu WHERE time > now() - 5m"
$ zigtsdb-cli query "SELECT avg(value) FROM t GROUP BY time_bucket(time, 1h)"
$ zigtsdb-cli query "SELECT rate(value) FROM requests WHERE host =~ 'web-.*'"
$ zigtsdb-cli query "SELECT percentile(value, 95) FROM latency GROUP BY region"
$ zigtsdb-cli query "SELECT count(value) FROM events" --format json
$ zigtsdb-cli query "SELECT max(value) FROM metrics" -e http://prod:8080

ingest

Ingest line protocol from a file or stdin (-). --batch posts to /ingest/batch (JSON batch body) instead of /ingest. Limits: 10 MB from stdin, 100 MB from file.

$ zigtsdb-cli ingest data.lp
$ cat data.lp | zigtsdb-cli ingest -
$ echo "cpu,host=web-1 value=42.5 1704067200000000000" | zigtsdb-cli ingest -

Line protocol format (up to 16 labels per line, timestamps in Unix nanoseconds):

<metric>[,<label>=<value>...] value=<float> <timestamp_ns>

metrics, stats, usage, prometheus

Command Description
metrics List metric names (GET /metrics)
stats Database statistics (GET /stats): points, metrics, cache entries
usage Usage statistics (GET /usage)
prometheus Print the server's Prometheus exposition (GET /metrics/prometheus)

raw-points, verify

raw-points [--metric <m>] [--limit <n>] fetches raw points (GET /raw_points). This is a scoped internal endpoint on the server (block-transfer auth); on a server with internal auth configured — or fail-closed unconfigured — it returns 401. Also accepted as raw_points.

verify runs a data-integrity check (GET /verify): local vs S3 series counts.


compact

compact triggers compaction (POST /compact); compact --status reads its status (GET /compact/status).

scheduler

$ zigtsdb-cli scheduler status
$ zigtsdb-cli scheduler run compaction
  • status — background-job summary (GET /scheduler/status).
  • run <job> — force-run a job. Jobs: compaction, purge, index_flush, tombstone_gc, retention_purge, orphan_block_gc.
Known limitation. scheduler enable / disable send POST /scheduler/enable without a job name, but the server only routes per-job paths, so these two subcommands currently get 404. Use curl -X POST "$EP/scheduler/enable/<job>?enabled=false" instead.

retention, delete

retention --days <N> [--metric <m>] sends POST /retention. The server treats this as an immediate purge and ignores the body — so this command triggers a purge; it does not set a policy. Set retention policies with PUT /retention on the HTTP API.

delete --metric <name> [--before <timestamp>] deletes a metric (DELETE /delete?metric=...). The server deletes all data for the metric; --before is transmitted but not evaluated server-side.

backup

$ zigtsdb-cli backup create
$ zigtsdb-cli backup list
$ zigtsdb-cli backup prune --keep 3
$ zigtsdb-cli backup verify /data/backups/<id>
$ zigtsdb-cli backup restore /data/backups/<id> --into /data \
    [--data-dir <dir>] [--force] [--skip-raft]
  • create (POST /backup), list (GET /backup) and prune --keep N (keeps the N newest; --keep 0 is refused) talk to the server; they need an admin token via TSDB_AUTH_TOKEN when auth is on.
  • verify and restore are offline: verify recomputes every CRC in MANIFEST.json and exits 1 naming the first bad or missing file; restore verifies first, refuses a non-empty target unless --force, copies every file back and fsyncs; --skip-raft omits Raft state so the node rejoins a live cluster.

A backup is the node's own point-in-time state (sealed files, WAL tail, Raft state, metadata) under <TSDB_WAL_DIR>/backups/<id>/; S3 blocks are not included. It lives on the same volume, so copy it off-node if it must survive the host.

license, profile

$ zigtsdb-cli license
$ zigtsdb-cli license activate --key-file /run/secrets/anzaran_license
$ cat key.txt | zigtsdb-cli license check -
  • license — the node's license status (GET /license: tier, licensed_to, expiry, meter).
  • license activate <key> | --key-file <path> | - — installs a key (POST /license/activate; admin token via TSDB_AUTH_TOKEN when auth is on) and reports whether it was persisted.
  • license check <key> | --key-file <path> | - — validates a key without installing it (GET /license?key=).

Prefer --key-file or - (stdin) over a key on the command line, which is visible in ps and shell history. Keys and tiers: License & tiers.

profile "<ZQL>" sends GET /profile?zql=.... The server does not route /profile, so this returns 404.


cluster

HA operations against a Raft cluster.

Subcommand Description
cluster status GET /cluster/status — cluster health, node list, versions, shard groups
cluster flush POST /flush — flush the memtable to S3
cluster sync POST /sync — replay this node's WAL segments from S3
cluster rebalance POST /rebalance — report the current shard assignment

cluster add-node / remove-node

Raft membership changes. Require TSDB_RAFT_ADMIN_TOKEN in the environment (deliberately not a CLI flag — argv leaks via ps and shell history). If the request hits a follower, the CLI follows the 503 leader_url hint and retries once against the leader; any further non-200 is surfaced.

$ TSDB_RAFT_ADMIN_TOKEN=... zigtsdb-cli cluster add-node http://node3:8080
$ TSDB_RAFT_ADMIN_TOKEN=... zigtsdb-cli cluster remove-node 3

cluster preflight

Decide whether a rolling upgrade to this CLI binary's version is safe. The CLI's compiled-in protocol window is compared against every node's advertised window; any FAIL line makes the command exit non-zero, and the upgrade must not proceed.

$ TSDB_RAFT_ADMIN_TOKEN=... zigtsdb-cli cluster preflight \
    --peers http://node0:8080,http://node1:8080,http://node2:8080 \
    [--max-apply-lag N] [--skip-migration-check]

Peers come from --peers, else TSDB_PEERS, else the configured endpoint. Checks: node health, protocol-window overlap, routing-epoch agreement with no staged entries, topology-epoch agreement, no active data migration (needs TSDB_RAFT_ADMIN_TOKEN; bypass only with --skip-migration-check), per-node apply lag within --max-apply-lag (default 0), and uniform secure-mode posture.

preflight: candidate protocol 1 (min-compatible 1), 3 peer(s)
PASS: http://node0:8080 healthy
PASS: http://node0:8080 protocol window [1,1] compatible
PASS: http://node0:8080 routing epoch 4 agrees
PASS: no active migration
PASS: http://node0:8080 apply lag 0 <= 0
...
preflight: PASS — safe to roll this binary

Output Formats

  • table (default) — human-readable.
  • json — raw server JSON, for scripting (... --format json | jq).
  • csv — comma-separated, for spreadsheet import.

Exit Codes

Code Meaning
0 Success
2 Invalid arguments
non-zero Failed command (e.g. HTTP error, unreachable server, preflight FAIL)

Examples

# Watch a live aggregate
$ watch -n 1 'zigtsdb-cli query "SELECT avg(value) FROM cpu WHERE time > now() - 1m"'

# Hourly rollup to CSV
$ zigtsdb-cli query \
    "SELECT avg(value) FROM cpu GROUP BY time_bucket(time, 1h)" \
    --format csv > hourly_cpu.csv

# Cluster health gate for scripts
$ zigtsdb-cli cluster status --format json | jq -e '.status == "healthy"'

# Bulk ingest
$ for f in data/*.lp; do zigtsdb-cli ingest "$f"; done

See also