> ## Documentation Index
> Fetch the complete documentation index at: https://docs.expanse.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Telemetry

> What the CLI records about your patch decisions, where it goes, and how to switch it off.

The `expanse` CLI records what you decide about its recommendations: one record per patch it offers, and a short description of how each `analyse` and `diagnose` command was invoked. Both stay inside your organisation's own intelligence plane. Nothing goes to a third party.

## What is recorded

One `PatchDecision` record per artefact the CLI offers, from the patch walk of `expanse analyse` and from `expanse analyse apply`. Every field is a name from a closed list; none is free text.

| Field | Values | Meaning |
| - | - | - |
| `kind` | `resource`, `right_size`, `code` | The heading the patch was offered under; `code` when the diff rewrites program source rather than a submission file |
| `mode` | `interactive`, `yes`, `json`, `non_tty` | How the offer was put: a question on a terminal, `--yes`, `--json`, or no terminal to ask on |
| `knob_count_bucket` | `one`, `two`, `three_plus` | How many changes the patch carried that the walk could decide one at a time |
| `decision` | `apply`, `apply_per_knob`, `decline`, `unattended_yes`, `not_asked`, `deferred` | Your answer: `y`, `k`, `n`, applied under `--yes`, never asked (`--json` or no terminal), or left for later because the patch could not be applied now |
| `knob_decisions` | one accept or reject per knob kind | Set only for `apply_per_knob`; the values you chose never travel |
| `git_apply_result` | `ok`, `failed`, `cancelled` | The exit of `git apply`; unset when nothing was applied |
| `applied_when` | `now`, `later` | In the walk, or through `expanse analyse apply`; unset when nothing was applied |
| `prompt_decision` | `shown`, `declined`, `printed_later` | What happened to the run's agent prompt question, stamped on every artefact of that run; unset when the run carried no prompt |
| `analyse_run_id`, `artefact_id` | opaque identifiers | The run and artefact inside your plane; they never leave it |

Never recorded: file paths, job names, diff text, prompt text, knob values, the working directory, the command line.

Each record also carries a session id minted once per CLI process and held in memory only, the minute it happened, and the organisation, user and team read from your session token by the plane.

## How the request was invoked

Every `expanse analyse` and `expanse diagnose` request names how it was made, in a `client_context` the plane stores beside the request's usage record (the same record the Security page's audit export already lists). This travels with the request and is not governed by the switches below.

| Field | Values |
| - | - |
| `trigger` | `deliberate` for a command a person ran; `automatic` for `expanse analyse --queue` |
| `is_tty` | Whether stdin and stdout were a terminal |
| `flags` | The switches set, named and never valued: `no_cache`, `no_patch`, `yes`, `json`, `queue` (`code` is reserved and has no switch today) |
| `cli_version` | The release version, digits and dots only; a development build sends none. The plane logs it and does not store it |

## Where it goes

The record is written to your organisation's intelligence plane under your own session token, through the same connection `expanse analyse` uses.

* In a customer-hosted deployment it stays inside your network and only hourly counts without identities leave, on the analytics report described in the deployment's data-flow documentation. In an air-gapped deployment nothing leaves.
* In the hosted demonstration service it goes to Expanse's own database and to no third party.

Sending is best-effort and shares one two-second budget with the command's other background sends: it never changes the command's output or exit code. A plane that does not answer is not retried in the same run, and a record the plane refuses is dropped. The unsent records of a run are kept in memory for the life of the command only, so a crash between the question and the send loses them.

## Switching it off

Highest first; the first switch set decides:

| Switch | Effect |
| - | - |
| `DO_NOT_TRACK=1` | Off (any value but `0`) |
| `EXPANSE_TELEMETRY=off`, `log` or `on` | Off, print what would be sent to stderr and send nothing, or on; any other value reads as off |
| A `.expanse/telemetry` file containing `off` | Off for every command run in that directory or below (the CLI walks up from the working directory) |
| `expanse telemetry disable` | Off for this machine, written to `telemetry.json` beside `session.json` in `${XDG_CONFIG_HOME:-~/.config}/expanse` |
| A `telemetry.json` that cannot be read or parsed | Off, with the error as the source `expanse telemetry status` prints; a privacy switch never fails open |
| Default | On |

Your organisation's own switch beats all of them: when an organisation owner switches the `product_usage` category off on the Security page, the CLI reads it from the session token and sends nothing, and the plane refuses what an older CLI might still send.

`EXPANSE_AIR_GAPPED` is not a switch. The record is written to the in-perimeter plane, and no connection opens outward.

## `expanse telemetry`

```bash theme={"dark"}
expanse telemetry status    # the mode, the switch that set it, the organisation's switch, the settings file
expanse telemetry disable   # off for this machine
expanse telemetry enable    # on again for this machine
```

`status` names a higher switch when one overrides the settings file, so `enable` under `DO_NOT_TRACK=1` prints the mode as off.

## The first-run notice

The first time `expanse analyse` or `expanse analyse apply` runs on a terminal with recording on, it prints this to stderr and records nothing in that run. It is not shown under `--json` or in a CI environment (`CI` or `GITHUB_ACTIONS` set), and it is shown once per machine.

```text theme={"dark"}
Expanse records what you decide about its recommendations.

When you answer y, n or k to a patch prompt, or run `expanse analyse apply`,
the CLI records the decision and the `git apply` result beside the run record
in your organisation's intelligence plane. It records names and outcomes only:
the patch kind, your answer, the exit status. Never file paths, job names,
diff text or prompt text.

In a customer-hosted deployment this stays inside your network and only hourly
counts without identities leave; in an air-gapped deployment nothing leaves. In
the hosted demonstration service it goes to Expanse's own database and to no
third party.

Nothing about your decisions has been recorded during this run.
To see exactly what would be sent:   EXPANSE_TELEMETRY=log
To turn it off:                      expanse telemetry disable
                                     (or EXPANSE_TELEMETRY=off, or DO_NOT_TRACK=1)
Details: https://docs.expanse.sh/cli/telemetry
```

## Seeing exactly what would be sent

```bash theme={"dark"}
EXPANSE_TELEMETRY=log expanse analyse train.slurm
```

prints each `RecordProductEvents` request to stderr as JSON instead of sending it, so you can read every field before switching recording on.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.