Berserk Docs

Berserk CLI

Command-line tool for interacting with Berserk

bzrk is Berserk's terminal tool for querying, scripting, administration and large exports. To connect an AI agent, use MCP: Connect Your AI Agent; agents can also run bzrk themselves.

Installation

curl -fsSL https://go.bzrk.dev | bash

This installs bzrk to ~/.local/bin; BZRK_INSTALL_DIR sets another directory:

BZRK_INSTALL_DIR=/usr/local/bin curl -fsSL https://go.bzrk.dev | bash

To install a specific version:

curl -fsSL https://go.bzrk.dev | bash -s v1.0.15

Platform support

The CLI is available for Linux (x86_64 and aarch64) and macOS (Apple Silicon).

Getting Started

Add a profile for your cluster, make it active and sign in. bzrk login runs a browser-based device-code flow:

bzrk profile add --endpoint https://<your-cluster-endpoint> my-cluster
bzrk profile use my-cluster
bzrk login

If your data lives in a non-default database, add --database my-database to bzrk profile add. Check that it works:

bzrk auth status
bzrk search '.show tables'

Endpoint vs. ingest URL

The profile --endpoint is your cluster's query/gateway URL (https://<your-cluster-endpoint>). Sending data into Berserk uses a separate OTLP ingest endpoint; see Ingestion.

bzrk login signs in an existing profile, so create the profile first. profile use makes it the default, so later commands need no -P; pass -P <name> for a one-off against a different profile (see Resolution order).

Use with an AI agent

Inside Claude Code, Codex, Aider, OpenCode and Gemini CLI, bzrk switches to agent mode automatically (or pass --agent): results stream as snapshots saved to files the agent can read, and every result says whether it is complete. Two commands are an agent's entry points:

  • bzrk help agents: how to search, read results and tell a complete answer from a partial one.
  • bzrk help topics: the guides (query craft, OpenTelemetry data, logs, traces, metrics, KQL), the same ones the MCP server serves.

If a Berserk MCP server is connected, prefer it for querying, and use bzrk for administration, scripting and large exports. Setting up an agent either way: Connect Your AI Agent.

Profiles

A profile is a named connection, for switching between environments (local, staging, production). The configuration keeps two things apart:

  • Endpoints: named URLs, not secret.
  • Sessions: credentials (bearer token, refresh token, expiry) that name an endpoint.

Configuration file

The configuration is at ~/.config/bzrk/config.toml (XDG Base Directory). Its mode must be 0600: otherwise the CLI refuses to read it and prints the chmod 600 <path> to run. bzrk profile add and bzrk login set the mode.

default_session = "staging"      # the active profile, used when no -P is passed

# Endpoint glossary — URLs by name, no secrets.
[endpoints.staging]
url = "https://berserk.staging.example.com"

[endpoints.gw-local]
url = "http://localhost:9500"

# A session pairs credentials with an endpoint, by name.
[sessions.staging]
endpoint = "staging"
bearer_token = "abcdef01…"
refresh_token = "0123456789…"
access_token_expires_at = "2026-05-26T14:00:00Z"

[sessions.gw-local]
endpoint = "gw-local"
bearer_token = "…"
refresh_token = "…"

Session fields:

FieldRequiredDescription
endpointYesThe name of an [endpoints.X] entry the session points at.
bearer_tokenNoAccess token issued by bzrk login. Sent as Authorization: Bearer … on every request. Auto-refreshed before expiry.
refresh_tokenNoLong-lived token used to mint new access tokens. bzrk logout revokes it server-side and clears it locally.
access_token_expires_atNoRFC 3339 timestamp written by bzrk login. The CLI refreshes ~30s before this fires.
username, databaseNoOptional metadata. database sets the default database for queries on this profile (overridable per-invocation with --database).

Client certificates and custom headers

Behind a mutual-TLS (mTLS) edge, which requires every client to present an X.509 certificate, set the certificate and any routing headers on the endpoint; every session that points at the endpoint uses them.

[endpoints.secure]
url = "https://gateway.internal.example:443"
# Client identity presented for mTLS (PEM). Both are required together.
client_cert_path = "~/.cache/certs/client.pem"   # leaf + signing chain
client_key_path  = "~/.cache/certs/client-key.pem"
# Verify the server against this CA instead of the system trust store (PEM, optional).
ca_cert_path     = "~/.cache/certs/ca.pem"
# TLS server name (SNI / authority) to verify against, when it differs from the
# endpoint host — e.g. an upstream service identity behind a routing proxy (optional).
tls_server_name  = "upstream.internal.example"

