Synadia Insights
CLI
The insights binary is a single command with several subcommands. Running insights with no subcommand starts the server — equivalent to insights serve (run is a kept alias). The client subcommands (query, db, checks, and the ops group) talk to an already-running server over NATS. The web, mcp, and http subcommands each run their own long-lived process that connects to a running node as a NATS client.
Synopsis
insights [flags] [subcommand] [subcommand-flags]
| Subcommand | Purpose |
|---|---|
(default) serve (alias run) | Start the Insights server. |
web | Run only the web tier, as a NATS client of a remote indexer/scraper node. |
mcp | Run a read-only Model Context Protocol server exposing the db and checks tools to AI agents. |
http | Run a stateless HTTP gateway fronting the read-only DB query API for HTTP-only clients. |
query | Run a SQL query against the embedded DuckDB over the NATS API. |
db explain <SQL> | Validate and plan (or profile) a SQL statement without running a full query. |
db schemas / tables / columns / macros | Discover the queryable schemas, tables, columns, and macros. |
checks list | List all available audit checks grouped by category. |
checks info <CODE> | Show full metadata and configurable parameters for one check. |
checks findings <CODE> | Run one audit check and return its findings. |
ops backup | Create a consistent database snapshot and download it. |
ops sizing | Recommend a DuckDB memory_limit / threads pair for the running instance. |
ops memory | Show the live DuckDB memory profile (current and peak by component). |
ops pprof | Capture a runtime profile from the running instance for diagnostics. |
--version | Print the binary version and exit. |
Configuration precedence
When a setting is defined in more than one place, the highest-priority source wins:
- Command-line flags
- Environment variables (
INSIGHTS_*) - YAML config file (
--config/-c) - Built-in defaults
Environment variables mirror the flag path: dots become underscores, everything is uppercased, and the INSIGHTS_ prefix is added. For example, --web.port becomes INSIGHTS_WEB_PORT, and --sys.server becomes INSIGHTS_SYS_SERVER.
Top-level flags
These flags apply to every subcommand.
| Flag | Env | Default | Description |
|---|---|---|---|
--log-level | INSIGHTS_LOG_LEVEL | info | Log level: debug, info, warn, error. |
--server | INSIGHTS_NATS_SERVER | nats://127.0.0.1:4222 | NATS server URL used by subcommands (query, db, checks, and the ops group) to reach the Insights API. |
--creds | INSIGHTS_NATS_CREDS | (empty) | Path to a NATS credentials file. |
--context | INSIGHTS_NATS_CONTEXT | (empty) | NATS CLI context name (resolved via ~/.config/nats/). |
These are nats-CLI-style flags; the pre-rename --nats.* forms (--nats.server, --nats.creds, --nats.context, --nats.tls-ca-cert) remain as aliases. Their environment variables keep the INSIGHTS_NATS_ prefix (for example --server reads INSIGHTS_NATS_SERVER).
See Configuration > nats.* for the full connection reference (TLS, auth, socks proxy).
insights serve
Default subcommand. Starts the Insights server: scraper, indexer, web UI, sink, backup scheduler, and the NATS API endpoints. run is a backward-compatible alias, so insights run and a bare insights both start the server.
insights serve [flags]
Because serve is the default, you can omit the subcommand name:
insights --config /etc/insights/config.yaml
Flags
serve owns every server-only subsystem flag. Rather than duplicate them all here, see the Configuration reference. Each subsystem (scraper, indexer, web, sink, simulator, backup, database, license, and so on) has its own section there.
Frequently used flags:
| Flag | Env | Default | Description |
|---|---|---|---|
--config / -c | (none) | (empty) | Path to YAML config file. |
--data-dir | INSIGHTS_DATA_DIR | (temp dir) | Base directory for DuckDB and JetStream data. |
--simulator.enabled | INSIGHTS_SIMULATOR_ENABLED | false | Run against the built-in simulator instead of a real NATS system. License validation is skipped when enabled. |
--sys.server | INSIGHTS_SYS_SERVER | (empty) | NATS URL of the target system to scrape. |
--sys.creds | INSIGHTS_SYS_CREDS | (empty) | NATS credentials file for the target system. |
--web.hostname | INSIGHTS_WEB_HOSTNAME | 127.0.0.1 | Web UI bind address. |
--web.port | INSIGHTS_WEB_PORT | 8080 | Web UI bind port. |
--license.token | INSIGHTS_LICENSE_TOKEN | (empty) | License JWT string. |
--license.file | INSIGHTS_LICENSE_FILE | (empty) | Path to a file containing the license JWT. |
Example
insights \
--config /etc/insights/config.yaml \
--license.file /etc/insights/license.jwt \
--web.hostname 0.0.0.0
insights web
Runs only the web tier — no indexer, scraper, or simulator, and no embedded NATS server — so the process holds no local state and serves the UI entirely from data it reaches over NATS. Point it at the node running the indexer and scraper with --server (or --context); that node owns the DuckDB and serves the $INS.db.* / $INS.ops.* endpoints this tier consumes. The instance's capabilities — geo enrichment, the realtime advisory feed, the scrape interval, retention, and the license — are discovered from that node over $INS.ops.info (see the API reference), so none of it needs to be configured locally. A web-only node validates no license of its own; it renders the backend's.
Because it is a pure client of the API, it exposes only the flags a web tier uses — the web server (--web.*), the Prometheus endpoint (--prometheus.*), the updater (--updater.*), and the top-level connection flags. The full server configuration lives on insights serve.
insights web [flags]
Example
# Node A — indexer + scraper, no web, embedded NATS on a fixed port:
insights --web=false --sink.port=4222 --data-dir /var/lib/insights
# Node B — stateless web tier pointing at Node A:
insights web --server nats://node-a:4222 --web.hostname 0.0.0.0 --web.port 8080
insights mcp
Runs a read-only Model Context Protocol server that exposes ten tools over the db and checks endpoints for AI agents. Like query, it owns no database: it forwards each tool call to a running Insights node over NATS and is read-only by construction, so pointing an agent at a production instance is safe. For client setup (Claude Desktop, Claude Code, Cursor) and the full tool list, see the AI Agents guide.
insights mcp [flags]
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--transport | INSIGHTS_MCP_TRANSPORT | stdio | stdio for a client-spawned subprocess, or http for a long-running Streamable HTTP service. |
--http | INSIGHTS_MCP_HTTP | 127.0.0.1:8090 | Listen address when --transport http. |
--http-tls | INSIGHTS_MCP_HTTP_TLS | false | Serve the http transport over HTTPS. Requires --http-tls-cert and --http-tls-key. |
--timeout | INSIGHTS_MCP_TIMEOUT | 2m | Per-tool NATS request timeout. |
Plus the top-level connection flags for reaching the node.
Example
# Local stdio server, launched by an MCP client:
insights mcp --context my-nats-context
# Long-running HTTP service:
insights mcp --transport http --http 127.0.0.1:8090
insights http
Runs a stateless HTTP gateway that fronts the read-only db query API over plain HTTP, so an HTTP-only client — a BI or dashboard datasource, a script, another service — can query Insights without a NATS client. Like web, it owns no database: each HTTP request is translated into the matching $INS.db.* NATS request and the reply is returned as-is, so the read-only guard, the row cap, and per-account NATS auth all stay enforced upstream. See the HTTP gateway section of the API reference for the route map.
Point it at the node serving the $INS.db.* endpoints with --server (or --context), exactly like query. It adds a bearer token at its own edge and refuses to start without one unless --allow-unauthenticated is given.
insights http [flags]
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--listen | INSIGHTS_HTTP_LISTEN | 127.0.0.1:8080 | HTTP listen address. Use 0.0.0.0:<port> to accept remote connections (e.g. behind a TLS-terminating ingress). |
--auth-token | INSIGHTS_HTTP_AUTH_TOKEN | (empty) | Bearer token required on every request except /healthz (Authorization: Bearer <token>). Required unless --allow-unauthenticated. |
--allow-unauthenticated | INSIGHTS_HTTP_ALLOW_UNAUTHENTICATED | false | Run without a bearer token. Only for trusted, network-isolated deployments — never for public exposure. |
--timeout | INSIGHTS_HTTP_TIMEOUT | 1m | Per-request NATS request timeout. |
--max-body-bytes | INSIGHTS_HTTP_MAX_BODY_BYTES | 1048576 | Maximum request body size in bytes. |
Plus the top-level connection flags for reaching the node that serves $INS.db.*.
Example
# Run the gateway pointed at an Insights node, with a bearer token:
export INSIGHTS_HTTP_AUTH_TOKEN=$(openssl rand -hex 32)
insights http \
--server nats://insights.example.com:4222 \
--creds ~/.config/nats/query.creds \
--listen 0.0.0.0:8080
# Query it over HTTP:
curl -s localhost:8080/db/query \
-H "Authorization: Bearer $INSIGHTS_HTTP_AUTH_TOKEN" \
-d '{"sql":"SELECT name, cpu FROM hx.servers ORDER BY cpu DESC LIMIT 10"}'
insights query
Send a SQL query to the running Insights server over NATS and write the result to stdout. See the Search reference for the Insights query language. Use query for arbitrary DuckDB SQL against the hx schema.
insights query [flags] [SQL]
The SQL statement can be passed as a positional argument or piped on stdin. If both are omitted, the command exits with an error.
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--format / -f | (none) | csv | Output format: csv or json. |
--timeout | (none) | 30s | NATS request timeout. |
Plus the top-level connection flags for reaching the server.
Examples
Inline SQL:
insights query "SELECT name, cpu FROM hx.servers ORDER BY cpu DESC LIMIT 10"
SQL via stdin:
cat query.sql | insights query --format json
Against a remote Insights server:
insights --server nats://insights.example.com:4222 \
--creds ~/.config/nats/ops.creds \
query "SELECT COUNT(*) FROM hx.connections"
insights db
Inspect the database without writing a full query: validate and plan (or profile) a statement, and discover the queryable schemas, tables, columns, and macros. These subcommands mirror the $INS.db.* discovery endpoints (see the API reference) and are scoped to the allowlisted schemas (hx, main, audit). The discovery commands read catalog metadata only and scan no data; db explain --analyze is the exception, since it executes the query to gather runtime timing. All of it is read-only, like query.
insights db explain [flags] [SQL]
insights db schemas [flags]
insights db tables [flags]
insights db columns [flags]
insights db macros [flags]
Flags
| Flag | Default | Description |
|---|---|---|
--format / -f | text | Output format. explain: text or json; the discovery commands also accept csv. |
--analyze / -a | false | (explain) Execute the query with EXPLAIN ANALYZE and include per-operator runtime timing. |
--schema | (none) | (tables, columns, macros) Restrict to one schema. Omit to span all allowlisted schemas. |
--table | (none) | (columns) Restrict to one table or view. |
--timeout | 30s | NATS request timeout. |
Plus the top-level connection flags. explain takes the SQL as a positional argument or on stdin, like insights query.
Examples
Discover schemas, then drill into one:
insights db schemas
insights db tables --schema hx
insights db columns --schema hx --table servers
insights db macros --schema audit
Plan a query before running it, or execute and profile it with --analyze:
insights db explain "SELECT name, cpu FROM hx.servers ORDER BY cpu DESC LIMIT 10"
insights db explain --analyze "SELECT name, cpu FROM hx.servers ORDER BY cpu DESC LIMIT 10"
insights checks list
List every audit check the server knows about, grouped by category. Default output is an aligned text table; pass --format for CSV or JSON.
insights checks list [flags]
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--format / -f | (none) | text | Output format: text, csv, or json. |
--timeout | (none) | 30s | NATS request timeout. |
Example
insights checks list --format json | jq '.[] | .label'
insights checks info
Show the full metadata for a single check: description, severity, scope, and any tunable parameters with their default and currently resolved values.
insights checks info [flags] <CODE>
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--format / -f | (none) | text | Output format: text or json. |
--timeout | (none) | 30s | NATS request timeout. |
Example
insights checks info SERVER_003
insights checks findings
Run one audit check by code over a time window and return the resulting findings.
insights checks findings [flags] <CODE>
<CODE> is a check code such as SERVER_001 or JETSTREAM_015. See the Audit Checks Reference for the full catalogue.
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--format / -f | (none) | text | Output format: text, csv, or json. The JSON response includes pagination metadata. |
--timeout | (none) | 30s | NATS request timeout. |
--duration | (none) | (empty) | Relative window as a DuckDB interval (e.g. 1 hour, 15 minutes, 7 days). |
--start | (none) | (empty) | Absolute start time (UTC, YYYY-MM-DDTHH:MM:SS). When omitted, derived from --duration. |
--end | (none) | (empty, meaning "live") | Absolute end time (UTC). |
--page | (none) | 1 | Page number (1-based) when results exceed one page. |
Example
Run SERVER_003 (High CPU Usage) against the last hour:
insights checks findings SERVER_003 --duration "1 hour"
Page through findings as JSON (1-based):
insights checks findings JETSTREAM_001 --format json --page 2
insights ops backup
Create a consistent snapshot of the Insights database, upload it to the JetStream object store, and download it locally. This is the recommended way to archive historical data. The server copies tables into a new DuckDB file without blocking live writes.
insights ops backup [flags]
ops backup always prints a plan summary (time range, epoch coverage, estimated file size) to stderr. When stdin is a terminal, it prompts for confirmation before running. Pass --force / -f to skip the prompt. --force is required when running non-interactively (for example, cron or CI).
Flags
| Flag | Env | Default | Description |
|---|---|---|---|
--output / -o | (none) | (server-generated filename) | Local output path. Use - to stream to stdout. |
--start | (none) | (no lower bound) | Start time: absolute (YYYY-MM-DD, RFC3339, or YYYY-MM-DDTHH:MM:SS UTC) or relative duration (7d, 1h, 30m). |
--end | (none) | (latest epoch) | End time: same formats as --start. |
--force / -f | (none) | false | Skip the confirmation prompt. Required for non-interactive use. |
--timeout | (none) | 10m | NATS request timeout for the backup operation. |
Examples
Back up the last seven days, prompting for confirmation:
insights ops backup --start 7d --output weekly-backup.db
Non-interactive full backup to a dated filename:
insights ops backup --force --output "insights-$(date +%Y%m%d).db"
Stream a backup to another host over SSH:
insights ops backup --force --output - | ssh archive "cat > /backups/insights-$(date +%s).db"
insights ops sizing
Recommend a DuckDB memory_limit and threads configuration for the running instance, grounded in DuckDB's per-thread guidance and the instance's real host capacity (cores and RAM) plus its observed memory use. Because it runs against the live database on the actual host the limits apply to, it is most useful run against an instance that is under load — for example when investigating a performance issue — after which you can decide whether to retune the limits or add host memory.
When the memory profiler is enabled (the default), the estimates are grounded in the peak memory measured under real load rather than conservative constants; the report flags when it had no samples to work from. The largest single write is usually a retention prune, which runs far less often than the profiler's rolling window — use --observe <duration> to watch the live profile long enough to span one so that peak is captured.
insights ops sizing [flags]
Flags
| Flag | Default | Description |
|---|---|---|
--per-thread | 2 | GB per thread used in the query budget (DuckDB recommends 1–4). |
--threads | 0 | Threads to size for (0 = recommend min(cores, 4)). |
--observe / -o | 0 | Observe the live memory profile for this long and size from the peaks seen (0 = one-shot). |
--timeout | 30s | NATS request timeout. |
Examples
# Size the running instance against its real host:
insights ops sizing
# Size for a specific thread count and per-thread budget:
insights ops sizing --threads 8 --per-thread 4
# Observe live load for an hour (ideally spanning a retention prune):
insights ops sizing --observe 1h
insights ops memory
Show the running instance's live DuckDB memory profile: current and peak resident bytes per component over a rolling window. This is the ground truth behind ops sizing's measured estimates, and a quick way to watch what the database is actually doing under load.
A background sampler in the server records the memory profile on an interval into a rolling window (both configurable under --db.memory-profile.*); ops memory reads that retained snapshot over NATS rather than sampling on demand. The same readings are also exported as the insights_duckdb_memory_bytes Prometheus gauge. Output is a summary table (current / peak / peak time per component) followed by a small self-scaled trend chart per component.
insights ops memory [flags]
Flags
| Flag | Default | Description |
|---|---|---|
--live / -l | false | Continuously re-render the profile as the server samples it (Ctrl-C to stop). |
--timeout | 30s | NATS request timeout. |
Example
insights ops memory --live
If the profiler is disabled (--db.memory-profile.enabled=false), the command reports that no samples are available.
insights ops pprof
Capture a runtime profile from the running instance for diagnostics — most usefully a goroutine dump to see where the process is parked when something has stalled (for example, a scrape or index loop that stopped advancing). The server does not expose HTTP profiling handlers, so this subcommand is the way to reach the standard profiles.
insights ops pprof [flags]
Flags
| Flag | Default | Description |
|---|---|---|
--type | goroutine | Profile to capture: goroutine, heap, allocs, threadcreate, block, mutex. |
--debug | 0 | Debug level: 0 = binary protobuf for go tool pprof; 1 = text with aggregated counts; 2 = full per-goroutine stacks. |
--output / -o | (none) | Write the profile to this file instead of stdout. |
--timeout | 30s | NATS request timeout. |
A binary profile (--debug 0) is refused when stdout is a terminal — pass --output to write it to a file, or --debug 2 for a readable text dump.
Examples
# Read a goroutine dump directly:
insights ops pprof --type goroutine --debug 2
# Capture a heap profile and open it in pprof:
insights ops pprof --type heap --output heap.pprof
go tool pprof heap.pprof
block and mutex return an empty profile unless their sampling was enabled at server startup.
--version
Print the binary version and exit. Recognized only as the sole argument:
insights --version
Official release binaries print a semantic version. Unstamped binaries print dev.