<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>gcx CLI on Grafana Labs</title><link>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/</link><description>Recent content in gcx CLI on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/index.xml" rel="self" type="application/rss+xml"/><item><title>Introduction to gcx</title><link>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/overview/</link><pubDate>Thu, 30 Jul 2026 16:41:53 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/overview/</guid><content><![CDATA[&lt;h1 id=&#34;overview-of-the-gcx-cli&#34;&gt;Overview of the &lt;code&gt;gcx&lt;/code&gt; CLI&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; is a single CLI that allows you and your AI coding agent structured access to both Grafana (dashboards, folders, alert rules, data sources) and Grafana Cloud products such as Synthetic Monitoring, K6, Fleet Management, Incidents, or Adaptive Telemetry.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; ships with a suite of agent skills for common workflows like alert investigation, root-cause analysis, dashboard creation and GitOps, SLO management, and observability setup. It natively supports agentic workflows and it&amp;rsquo;s integrated with Grafana Assistant, combining the previously fragmented user experience into one single tool.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; is under continuous development. &lt;a href=&#34;/help/&#34;&gt;Contact Grafana&lt;/a&gt; for support or to report any issues you encounter and help us improve this feature.&lt;/p&gt;
&lt;h2 id=&#34;benefits-of-gcx&#34;&gt;Benefits of &lt;code&gt;gcx&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Among others, &lt;code&gt;gcx&lt;/code&gt; provides the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Manage Grafana OSS/Enterprise and Grafana Cloud:&lt;/strong&gt; Use a single tool for dashboards, alerting, SLOs, on-call, synthetic checks, load testing, and more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitOps&lt;/strong&gt;: Pull resources to files, version in Git, or push back with full round-trip fidelity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SRE&lt;/strong&gt;: Ensure system performance by monitoring telemetry and root-causing incidents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability as code:&lt;/strong&gt; &lt;code&gt;gcx&lt;/code&gt; can scaffold Go projects, import existing dashboards, lint with Rego rules, or live-reload development servers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation:&lt;/strong&gt; &lt;code&gt;gcx&lt;/code&gt; uses JSON/YAML output, structured errors, and predictable exit codes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-environment:&lt;/strong&gt; Use named contexts to switch between development, staging, and production environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI agent friendly:&lt;/strong&gt; Agent mode auto-detected for Claude Code, Copilot, Cursor, and other.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;costs&#34;&gt;Costs&lt;/h2&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; itself is free, but &lt;strong&gt;some commands operate Grafana Cloud products that are billed based on usage&lt;/strong&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grafana Assistant is charged per token consumed, including requests made through &lt;code&gt;gcx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Synthetic Monitoring is billed per test execution.&lt;/li&gt;
&lt;li&gt;Performance Testing (k6) is charged per Virtual User Hour.&lt;/li&gt;
&lt;li&gt;IRM is billed per monthly active user.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For details, refer to the &lt;a href=&#34;/docs/grafana-cloud/cost-management-and-billing/&#34;&gt;Cost Management and Billing documentation&lt;/a&gt; and &lt;a href=&#34;/pricing/&#34;&gt;Grafana Cloud pricing&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;compatibility&#34;&gt;Compatibility&lt;/h2&gt;
&lt;p&gt;The following applies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; is available for Grafana Cloud and Grafana OSS/Enterprise v12 or later. Older Grafana versions are not supported.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; is compatible with any agentic coding tool.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; works across a wide range of Grafana product offerings. Feature availability depends on your Grafana deployment. For more information, refer to the &lt;a href=&#34;https://github.com/grafana/gcx#compatibility&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Compatibility matrix&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;migrate-from-grafanactl&#34;&gt;Migrate from &lt;code&gt;grafanactl&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;If you want to migrate from &lt;code&gt;grafanctl&lt;/code&gt; to &lt;code&gt;gcx&lt;/code&gt;, search-and-replace &lt;code&gt;grafanactl&lt;/code&gt; with &lt;code&gt;gcx&lt;/code&gt;. For &lt;code&gt;grafanactl resources serve&lt;/code&gt;, use &lt;code&gt;gcx dev serve&lt;/code&gt; instead.&lt;/p&gt;
&lt;h2 id=&#34;learn-more&#34;&gt;Learn more&lt;/h2&gt;
&lt;p&gt;Refer to the &lt;a href=&#34;https://github.com/grafana/gcx&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;gcx&lt;/code&gt; repository&lt;/a&gt; in GitHub for more information on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Installation and configuration&lt;/li&gt;
&lt;li&gt;How to manage resources, including dashboards-as-code&lt;/li&gt;
&lt;li&gt;CLI command reference&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="overview-of-the-gcx-cli">Overview of the &lt;code>gcx&lt;/code> CLI&lt;/h1>
&lt;p>&lt;code>gcx&lt;/code> is a single CLI that allows you and your AI coding agent structured access to both Grafana (dashboards, folders, alert rules, data sources) and Grafana Cloud products such as Synthetic Monitoring, K6, Fleet Management, Incidents, or Adaptive Telemetry.&lt;/p></description></item><item><title>Install gcx</title><link>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/installation/</link><pubDate>Fri, 14 Aug 2026 09:32:53 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/installation/</guid><content><![CDATA[&lt;h1 id=&#34;install-gcx&#34;&gt;Install &lt;code&gt;gcx&lt;/code&gt;&lt;/h1&gt;
&lt;h2 id=&#34;quick-install-using-the-script&#34;&gt;Quick install using the script&lt;/h2&gt;
&lt;p&gt;The fastest way to install &lt;code&gt;gcx&lt;/code&gt; on Linux or macOS is with the script:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;curl -fsSL https://raw.githubusercontent.com/grafana/gcx/main/scripts/install.sh | sh&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The script:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Detects your operating system and architecture.&lt;/li&gt;
&lt;li&gt;Downloads the latest release from GitHub&lt;/li&gt;
&lt;li&gt;Verifies the SHA-256 checksum.&lt;/li&gt;
&lt;li&gt;Installs the binary to &lt;code&gt;~/.local/bin&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;upgrade&#34;&gt;Upgrade&lt;/h3&gt;
&lt;p&gt;To upgrade, run the same command again. The script always installs the latest release.&lt;/p&gt;
&lt;p&gt;Check the result:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;gcx --version&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the version does not change, refer to &lt;a href=&#34;#the-version-does-not-change-after-an-upgrade&#34;&gt;The version does not change after an upgrade&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;installer-configuration-options&#34;&gt;Installer configuration options&lt;/h3&gt;
&lt;p&gt;Use these environment variables to customize the install script:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Environment variable&lt;/th&gt;
              &lt;th&gt;Default&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;GCX_INSTALL_DIR&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;$HOME/.local/bin&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Directory to install the binary into&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;GCX_VERSION&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;latest&lt;/td&gt;
              &lt;td&gt;Specific version to install (e.g., &lt;code&gt;0.2.4&lt;/code&gt;)&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;GITHUB_TOKEN&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;unset&lt;/td&gt;
              &lt;td&gt;GitHub token for API requests (avoids rate limits)&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The script also accepts &lt;code&gt;INSTALL_DIR&lt;/code&gt; and &lt;code&gt;VERSION&lt;/code&gt;. The &lt;code&gt;GCX_&lt;/code&gt; names take
precedence. Prefer the &lt;code&gt;GCX_&lt;/code&gt; names, because &lt;code&gt;INSTALL_DIR&lt;/code&gt; and &lt;code&gt;VERSION&lt;/code&gt; are
common names, and &lt;code&gt;curl | sh&lt;/code&gt; inherits every variable that your shell exports.&lt;/p&gt;
&lt;h3 id=&#34;examples&#34;&gt;Examples&lt;/h3&gt;
&lt;p&gt;Install a specific version:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;curl -fsSL https://raw.githubusercontent.com/grafana/gcx/main/scripts/install.sh | GCX_VERSION=0.2.4 sh&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Install to &lt;code&gt;/usr/local/bin&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;curl -fsSL https://raw.githubusercontent.com/grafana/gcx/main/scripts/install.sh | GCX_INSTALL_DIR=/usr/local/bin sh&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;uninstall&#34;&gt;Uninstall&lt;/h3&gt;
&lt;p&gt;To remove &lt;code&gt;gcx&lt;/code&gt;, delete the binary:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;rm ~/.local/bin/gcx&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;install-gcx-with-homebrew-macos-and-linux&#34;&gt;Install &lt;code&gt;gcx&lt;/code&gt; with Homebrew (macOS and Linux)&lt;/h2&gt;
&lt;p&gt;To install &lt;code&gt;gcx&lt;/code&gt; with Homebrew run:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;brew install gcx&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This command installs the &lt;code&gt;gcx&lt;/code&gt; formula from homebrew-core. Homebrew has a prebuilt bottle for macOS and Linux, so the install takes seconds. You do not need to add a tap.&lt;/p&gt;
&lt;p&gt;To upgrade an existing installation:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;brew upgrade gcx&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;install-from-the-grafana-tap&#34;&gt;Install from the Grafana tap&lt;/h3&gt;
&lt;p&gt;The Grafana tap also carries &lt;code&gt;gcx&lt;/code&gt;. Use the tap if you want Homebrew to compile the binary on your machine:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;brew install grafana/grafana/gcx&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Homebrew installs &lt;code&gt;go&lt;/code&gt; as a build dependency for this formula. The first install usually takes 30 to 60 seconds, and later upgrades reuse the Homebrew download cache.&lt;/p&gt;
&lt;p&gt;Install &lt;code&gt;gcx&lt;/code&gt; from one source only. Two Homebrew formulas with the same name conflict with each other.&lt;/p&gt;
&lt;h3 id=&#34;homebrew-and-macos-gatekeeper&#34;&gt;Homebrew and macOS Gatekeeper&lt;/h3&gt;
&lt;p&gt;Both Homebrew methods avoid the macOS Gatekeeper problem. Homebrew does not set the quarantine attribute on the files that it installs, so you do not need to work around notarisation.&lt;/p&gt;
&lt;h2 id=&#34;install-a-prebuilt-binary&#34;&gt;Install a prebuilt binary&lt;/h2&gt;
&lt;p&gt;Prebuilt binaries are available for a variety of systems and architectures. Refer to the &lt;a href=&#34;https://github.com/grafana/gcx/releases/latest&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;release versions on GitHub&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;To install a prebuilt binary:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the archive for the operating system and architecture you need.&lt;/li&gt;
&lt;li&gt;Extract the archive.&lt;/li&gt;
&lt;li&gt;Move the executable to the directory where you want to keep it.&lt;/li&gt;
&lt;li&gt;Make sure that directory is in your &lt;code&gt;PATH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make sure the file has execute permission.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you use macOS, a manually downloaded binary might be blocked by Gatekeeper.
For more information, refer to &lt;a href=&#34;#macos-gatekeeper-and-killed-9&#34;&gt;macOS Gatekeeper and killed: 9&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;install-gcx-from-source&#34;&gt;Install &lt;code&gt;gcx&lt;/code&gt; from source&lt;/h2&gt;
&lt;p&gt;To install &lt;code&gt;gcx&lt;/code&gt; with Go, you need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://git-scm.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;git&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://go.dev/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;go&lt;/code&gt;&lt;/a&gt; 1.24 or later.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To install, run:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;go install github.com/grafana/gcx/cmd/gcx@latest&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;the-version-does-not-change-after-an-upgrade&#34;&gt;The version does not change after an upgrade&lt;/h2&gt;
&lt;p&gt;This page lists several install methods, and they write &lt;code&gt;gcx&lt;/code&gt; to different
directories. If you use two methods, you get two copies. Your shell runs the
copy in the directory that comes first in &lt;code&gt;PATH&lt;/code&gt;, and an upgrade of the other
copy changes nothing that you can see.&lt;/p&gt;
&lt;p&gt;List every copy:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;which -a gcx&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The first line is the copy that your shell runs. Remove the copies that you do
not want:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Path&lt;/th&gt;
              &lt;th&gt;Install method&lt;/th&gt;
              &lt;th&gt;Command that removes it&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;~/.local/bin/gcx&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Install script&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;rm ~/.local/bin/gcx&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/usr/local/bin/gcx&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Prebuilt binary, or the script with &lt;code&gt;GCX_INSTALL_DIR&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;sudo rm /usr/local/bin/gcx&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/opt/homebrew/bin/gcx&lt;/code&gt;, &lt;code&gt;/home/linuxbrew/.../gcx&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Homebrew&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;brew uninstall gcx&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;~/go/bin/gcx&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;go install&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;rm ~/go/bin/gcx&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;After you remove a copy, your shell can still hold the old path in its command
hash table. Open a new terminal, or run:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;hash -r&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The install script reports this problem for you. It names both paths and both
versions, and it gives the removal command.&lt;/p&gt;
&lt;h2 id=&#34;macos-gatekeeper-and-killed-9&#34;&gt;macOS Gatekeeper and killed 9&lt;/h2&gt;
&lt;p&gt;macOS quarantines any downloaded binary by default. Since &lt;code&gt;gcx&lt;/code&gt; release binaries are not yet Apple-notarised, macOS may block it the first time you run it. If this happens, you&amp;rsquo;ll see one of these two symptoms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Intel macOS&lt;/strong&gt;: A dialog says, &lt;em&gt;&amp;ldquo;Apple could not verify &amp;lsquo;gcx&amp;rsquo; is free of malware…&amp;rdquo;&lt;/em&gt;, and the binary doesn&amp;rsquo;t run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apple Silicon (M-series) macOS&lt;/strong&gt;: The binary exits immediately with &lt;code&gt;killed: 9&lt;/code&gt; and no visible dialog.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Homebrew users are not affected&lt;/strong&gt;. Homebrew does not set the &lt;code&gt;xattr&lt;/code&gt; on the files that it installs.&lt;/p&gt;
&lt;h3 id=&#34;bypass-the-macos-gatekeeper&#34;&gt;Bypass the macOS gatekeeper&lt;/h3&gt;
&lt;p&gt;In manual downloads, bypass this by clearing the &lt;code&gt;xattr&lt;/code&gt; and ad-hoc sign the binary so Apple Silicon accepts it:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;xattr -d com.apple.quarantine &amp;#34;$(command -v gcx)&amp;#34; 2&amp;gt;/dev/null || true
codesign --sign - --force &amp;#34;$(command -v gcx)&amp;#34;   # required on Apple Silicon&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Next, run &lt;code&gt;gcx --version&lt;/code&gt; again; subsequent invocations should succeed without the block.&lt;/p&gt;
&lt;p&gt;Note that these steps will no longer be necessary once &lt;code&gt;gcx&lt;/code&gt; release binaries are Apple-notarised.&lt;/p&gt;
]]></content><description>&lt;h1 id="install-gcx">Install &lt;code>gcx&lt;/code>&lt;/h1>
&lt;h2 id="quick-install-using-the-script">Quick install using the script&lt;/h2>
&lt;p>The fastest way to install &lt;code>gcx&lt;/code> on Linux or macOS is with the script:&lt;/p>
&lt;div class="code-snippet ">&lt;div class="lang-toolbar">
&lt;span class="lang-toolbar__item lang-toolbar__item-active">sh&lt;/span>
&lt;span class="code-clipboard">
&lt;button x-data="app_code_snippet()" x-init="init()" @click="copy()">
&lt;img class="code-clipboard__icon" src="/media/images/icons/icon-copy-small-2.svg" alt="Copy code to clipboard" width="14" height="13">
&lt;span>Copy&lt;/span>
&lt;/button>
&lt;/span>
&lt;div class="lang-toolbar__border">&lt;/div>
&lt;/div>&lt;div class="code-snippet ">
&lt;pre data-expanded="false">&lt;code class="language-sh">curl -fsSL https://raw.githubusercontent.com/grafana/gcx/main/scripts/install.sh | sh&lt;/code>&lt;/pre>
&lt;/div>
&lt;/div>
&lt;p>The script:&lt;/p></description></item><item><title>Configure gcx</title><link>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/configuration/</link><pubDate>Fri, 14 Aug 2026 15:24:45 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/configuration/</guid><content><![CDATA[&lt;h1 id=&#34;configure-gcx&#34;&gt;Configure &lt;code&gt;gcx&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;You can configure &lt;code&gt;gcx&lt;/code&gt; with a configuration file or using environment variables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A configuration file stores named stacks, named Grafana Cloud credentials, and contexts that bind them. &lt;code&gt;gcx&lt;/code&gt; can layer system, user, and repository files. Check the &lt;a href=&#34;https://github.com/grafana/gcx/tree/main/docs/reference/configuration/index.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;configuration file reference documentation&lt;/a&gt; for all options. If you have a file from an older &lt;code&gt;gcx&lt;/code&gt; version, refer to &lt;a href=&#34;../migrate-configuration/&#34;&gt;Migrate your gcx configuration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Environment variables override the selected context in memory, so they work best in CI environments and are never persisted implicitly. Refer to &lt;a href=&#34;#configure-gcx-with-environment-variables&#34;&gt;Configure &lt;code&gt;gcx&lt;/code&gt; with environment variables&lt;/a&gt; for more information.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;choose-an-authentication-method&#34;&gt;Choose an authentication method&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; supports four ways to authenticate to a Grafana instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OAuth&lt;/strong&gt; (Grafana Cloud only): Browser-based sign-in with &lt;code&gt;gcx login&lt;/code&gt;. Recommended for interactive use. The tokens are user-scoped: every request runs with your own identity and RBAC permissions, so you can&amp;rsquo;t access anything through &lt;code&gt;gcx&lt;/code&gt; that you can&amp;rsquo;t already access in the Grafana UI. Refer to &lt;a href=&#34;#required-role-for-oauth-sign-in&#34;&gt;Required role for OAuth sign-in&lt;/a&gt; for the permission this flow needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service account token&lt;/strong&gt;: Works for Grafana Cloud and on-premises instances, and is the recommended method for CI and other non-interactive environments. Refer to &lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/&#34;&gt;Grafana service accounts&lt;/a&gt; for how to create one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Basic authentication&lt;/strong&gt;: Username and password. Use this only when service accounts aren&amp;rsquo;t available.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mTLS&lt;/strong&gt;: A client certificate and key for instances behind an identity-aware proxy. Configure the &lt;code&gt;grafana.tls&lt;/code&gt; fields or corresponding TLS environment variables.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Grafana Cloud platform APIs use a separate credential stored in a named Cloud
entry. A Cloud Access Policy token has full command compatibility and is
recommended for automation. Direct Cloud OAuth is available through
&lt;code&gt;gcx cloud login&lt;/code&gt; or the interactive Cloud step of &lt;code&gt;gcx login&lt;/code&gt;, but remains
experimental and is not yet accepted by every Cloud product command. OAuth
entries retain expiry, granted scopes, and a coherent OAuth/API endpoint pair.&lt;/p&gt;
&lt;h3 id=&#34;required-role-for-oauth-sign-in&#34;&gt;Required role for OAuth sign-in&lt;/h3&gt;
&lt;p&gt;To authorize a &lt;code&gt;gcx&lt;/code&gt; CLI connection with OAuth, your Grafana user needs the &lt;code&gt;grafana-assistant-app.tokens.gcx:access&lt;/code&gt; permission. The &lt;strong&gt;gcx User&lt;/strong&gt; role, registered by the Grafana Assistant application, grants this permission and is assigned automatically to users with the basic role Viewer or higher.&lt;/p&gt;
&lt;p&gt;This permission only lets you create &lt;code&gt;gcx&lt;/code&gt; tokens for your own user. It doesn&amp;rsquo;t grant access to other users&amp;rsquo; tokens and it doesn&amp;rsquo;t extend your existing Grafana permissions.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;If &lt;code&gt;gcx login&lt;/code&gt; fails with a &lt;code&gt;Permission Required&lt;/code&gt; error naming the &lt;strong&gt;gcx User&lt;/strong&gt; role, ask your Grafana administrator to assign you the &lt;strong&gt;gcx User&lt;/strong&gt; role, or a custom role that includes the &lt;code&gt;grafana-assistant-app.tokens.gcx:access&lt;/code&gt; permission. If the role doesn&amp;rsquo;t exist on your instance, the Grafana Assistant application needs to be updated to a version that includes it.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;understand-the-gcx-configuration-file-in-use&#34;&gt;Understand the &lt;code&gt;gcx&lt;/code&gt; configuration file in use&lt;/h2&gt;
&lt;p&gt;Run &lt;code&gt;gcx config path&lt;/code&gt; to display the configuration files currently in use.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; stores configuration in YAML. &lt;code&gt;--config &amp;lt;path&amp;gt;&lt;/code&gt; or &lt;code&gt;GCX_CONFIG=&amp;lt;path&amp;gt;&lt;/code&gt;
selects one explicit file and bypasses layering. Otherwise, gcx loads every
existing source in this order, with later sources taking precedence:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;System: the platform system config directory (for example, &lt;code&gt;$XDG_CONFIG_DIRS/gcx/config.yaml&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;User: &lt;code&gt;$HOME/.config/gcx/config.yaml&lt;/code&gt;, falling back to the platform user config directory such as &lt;code&gt;$XDG_CONFIG_HOME/gcx/config.yaml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Repository: &lt;code&gt;.gcx.yaml&lt;/code&gt; in the current working directory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Named &lt;code&gt;stacks&lt;/code&gt; and &lt;code&gt;cloud&lt;/code&gt; entries are atomic across sources: a higher-priority
same-named entry replaces the lower entry completely. This keeps a credential
and its server or Cloud endpoint in the same trust source. Context references
and datasource defaults may merge field-by-field.&lt;/p&gt;
&lt;p&gt;Credentials in the OS credential store (Keychain on macOS, Credential Manager
on Windows, Secret Service on Linux) are tied to the canonical config file,
exact owner kind and name, exact secret field, and normalized destination. Copying a config
file does not make its stored credentials portable; authenticate the copied
file separately.&lt;/p&gt;
&lt;p&gt;An automatically discovered repository &lt;code&gt;.gcx.yaml&lt;/code&gt; cannot attach tokens,
passwords, or client-certificate files from your environment, login flags, or
prompts to destinations the file supplies. It also cannot implicitly combine a
Cloud credential with a direct provider endpoint or write derived provider
credentials and caches. A provider endpoint supplied at runtime is accepted
only with its matching runtime credential, and neither value authorizes TLS or
proxy settings from an auto-discovered repository stack. To trust the
repository config for those operations, select it explicitly:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;gcx login --config .gcx.yaml
# or
GCX_CONFIG=.gcx.yaml gcx login&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Credentials already owned by that exact file remain usable while their bound
destination is unchanged.&lt;/p&gt;
&lt;p&gt;Literal edits to a named stack or Cloud entry affect every context that
references it. If an edit changes a credential destination - such as a Grafana
server, Synthetic Monitoring URL, or Cloud API/OAuth endpoint - gcx clears the
old credential in the same write. Supply a fresh credential before using the
new destination. Normalization-equivalent endpoint edits preserve it.&lt;/p&gt;
&lt;h2 id=&#34;define-contexts&#34;&gt;Define contexts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; supports multiple contexts so you can switch between instances. A context references a named stack entry, which holds the Grafana connection details. By default, &lt;code&gt;gcx&lt;/code&gt; uses the &lt;code&gt;default&lt;/code&gt; context.&lt;/p&gt;
&lt;p&gt;A stack entry holds one credential alongside its server. To use two identities against the same stack - for example a personal token and a CI token, or read-only and admin - define two stack entries and a context for each.&lt;/p&gt;
&lt;p&gt;To configure the &lt;code&gt;default&lt;/code&gt; context:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config set stacks.default.grafana.server http://localhost:3000
gcx config set contexts.default.stack default

# Set org-id when using OSS/Enterprise - skip when targeting Grafana Cloud
gcx config set stacks.default.grafana.org-id 1

# Authenticate with a service account token
gcx config set stacks.default.grafana.token service-account-token

# Or alternatively, use basic authentication
gcx config set stacks.default.grafana.user admin
gcx config set stacks.default.grafana.password admin&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To create another context, use the same pattern:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config set stacks.staging.grafana.server https://staging.grafana.example
gcx config set stacks.staging.grafana.org-id 1
gcx config set contexts.staging.stack staging&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that in these examples, &lt;code&gt;default&lt;/code&gt; and &lt;code&gt;staging&lt;/code&gt; are the context and stack names.&lt;/p&gt;
&lt;h2 id=&#34;useful-commands&#34;&gt;Useful commands&lt;/h2&gt;
&lt;p&gt;Use these commands to check the configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config check&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Without &lt;code&gt;--context&lt;/code&gt;, the check covers every configured context before
returning. It exits non-zero when the current context is invalid or any checked
context fails configuration, authentication setup, connectivity, or Grafana
version checks, so it is safe to use as a deployment gate.&lt;/p&gt;
&lt;p&gt;To check only one context without validating unrelated entries, pass
&lt;code&gt;--context&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config check --context staging&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;List existing contexts:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config list-contexts&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Switch to a different context:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config use-context staging&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;See the entire configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;gcx config view&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configure-gcx-with-environment-variables&#34;&gt;Configure &lt;code&gt;gcx&lt;/code&gt; with environment variables&lt;/h2&gt;
&lt;p&gt;Every supported environment variable is listed in our &lt;a href=&#34;https://github.com/grafana/gcx/tree/main/docs/reference/environment-variables/index.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;reference documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;gcx&lt;/code&gt; connects to Grafana through the REST API, you must configure authentication credentials. At minimum, set the Grafana URL and organization ID:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;GRAFANA_SERVER=&amp;#39;http://localhost:3000&amp;#39; GRAFANA_ORG_ID=&amp;#39;1&amp;#39; gcx config check&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Depending on your authentication method, also set one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you use a &lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/&#34;&gt;Grafana service account&lt;/a&gt; (recommended), set a &lt;a href=&#34;https://github.com/grafana/gcx/tree/main/docs/reference/environment-variables/index.md#grafana_token&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;token&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you use basic authentication, set a &lt;a href=&#34;https://github.com/grafana/gcx/tree/main/docs/reference/environment-variables/index.md#grafana_user&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;username&lt;/a&gt; and a &lt;a href=&#34;https://github.com/grafana/gcx/tree/main/docs/reference/environment-variables/index.md#grafana_password&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;password&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After you configure authentication, you can start using &lt;code&gt;gcx&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to persist this configuration, &lt;a href=&#34;#define-contexts&#34;&gt;create a context&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="configure-gcx">Configure &lt;code>gcx&lt;/code>&lt;/h1>
&lt;p>You can configure &lt;code>gcx&lt;/code> with a configuration file or using environment variables.&lt;/p>
&lt;ul>
&lt;li>A configuration file stores named stacks, named Grafana Cloud credentials, and contexts that bind them. &lt;code>gcx&lt;/code> can layer system, user, and repository files. Check the &lt;a href="https://github.com/grafana/gcx/tree/main/docs/reference/configuration/index.md" target="_blank" rel="noopener noreferrer">configuration file reference documentation&lt;/a> for all options. If you have a file from an older &lt;code>gcx&lt;/code> version, refer to &lt;a href="../migrate-configuration/">Migrate your gcx configuration&lt;/a>.&lt;/li>
&lt;li>Environment variables override the selected context in memory, so they work best in CI environments and are never persisted implicitly. Refer to &lt;a href="#configure-gcx-with-environment-variables">Configure &lt;code>gcx&lt;/code> with environment variables&lt;/a> for more information.&lt;/li>
&lt;/ul>
&lt;h2 id="choose-an-authentication-method">Choose an authentication method&lt;/h2>
&lt;p>&lt;code>gcx&lt;/code> supports four ways to authenticate to a Grafana instance:&lt;/p></description></item><item><title>Migrate your gcx configuration</title><link>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/migrate-configuration/</link><pubDate>Fri, 14 Aug 2026 15:24:45 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/migrate-configuration/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-your-gcx-configuration-files-to-v1-format&#34;&gt;Migrate your &lt;code&gt;gcx&lt;/code&gt; configuration files to v1 format&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; is adjusting its configuration file format to make it easier to reuse credentials across contexts. This applies for &lt;code&gt;gcx&lt;/code&gt; versions &lt;code&gt;v0.6.0&lt;/code&gt; and later. The &lt;code&gt;v1&lt;/code&gt; format splits the file into three sections: &lt;code&gt;stacks&lt;/code&gt; for Grafana connections, &lt;code&gt;cloud&lt;/code&gt; for Grafana Cloud credentials that multiple contexts can reference, and &lt;code&gt;contexts&lt;/code&gt; that reference both by name.&lt;/p&gt;
&lt;h2 id=&#34;how-migration-works&#34;&gt;How migration works&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; attempts to migrate any legacy configuration file automatically the first time it loads it. If &lt;code&gt;gcx&lt;/code&gt; prints a warning or error that linked here, your migration paused or stopped for one of a small set of reasons. Find the message you saw in &lt;a href=&#34;#why-a-migration-paused-or-stopped&#34;&gt;Why a migration paused or stopped&lt;/a&gt; and follow the steps.&lt;/p&gt;
&lt;p&gt;Refer to the &lt;a href=&#34;#map-a-legacy-configuration-to-version-1&#34;&gt;table of field mappings&lt;/a&gt; at the end of this document to see how to convert a config file manually.&lt;/p&gt;
&lt;h3 id=&#34;migration-doesnt-delete-any-information&#34;&gt;Migration doesn&amp;rsquo;t delete any information&lt;/h3&gt;
&lt;p&gt;Whatever state your migration is in, nothing has been lost:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A paused or stopped migration changes &lt;strong&gt;nothing&lt;/strong&gt;: no file, no backup, no credential store entry. &lt;code&gt;gcx&lt;/code&gt; keeps working from an in-memory conversion where it safely can.&lt;/li&gt;
&lt;li&gt;A completed migration replaces the file only after checking the converted result means the same as the original, and keeps the original next to it as &lt;code&gt;&amp;lt;file&amp;gt;.legacy.bak&lt;/code&gt;. &lt;code&gt;gcx&lt;/code&gt; never overwrites or deletes that backup.&lt;/li&gt;
&lt;li&gt;Credentials in the OS credential store (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux) are copied into new entries; the old entries stay, so the backup remains fully usable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;roll-back-a-completed-migration&#34;&gt;Roll back a completed migration&lt;/h3&gt;
&lt;p&gt;To roll back a completed migration, copy the backup over the configuration file:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;cp ~/.config/gcx/config.yaml.legacy.bak ~/.config/gcx/config.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-caution&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Caution&lt;/p&gt;&lt;p&gt;If your legacy file contained plaintext credentials, they remain in &lt;code&gt;&amp;lt;file&amp;gt;.legacy.bak&lt;/code&gt; even after migration moves them into the OS credential store. Remove the backup yourself once you&amp;rsquo;re sure you won&amp;rsquo;t roll back.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;why-a-migration-paused-or-stopped&#34;&gt;Why a migration paused or stopped&lt;/h2&gt;
&lt;p&gt;Here are the reasons the config migration might have aborted, with an explanation of how to fix it:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;layered configuration migration is incomplete&amp;rdquo;&lt;/strong&gt;: your configuration is spread across several files (system, user, or a repository &lt;code&gt;.gcx.yaml&lt;/code&gt;). &lt;code&gt;gcx&lt;/code&gt; converts them in memory so commands keep working, but never rewrites several files for you, to avoid a state where some config files were migrated, but others were not. To remedy this, follow &lt;a href=&#34;#how-to-migrate-layered-files&#34;&gt;How to migrate layered files&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;cannot safely auto-migrate layered legacy configuration&amp;rdquo;&lt;/strong&gt; or &lt;strong&gt;&amp;ldquo;the overlapping entries require manual consolidation&amp;rdquo;&lt;/strong&gt;: two of your files define overlapping pieces of the same entry, which the v1 merge rules would combine differently than the legacy rules did. To remedy this, follow &lt;a href=&#34;#how-to-consolidate-overlapping-layers&#34;&gt;How to consolidate overlapping layers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;running with in-memory config migration &amp;hellip; reason: a legacy credential could not be read from the credential store&amp;rdquo;&lt;/strong&gt;: the credential store was locked, an unlock prompt was dismissed, or &lt;code&gt;gcx&lt;/code&gt; ran in a session without credential store access (SSH, CI). Persisting the migration then could strand references to credentials it couldn&amp;rsquo;t re-store, so &lt;code&gt;gcx&lt;/code&gt; waits. Unlock your credential store (or run from a desktop session) and run any &lt;code&gt;gcx&lt;/code&gt; command; the migration completes on its own.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;running with in-memory config migration&amp;rdquo;&lt;/strong&gt; with a permission-related reason: the configuration file or its directory isn&amp;rsquo;t writable. Read-only config commands keep working from the in-memory config, but anything that writes configuration or credentials fails until the file is writable or replaced with a v1 file. To remedy this, either fix the permissions and run any &lt;code&gt;gcx&lt;/code&gt; command, or for CI type environments, update the config file to use the v1 format. (see the &lt;a href=&#34;#map-a-legacy-configuration-to-version-1&#34;&gt;field mapping&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;existing legacy config backup does not match the current source&amp;rdquo;&lt;/strong&gt;: a previous migration left a &lt;code&gt;.legacy.bak&lt;/code&gt; and the file has since been rewritten in the legacy format (for example by an older &lt;code&gt;gcx&lt;/code&gt; version). &lt;code&gt;gcx&lt;/code&gt; won&amp;rsquo;t overwrite the earlier backup. To fix this, compare the two files, keep the one you trust and run any &lt;code&gt;gcx&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;unsupported config version&amp;rdquo;&lt;/strong&gt;: the file isn&amp;rsquo;t in the legacy format, and &lt;code&gt;gcx&lt;/code&gt; doesn&amp;rsquo;t recognize it. Upgrade &lt;code&gt;gcx&lt;/code&gt; to support a more modern format (this is more for futureproofing - there is only v1 at the moment).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;config migration self-check failed&amp;rdquo;&lt;/strong&gt;: &lt;code&gt;gcx&lt;/code&gt; converted the file, checked the result against the original, and found a difference, so it left the file untouched. &lt;strong&gt;This indicates a bug, &lt;a href=&#34;https://github.com/grafana/gcx/issues&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;report it&lt;/a&gt; with the error text&lt;/strong&gt;, and migrate by hand in the meantime.&lt;/p&gt;
&lt;h2 id=&#34;how-to-migrate-layered-files&#34;&gt;How to migrate layered files&lt;/h2&gt;
&lt;p&gt;The migration warning lists each remaining legacy file that needs migrating. Migrate the config files one at a time - each command rewrites just that file in the v1 format and leaves a &lt;code&gt;.legacy.bak&lt;/code&gt; backup next to it. For example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;gcx config set --file user version 1
gcx config set --file local version 1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After each step, &lt;code&gt;gcx&lt;/code&gt; re-prints the commands for whatever legacy files still need migrating, and refuses any per-file conversion that could replace a complete entry with a partial one. When it can&amp;rsquo;t offer a safe command it tells you to edit the file instead. To inspect any file without loading it, run &lt;code&gt;gcx config edit &amp;lt;system|user|local&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Be aware that editing the &lt;code&gt;system&lt;/code&gt; config file edits the config for all users on your system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When all files are migrated, the warning will disappear. To confirm everything is ok, refer to &lt;a href=&#34;#verify-the-result&#34;&gt;Verify the result&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-consolidate-overlapping-layers&#34;&gt;How to consolidate overlapping layers&lt;/h2&gt;
&lt;p&gt;Legacy &lt;code&gt;gcx&lt;/code&gt; merged contexts with the same name, but from different files, field by field. &lt;code&gt;v1&lt;/code&gt; doesn&amp;rsquo;t: a stack or Cloud entry in a higher-priority file completely replaces a same-named entry in a lower one. This is so one file can never mix its server with another file&amp;rsquo;s credentials. Files that relied on partial overrides need consolidating once, manually:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The error will name the entries that overlap. Open each file with &lt;code&gt;gcx config edit &amp;lt;system|user|local&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Move the overriding fields into the file that owns the complete entry, or rename the overriding entry (for example, give a repository-specific context its own stack name) so nothing overlaps.&lt;/li&gt;
&lt;li&gt;Run any &lt;code&gt;gcx&lt;/code&gt; command. The preflight re-checks; once nothing overlaps you are directed to &lt;a href=&#34;#how-to-migrate-layered-files&#34;&gt;Migrate layered files&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;map-a-legacy-configuration-to-version-1&#34;&gt;Map a legacy configuration to version 1&lt;/h2&gt;
&lt;p&gt;To convert a file by hand: copy the original somewhere safe, move each field to its new home using the table, add &lt;code&gt;version: 1&lt;/code&gt; at the top, and &lt;a href=&#34;#verify-the-result&#34;&gt;verify&lt;/a&gt;. Here is a map from the old field locations to the new ones:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Legacy (per context)&lt;/th&gt;
              &lt;th&gt;Version 1&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.grafana.*&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;stacks.&amp;lt;name&amp;gt;.grafana.*&lt;/code&gt;, plus &lt;code&gt;contexts.&amp;lt;name&amp;gt;.stack: &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.cloud.token&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;cloud.&amp;lt;entry&amp;gt;.token&lt;/code&gt;, plus &lt;code&gt;contexts.&amp;lt;name&amp;gt;.cloud: &amp;lt;entry&amp;gt;&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.cloud.api-url&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;cloud.&amp;lt;entry&amp;gt;.api-url&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.cloud.oauth-url&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;cloud.&amp;lt;entry&amp;gt;.oauth-url&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.cloud.stack&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;stacks.&amp;lt;name&amp;gt;.slug&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.providers.*&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;stacks.&amp;lt;name&amp;gt;.providers.*&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.resources.*&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;stacks.&amp;lt;name&amp;gt;.resources.*&lt;/code&gt;, or top-level &lt;code&gt;resources:&lt;/code&gt; to apply to all stacks&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.default-prometheus-datasource&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.datasources.prometheus&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.default-loki-datasource&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.datasources.loki&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.default-tempo-datasource&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.datasources.tempo&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.default-pyroscope-datasource&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.datasources.pyroscope&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;contexts.&amp;lt;name&amp;gt;.datasources.*&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;unchanged&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;current-context&lt;/code&gt;, &lt;code&gt;diagnostics&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;unchanged&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;You can name the &lt;code&gt;cloud&lt;/code&gt; entries whatever you like, since contexts refer to them by name. You can reuse cloud configs in multiple contexts.&lt;/p&gt;
&lt;p&gt;If your legacy &lt;code&gt;cloud.token&lt;/code&gt; came from the experimental OAuth sign-in rather than an access policy, it still migrates into &lt;code&gt;token&lt;/code&gt; - the legacy format can&amp;rsquo;t tell the two apart. The next &lt;code&gt;gcx cloud login&lt;/code&gt; stores it in the entry&amp;rsquo;s &lt;code&gt;oauth-token&lt;/code&gt; field.&lt;/p&gt;
&lt;h3 id=&#34;example-of-a-legacy-configuration-update&#34;&gt;Example of a legacy configuration update&lt;/h3&gt;
&lt;p&gt;A legacy configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;contexts:
  prod:
    grafana:
      server: https://myorg.grafana.net
      token: &amp;#34;&amp;lt;service account token&amp;gt;&amp;#34;
    cloud:
      token: &amp;#34;&amp;lt;cloud access policy token&amp;gt;&amp;#34;
      stack: myorg
    default-prometheus-datasource: my-prom
  dev:
    grafana:
      server: https://myorg-dev.grafana.net
      token: &amp;#34;&amp;lt;service account token&amp;gt;&amp;#34;
    cloud:
      token: &amp;#34;&amp;lt;cloud access policy token&amp;gt;&amp;#34;   # same token as prod
current-context: prod&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;becomes:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: 1
stacks:
  prod:
    slug: myorg
    grafana:
      server: https://myorg.grafana.net
      token: &amp;#34;&amp;lt;service account token&amp;gt;&amp;#34;
  dev:
    grafana:
      server: https://myorg-dev.grafana.net
      token: &amp;#34;&amp;lt;service account token&amp;gt;&amp;#34;
cloud:
  grafana-com:
    token: &amp;#34;&amp;lt;cloud access policy token&amp;gt;&amp;#34;     # shared by both contexts
contexts:
  prod:
    stack: prod
    cloud: grafana-com
    datasources:
      prometheus: my-prom
  dev:
    stack: dev
    cloud: grafana-com
current-context: prod&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;credential-references&#34;&gt;Credential references&lt;/h3&gt;
&lt;p&gt;If your legacy file contains values like &lt;code&gt;keychain:gcx:prod:cloud-token&lt;/code&gt;, they are references to secrets in the OS credential store. Let the migration move them rather than copying the strings yourself.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; only resolves legacy credential references from files you chose and own, such as your standard user config file (a symlinked home or XDG path still counts), or one you selected explicitly with &lt;code&gt;--config&lt;/code&gt; or &lt;code&gt;GCX_CONFIG&lt;/code&gt;, &lt;strong&gt;and only when the file is writable by you alone&lt;/strong&gt;. A reference must also sit where it claims to belong: the context and field named inside it have to match its location in the file. Files discovered from repositories or system directories are never trusted.&lt;/p&gt;
&lt;p&gt;If a repository config contains credential references, select it explicitly with &lt;code&gt;--config&lt;/code&gt; (only if you trust it), or replace the references with fresh credentials before migrating. Copying a legacy reference into a version 1 file never grants access to the secret.&lt;/p&gt;
&lt;p&gt;Version 1 credential references are tied to the config file&amp;rsquo;s path, the exact stack or Cloud entry and field they belong to, and the credential&amp;rsquo;s destination. Copying a version 1 config to a different path copies its structure but not access to its credentials - run &lt;code&gt;gcx login&lt;/code&gt; or &lt;code&gt;gcx cloud login&lt;/code&gt; for the copied file instead of copying reference strings by hand.&lt;/p&gt;
&lt;h2 id=&#34;verify-the-result&#34;&gt;Verify the result&lt;/h2&gt;
&lt;p&gt;After migrating, confirm the configuration parses and every context connects:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;gcx config view
gcx config check&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gcx config view&lt;/code&gt; shows the effective configuration with secrets redacted.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gcx config check&lt;/code&gt; validates every context, including connectivity, and exits non-zero if any check fails. Pass
&lt;code&gt;--context &amp;lt;name&amp;gt;&lt;/code&gt; to validate only that context.&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="migrate-your-gcx-configuration-files-to-v1-format">Migrate your &lt;code>gcx&lt;/code> configuration files to v1 format&lt;/h1>
&lt;p>&lt;code>gcx&lt;/code> is adjusting its configuration file format to make it easier to reuse credentials across contexts. This applies for &lt;code>gcx&lt;/code> versions &lt;code>v0.6.0&lt;/code> and later. The &lt;code>v1&lt;/code> format splits the file into three sections: &lt;code>stacks&lt;/code> for Grafana connections, &lt;code>cloud&lt;/code> for Grafana Cloud credentials that multiple contexts can reference, and &lt;code>contexts&lt;/code> that reference both by name.&lt;/p></description></item><item><title>Usage statistics</title><link>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/anonymous-usage-statistics/</link><pubDate>Thu, 30 Jul 2026 16:41:53 +0000</pubDate><guid>https://grafana.com/docs/grafana/v13.2/as-code/observability-as-code/grafana-cli/gcx/anonymous-usage-statistics/</guid><content><![CDATA[&lt;h1 id=&#34;understand-gcx-usage-statistics&#34;&gt;Understand gcx usage statistics&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;gcx&lt;/code&gt; 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&amp;rsquo;t exist, so we can make the product better.&lt;/p&gt;
&lt;p&gt;The statistics describe only the &lt;em&gt;shape&lt;/em&gt; of usage, including command path, and flag names. Positional argument values and flag values are never sent. Some server-side enrichment is also performed on the usage statistics exported - see &lt;a href=&#34;#server-side-enrichment&#34;&gt;Server-side enrichment&lt;/a&gt; for details.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Usage statistics reporting is &lt;strong&gt;enabled by default&lt;/strong&gt;. See the &lt;a href=&#34;#opt-out&#34;&gt;Opt out&lt;/a&gt; section below for guidance on how to turn off usage reporting.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;telemetry-data-and-identifiers&#34;&gt;Telemetry data and identifiers&lt;/h2&gt;
&lt;p&gt;The only identifier is a &lt;code&gt;device_id&lt;/code&gt; field: a randomly generated UUID created on first use and stored at &lt;code&gt;$XDG_STATE_HOME/gcx/device-id&lt;/code&gt;. It identifies an installation of &lt;code&gt;gcx&lt;/code&gt;, not a person. It&amp;rsquo;s random, not derived from your hardware or account.&lt;/p&gt;
&lt;h2 id=&#34;understand-which-data-is-collected&#34;&gt;Understand which data is collected&lt;/h2&gt;
&lt;p&gt;Each &lt;code&gt;gcx&lt;/code&gt; event contains the following properties:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;Field&lt;/th&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;Description&lt;/th&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;Example&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;service&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Always &lt;code&gt;gcx&lt;/code&gt;, identifying the reporting product.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;gcx&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The version of &lt;code&gt;gcx&lt;/code&gt;.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;0.4.1&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;os&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Operating system.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;linux&lt;/code&gt;, &lt;code&gt;darwin&lt;/code&gt;, &lt;code&gt;windows&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;arch&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;CPU architecture.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;amd64&lt;/code&gt;, &lt;code&gt;arm64&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;device_id&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The random per-installation ID described in &lt;a href=&#34;#telemetry-data-and-identifiers&#34;&gt;Telemetry data and identifiers&lt;/a&gt;.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;UUID&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;device_id_persisted&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Whether the device ID was read from or saved to disk. &lt;code&gt;false&lt;/code&gt; means a throwaway ID was used for this invocation.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;command&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The resolved command path only, no arguments are sent.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;dashboards push&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;flags&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The &lt;strong&gt;names&lt;/strong&gt; of the flags you set, sorted. No flag values are sent.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;dry-run,folder&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;provider&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The resource provider the command belongs to.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;dashboards&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;outcome&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;How the invocation ended: &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;runtime_error&lt;/code&gt;, &lt;code&gt;parse_error&lt;/code&gt;, or &lt;code&gt;help&lt;/code&gt;.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;ok&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;exit_code&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The process exit code.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;error_kind&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A coarse error category when the command failed: &lt;code&gt;usage_error&lt;/code&gt;, &lt;code&gt;auth_failure&lt;/code&gt;, &lt;code&gt;partial_failure&lt;/code&gt;, &lt;code&gt;version_incompatible&lt;/code&gt;, or &lt;code&gt;error&lt;/code&gt;. Never an error message.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;auth_failure&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;duration_ms&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Total invocation duration in milliseconds.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;1234&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;is_tty&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Whether &lt;code&gt;gcx&lt;/code&gt; ran attached to an interactive terminal.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;is_ci&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Whether a CI environment was detected.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;ci_provider&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Which CI system was detected, from a fixed list of known names. &lt;code&gt;gcx&lt;/code&gt; reads well-known CI environment variables to detect the provider but never sends their values.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;github_actions&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;is_agent&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Whether an AI coding agent drove the invocation.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;agent&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The name of the agent harness, if one was detected.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;claude-code&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;target_kind&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Whether the target Grafana is &lt;code&gt;cloud&lt;/code&gt; or &lt;code&gt;self-hosted&lt;/code&gt;. Empty when no effective Grafana target could be resolved. Deliberately coarse — never the URL, hostname, or stack slug.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;cloud&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;output_format&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The output format the command used.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;table&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;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:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;Field&lt;/th&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;Description&lt;/th&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;Example&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;parse_error_kind&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The kind of parse failure: &lt;code&gt;unknown_command&lt;/code&gt;, &lt;code&gt;unknown_flag&lt;/code&gt;, or &lt;code&gt;invalid_args&lt;/code&gt;.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;unknown_command&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;parse_error_parent&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The deepest valid command reached before the failure.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;dashboards&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;parse_error_token&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The first unknown toke. It&amp;rsquo;s only sent if it looks like a command name (short, lowercase, no digits, not a URL, IP address, or UUID); otherwise it&amp;rsquo;s replaced with &lt;code&gt;&amp;lt;redacted&amp;gt;&lt;/code&gt;.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;serch&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;attempted_command&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The parent command plus the unknown token, truncated at the unknown token so no later arguments are included.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;dashboards serch&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;parse_error_flags&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The &lt;strong&gt;names&lt;/strong&gt; of unknown flags. No flag values are sent.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;verbsoe&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;parse_error_nearest&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The nearest real command or flag name, if one is close.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;search&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;parse_error_distance&lt;/code&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The edit distance to the nearest real name, or &lt;code&gt;-1&lt;/code&gt; if there is no near match.&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h2 id=&#34;invocations-that-report-nothing&#34;&gt;Invocations that report nothing&lt;/h2&gt;
&lt;p&gt;Some invocations never emit an event:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shell completion&lt;/strong&gt; — the completion machinery runs on every tab-press and carries no usage signal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;gcx version&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cancelled invocations&lt;/strong&gt; — pressing Ctrl-C emits nothing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;server-side-enrichment&#34;&gt;Server-side enrichment&lt;/h2&gt;
&lt;p&gt;Reports are received by Grafana&amp;rsquo;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A coarse &lt;strong&gt;geographic region&lt;/strong&gt; (for example, a country or subdivision), taken from headers added by the CDN edge.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;network organization name&lt;/strong&gt; from a whois lookup of the connecting IP address. For CLI traffic this typically resolves to your ISP or employer&amp;rsquo;s network.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The connecting IP address is not stored in the usage event.&lt;/p&gt;
&lt;h2 id=&#34;inspect-what-would-be-sent&#34;&gt;Inspect what would be sent&lt;/h2&gt;
&lt;p&gt;To see exactly what &lt;code&gt;gcx&lt;/code&gt; would report for an invocation, set &lt;code&gt;GCX_TELEMETRY=log&lt;/code&gt;. The event is printed to stderr and nothing is sent:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;GCX_TELEMETRY=log gcx dashboards list&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;opt-out&#34;&gt;Opt out&lt;/h2&gt;
&lt;p&gt;You can control usage statistics reporting three ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;GCX_TELEMETRY&lt;/code&gt; environment variable&lt;/strong&gt;: Set to &lt;code&gt;enabled&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, or &lt;code&gt;log&lt;/code&gt;. Takes precedence over everything else:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;export GCX_TELEMETRY=disabled&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;DO_NOT_TRACK&lt;/code&gt; environment variable&lt;/strong&gt;:  Set to &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;true&lt;/code&gt; to disable reporting, following the cross-tool &lt;a href=&#34;https://consoledonottrack.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;DO_NOT_TRACK&lt;/a&gt; convention. Overridden by &lt;code&gt;GCX_TELEMETRY&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configuration file&lt;/strong&gt;: Add a top-level &lt;code&gt;diagnostics&lt;/code&gt; block to your &lt;code&gt;gcx&lt;/code&gt; configuration file, with &lt;code&gt;telemetry&lt;/code&gt; set to &lt;code&gt;enabled&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, or &lt;code&gt;log&lt;/code&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;diagnostics:
  telemetry: disabled&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Opting out disables reporting entirely. No event is constructed and nothing is sent.&lt;/p&gt;
]]></content><description>&lt;h1 id="understand-gcx-usage-statistics">Understand gcx usage statistics&lt;/h1>
&lt;p>&lt;code>gcx&lt;/code> 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&amp;rsquo;t exist, so we can make the product better.&lt;/p></description></item></channel></rss>