# Headers added to every gRPC request to this endpoint — e.g. an edge routing tag.
[endpoints.secure.headers]
"x-routing-tag" = "region/prod"
Endpoint fieldDescription
client_cert_pathPEM client certificate (leaf + chain) presented for mTLS. Requires client_key_path and an https:// URL.
client_key_pathPEM private key for client_cert_path.
ca_cert_pathPEM CA bundle used to verify the server, instead of the system roots.
tls_server_nameTLS server name (SNI / authority) to verify against when it differs from the endpoint host.
headersTable of Name = "Value" pairs attached to every gRPC request sent to this endpoint.

Paths may start with ~ or $HOME. The mTLS fields need an https:// endpoint; the CLI refuses to start otherwise. The certificate is read on every invocation, so a rotated certificate takes effect on the next command.

bzrk profile add takes the same settings as flags and writes them into the new [endpoints.X] entry:

bzrk profile add secure \
  --endpoint https://gateway.internal.example:443 \
  --client-cert ~/.cache/certs/client.pem \
  --client-key  ~/.cache/certs/client-key.pem \
  --ca-cert     ~/.cache/certs/ca.pem \
  --tls-server-name upstream.internal.example \
  --header "x-routing-tag: region/prod"

Each setting can also be given, or overridden, per invocation with a flag:

bzrk -P secure search "default | take 10" --since "1h ago" \
  --client-cert ~/.cache/certs/client.pem \
  --client-key  ~/.cache/certs/client-key.pem \
  --ca-cert     ~/.cache/certs/ca.pem \
  --tls-server-name upstream.internal.example \
  --header "x-routing-tag: region/prod"

Flags win over the endpoint's stored values; --header is repeatable and merges over the endpoint's headers (the flag wins on a name clash).

Managing profiles

# List profiles
bzrk profile list

# Add a profile
bzrk profile add staging --endpoint https://berserk.staging.example.com

# Show a profile (the active one without a name)
bzrk profile show staging

# Change its endpoint or default database ("" unsets the database)
bzrk profile set staging --database logs

# Set the active profile (used when no -P is passed)
bzrk profile use gw-local

# Rename
bzrk profile rename staging-gw staging

# Remove
bzrk profile remove old-env

After adding a profile, sign in with bzrk login, or set BZRK_BEARER_TOKEN for unattended use (Authenticating).

Resolution order

