Important: This documentation is about an older version. It's relevant only to the release noted, many of the features and functions have been updated or replaced. Please view the current version.
Understand gcx usage statistics
gcx reports limited usage statistics about itself to Grafana Labs. This data is used to understand which commands and flags are used most, where commands fail, and which commands people try that don’t exist, so we can make the product better.
The statistics describe only the shape of usage, including command path, and flag names. Positional argument values, free-form flag values, and resource names are never sent, and the flags you set are recorded by name only. No raw count of batch or resource volume is sent.
For the resource commands that operate on batches, the size of the operation is sent as one of seven fixed categories rather than as a number. Two of those categories, 0 and 1, cover a single value each, so those two sizes are exact; every larger category is a range. See How to read the batch fields.
Two further fields describe how the command ran rather than naming a flag: output_format records the output format used, from a fixed list of known formats, and dry_run records whether the operation executed in dry-run mode. output_format is read from --output, which means a command that renders JSON because you passed --json is still recorded with --output’s value; that mismatch is a known bug rather than intended behaviour. dry_run is derived from the operation and is set even for commands that have no --dry-run flag. Some server-side enrichment is also performed on the usage statistics exported - see Server-side enrichment for details.
Note
Usage statistics reporting is enabled by default. See the Opt out section below for guidance on how to turn off usage reporting.
Telemetry data and identifiers
The only identifier is a device_id field: a randomly generated UUID created on first use and stored at $XDG_STATE_HOME/gcx/device-id. It identifies an installation of gcx, not a person. It’s random, not derived from your hardware or account.
Understand which data is collected
Each gcx event contains the following properties:
When the invocation is a batch resource operation (gcx resources push, pull, delete, or validate) that ran to completion, these additional fields are set. They describe the size of the operation, never what it contained:
The seven categories are exactly 0, 1, 2-5, 6-20, 21-100, 101-1000, and 1001+. Note that 0 and 1 are singleton categories, so those two sizes are recoverable exactly; every larger category is a range.
Sizes are sent as categories rather than as numbers on purpose. An exact count of a large batch, correlated with the per-installation device_id and the network organization name added on receipt, would describe a specific organization’s resource inventory. Categories answer how gcx is used without carrying that detail, and the two singleton categories carry no inventory to infer. No raw numeric count field is sent.
How to read the batch fields
These fields are easy to misread, so the following constraints are part of the contract:
- All four are present together, or none are. Their absence means the invocation was not one of those four commands, or it stopped before the operation reached a final count.
0means nothing was counted in that outcome, which is not the same as nothing having happened. The three counts are not a complete partition of the work: a resource filtered out before processing is recorded in none of them.gcx resources validateover resources that are all managed elsewhere, orgcx resources deleteagainst a resource type whose API does not support deletion, can therefore report0/0/0for a run that did examine resources. A0is still distinct from the field being absent, which means the operation never reached a final count.- The sizes describe the operation, not the output. They are recorded once the operation has finished and its counts are final. If the summary then fails to render or cannot be written to stdout, the sizes are still reported, because work that already happened is not undone by a display failure. Equally, they do not always correspond to a number printed on screen:
--jqand--json <fields>reshape the output, andvalidateprints only failures and skips in JSON. - An operation that aborted partway reports nothing. It never reached a final count, so there is no size to report. Note that
gcx resources deletewith--on-error=abortmay have deleted some resources before stopping; that partial work is deliberately not reported, so absence consistently means “no final count”, never “no work done”. - The unit depends on the command, so these must not be compared or totalled across commands.
gcx resources pullis the clearest case, and its failure count is genuinely mixed: a resource fetched but not written to disk counts as one failure, and a whole resource type whose list call fails also counts as one failure. Skips there count whole resource types the server could not list. A pull failure count of 2 can therefore mean two resources or two entire types. batch_skipped_bucketmeans different things per command, and whether it measures anything depends on the run. Ingcx resources pushandgcx resources deletea skip is recorded solely when a dry run cannot be verified server-side, so a run without--dry-runreports0by construction rather than as a measurement, while a dry run reports a real count.gcx resources validateis always a dry run, so its skip count is a genuine measurement on every run, and a non-zero value there is a normal outcome rather than a sign of trouble. Ingcx resources pullit is also a genuine measurement on every run, counting resource types the server could not list.dry_runis not a mutation flag.gcx resources validatealways reportstrueandgcx resources pullalwaysfalse, yet neither changes anything: pull is read-only. Readdry_runtogether withcommand, never as “this run modified resources”.gcx resources getnever reports these fields, because only the four commands listed above are instrumented. It is a read, but so ispull, which does report.
Parse-failure fields
When the invocation fails to parse, these additional fields are set. They capture what was attempted so the team can understand the differences between what users expect and what exists:
Invocations that report nothing
Some invocations never emit an event:
- Shell completion — the completion machinery runs on every tab-press and carries no usage signal.
gcx version- Cancelled invocations — pressing Ctrl-C emits nothing.
Server-side enrichment
Reports are received by Grafana’s usage-stats service, the same service that receives usage reports from Grafana, Loki, Tempo, and Mimir. On receipt, the service adds two pieces of information derived from the connection:
- A coarse geographic region (for example, a country or subdivision), taken from headers added by the CDN edge.
- The network organization name from a whois lookup of the connecting IP address. For CLI traffic this typically resolves to your ISP or employer’s network.
The connecting IP address is not stored in the usage event.
Inspect what would be sent
To see exactly what gcx would report for an invocation, set GCX_TELEMETRY=log. The event is printed to stderr and nothing is sent:
GCX_TELEMETRY=log gcx dashboards listOpt out
You can control usage statistics reporting three ways:
GCX_TELEMETRYenvironment variable: Set toenabled,disabled, orlog. Takes precedence over everything else:
export GCX_TELEMETRY=disabledDO_NOT_TRACKenvironment variable: Set to1ortrueto disable reporting, following the cross-tool DO_NOT_TRACK convention. Overridden byGCX_TELEMETRY.Configuration file: Add a top-level
diagnosticsblock to yourgcxconfiguration file, withtelemetryset toenabled,disabled, orlog:
diagnostics:
telemetry: disabledOpting out disables reporting entirely. No event is constructed and nothing is sent.