The CLI picks a profile in this order:

  1. Explicit --endpoint / --bearer-token flags override the resolved profile's URL / token.
  2. -P <name> — use that profile.
  3. BZRK_SESSION env var — same.
  4. Otherwise the active profile (default_session, set by bzrk profile use).
  5. Default endpoint (http://localhost:9500) if nothing matches.

Migration

A ~/.config/bzrk/profiles.toml from an older release is migrated to config.toml on the first invocation and renamed to profiles.toml.bak-<ISO>. Once config.toml exists, the old file is not read again.

Anonymized usage

bzrk counts how the CLI is used and sends that count to https://feedback.bzrk.dev/v1/cli-usage at most once a day. Collection is on by default. The first interactive run prints one notice and records nothing. Later runs keep a local batch at ~/.config/bzrk/usage.json (mode 0600) and upload the previous batch on a later invocation, at most once a day.

A batch contains the command, the boolean flag names set on the command line, known function names, and the declared argument names the function registry agrees on. It also names the functions and operators Microsoft documents for KQL that the query uses and Berserk does not support yet, such as has_any or make-graph; only names on that published list are sent. Unknown spellings are omitted. A query that fails to parse still counts, with the outcome query and the code parse_error. A build that is not a release, such as one built from source, also sends the names it does not recognise as typed and the full error of a failed query; a release never does. The outcome is one of ok, invalid_argument, not_found, already_exists, auth, permission_denied, unimplemented, network, server, query, io, or other. When a query failure carries one of the defined query error codes, that code is included too (unknown_function, argument_count, and the rest of that set). The batch also contains a duration bucket, the CLI version, the OS, the architecture, and whether the process is running in CI. It does not contain query text, the error message, argument values, paths, endpoints, or account names. A failed send does not change the command's exit code.

bzrk telemetry off       # stop collecting and delete the local batch
bzrk telemetry on        # collect and send on its own, including in CI
bzrk telemetry manual    # collect, and send only when you run `telemetry send`
bzrk telemetry send      # send the pending batch now
bzrk telemetry status    # whether this process collects
bzrk telemetry preview   # print the pending batch without sending it

bzrk telemetry send uploads the pending batch now, in any mode and however recently the last upload ran. telemetry preview shows what it sends. Unlike the background upload, a failed send is an error and keeps the batch for the next try; a batch the server rejects is discarded.

The same choice is allow_anonymized_telemetry in ~/.config/bzrk/config.toml. Absent means on. false turns collection off and deletes the local batch. true turns it on even in CI. auto_send_anonymized_telemetry = false is manual mode: the batch is kept and sent only by bzrk telemetry send. telemetry on and off clear it.

BZRK_ANONYMIZED_TELEMETRY wins over DO_NOT_TRACK, and both win over the file. For BZRK_ANONYMIZED_TELEMETRY:

  • 0, false, no, off, an empty value, or any other value except the ones below turns collection off.
  • 1, true, yes, or on turns it on, including in CI.
  • log or preview prints the batch and does not send it.

DO_NOT_TRACK=1 or true turns collection off when BZRK_ANONYMIZED_TELEMETRY is unset. Empty and 0 do not.

CI is off unless the config key is true or BZRK_ANONYMIZED_TELEMETRY is explicitly on. CI is CI, GITHUB_ACTIONS, GITLAB_CI, CIRCLECI, TRAVIS, BUILDKITE, TF_BUILD, or JENKINS_URL when the value is not 0, false, or empty. This is separate from BZRK_NO_UPDATE_CHECK, which only skips the update check.

Authenticating

The CLI talks to Berserk through the gateway, which owns OIDC, sessions and bearer tokens. Commands that query or change a cluster carry a bearer token; without one they print No active session for profile "<name>". with the command that signs that profile in (bzrk -P <name> login) and exit 1.

bzrk login — RFC 8628 device-code flow

bzrk login signs in the active profile, so create one first. With no resolvable profile it stops with an error telling you to pass --profile <name> or run bzrk profile use <name> first; there is no zero-config login.

Sign in via the device-code flow:

bzrk login            # signs in the active profile
bzrk -P staging login     # or target a specific profile

The CLI:

  1. POSTs to /api/oauth/device on your gateway and gets a short-lived device_code, user_code and verification_uri.
  2. Prints the verification URL and user code on stderr, so stdout stays clean for piping, and on a TTY tries to open the browser.
  3. Polls the gateway every few seconds until you approve in the browser, or until the device code expires after about 10 minutes.
$ bzrk -P staging login
To authenticate, open https://berserk.example.com/oauth/device and enter:

    user_code: ABCD-WXYZ

Waiting for approval…
✓ Signed in as alice@example.com (profile: staging)

On success the CLI stores the access token, refresh token and expiry in the active profile in ~/.config/bzrk/config.toml. Access tokens refresh on every command; run bzrk login again only when the refresh token expires or to switch identity.

Where the verification URL points

verification_uri is built from the gateway's public base URL (global.publicBaseUrl in the chart). With a local port-forward, set it to http://127.0.0.1:9500 so your browser can reach the URL.

bzrk auth status — who am I

Prints the resolved identity from the gateway's GET /api/me:

bzrk auth status
# alice@example.com (user_id 019e41d1-…, session expires 2026-05-26T14:00:00Z)

bzrk status — check everything at once

Prints the CLI version, the profile, endpoint and database commands will use, whether the profile is signed in (and as whom, via the same GET /api/me as bzrk auth status), and the query service's health and version. It needs no session: a signed-out profile is reported as Signed in: no — run `bzrk -P <name> login`. It exits 1 when the query service is unhealthy or the profile is not signed in, so scripts and agents can rely on the exit code.

bzrk logout — revoke the token

Revokes the refresh token server-side and clears the access / refresh / expiry fields from the active profile. Idempotent: with no session it prints Not signed in to profile "<name>". and exits 0.

bzrk logout

Scripted / CI use

For CI and scheduled jobs, set BZRK_BEARER_TOKEN; it overrides the active profile's token:

BZRK_BEARER_TOKEN="…" bzrk search "default | take 10"

Keep the token in your secret manager. For a workload, use a service account's token, not a person's:

bzrk service-account create ci
bzrk service-account grant ci observer
bzrk service-account token create ci ci-token --expires 90d

Every service account can query and read the catalog. Grant maintainer to one that must also change it: create, change, delete or restore databases, tables, views and ingest tokens. observer adds nothing to that yet. A service account cannot be an admin.

Commands

On this page