# No-Mistakes Telemetry Privacy Options: Local-Only vs Remote Data

> Explore no-mistakes telemetry privacy options: local-only metrics vs. remote data. Configure granular controls for enhanced data protection and choose your preferred reporting.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: deep-dive
- Published: 2026-07-12

---

**No-mistakes provides granular telemetry controls that keep read-operation metrics in local gate files while allowing optional mutation-event reporting to self-hosted Umami instances, configurable via build-time variables and the `NO_MISTAKES_TELEMETRY` environment flag.**

The `kunchenguid/no-mistakes` repository implements a privacy-conscious telemetry system that separates read-surface analytics from mutation-surface event tracking. Understanding these no-mistakes telemetry privacy options ensures you can audit exactly what data remains on your local filesystem and what conditionally transmits to remote endpoints.

## Understanding the Two Telemetry Surfaces

The telemetry architecture in `no-mistakes` operates through two distinct surfaces defined in [`internal/telemetry/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/telemetry.go). Each surface handles different user interactions with specific privacy implications.

**Read-surface telemetry** captures lightweight UI metrics from commands like `axi status` or `stats agents`. This data includes action counts and timestamps but explicitly excludes raw prompts, diffs, or run IDs. By default, this surface operates in **local-only mode**, storing deduplication state in a gate file without any network transmission.

**Mutation-surface telemetry** records high-level lifecycle events such as `run started`, `run finished`, and `fix` operations. No command arguments, file contents, or agent outputs are included in these payloads. Remote transmission only occurs when the binary is compiled with specific host variables, otherwise this surface remains local-only as well.

## Local-Only Telemetry Implementation

### The Gate File Mechanism

The read-surface telemetry maintains privacy through a local gate file managed by [`internal/telemetry/readgate.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/readgate.go). This implementation persists state in a JSON file located at the path returned by `TelemetryGateFile()` in [`internal/paths/paths.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/paths/paths.go), typically resolving to `<NM_HOME>/telemetry_gate.json`.

The gate file serves two critical functions: it deduplicates events to prevent duplicate logging and implements rate-limiting to approximately one write per ten minutes. Because this data never leaves the local machine, read patterns remain entirely private even in the default configuration.

### Privacy Guarantees in Read Operations

As implemented in [`internal/cli/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/telemetry.go), the read-surface telemetry explicitly sanitizes all data before local storage. The code ensures that no command arguments, prompt text, or file diffs enter the telemetry pipeline. Only anonymized counts and timestamps reach the gate file, making this surface suitable for air-gapped environments without additional configuration.

## Remote Data Transmission Controls

### Umami Integration for Mutation Events

When enabled, mutation-surface telemetry transmits to a self-hosted Umami analytics server. The client initialization in [`internal/telemetry/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/telemetry.go) reads compiled-in values from [`internal/buildinfo/version.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/buildinfo/version.go), specifically the variables `TelemetryHost` and `TelemetryWebsiteID`.

These build-time values determine the remote destination. If they remain unset during compilation, the Umami client initialization is skipped entirely, forcing local-only operation even for mutation events. Tests in [`internal/cli/telemetry_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/telemetry_test.go) and [`internal/cli/wizard_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/wizard_test.go) verify that no network requests occur when these values are absent.

### Build-Time Configuration

You can embed custom telemetry endpoints during the build process by exporting environment variables before compilation:

```bash
TelemetryHost="https://umami.internal.company.com" \
TelemetryWebsiteID="550e8400-e29b-41d4-a716-446655440000" \
make build

```

The linker injects these values into `buildinfo.TelemetryHost` and `buildinfo.TelemetryWebsiteID` as defined in [`internal/buildinfo/version.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/buildinfo/version.go). A binary built without these variables contains no remote telemetry capability, ensuring all data remains local by default.

## Disabling Telemetry at Runtime

### Environment Variable Opt-Out

Even when compiled with remote endpoints, you can suppress all telemetry emission at runtime using the `NO_MISTAKES_TELEMETRY` environment variable. Setting this to `0` (or alternatively using `NM_TELEMETRY=off`) immediately disables both gate file updates and network transmission:

```bash
export NO_MISTAKES_TELEMETRY=0
no-mistakes run --target production

```

The validation logic in [`internal/telemetry/config_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/config_test.go) confirms this behavior through the test `TestDefaultDisablesTelemetryWhenEnvIsOff`, which asserts that the telemetry client returns a no-op implementation when this variable is present, guaranteeing zero data emission.

### Complete Privacy Lockdown

To ensure absolute data privacy, combine build-time and runtime controls. Compile the binary without embedded telemetry hosts, then set the opt-out environment variable:

```bash

# Build without remote endpoints

make build

# Runtime enforcement

export NO_MISTAKES_TELEMETRY=0

```

This configuration ensures that [`internal/telemetry/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/telemetry.go) initializes neither the Umami client nor the local read gate, creating a completely silent telemetry state.

## Verifying Your Privacy Settings

### Inspecting Local Gate Data

You can audit exactly what telemetry data remains local by examining the gate file directly:

```bash
cat "$(no-mistakes env --print NM_HOME)/telemetry_gate.json"

```

This JSON contains only event hashes and timestamps, confirming that [`internal/paths/paths.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/paths/paths.go) correctly isolated the read-surface data to your local filesystem according to the `TelemetryGateFile()` implementation.

### Checking Remote Configuration

To verify whether your binary includes remote endpoints, inspect the build information:

```bash
no-mistakes version --telemetry

```

If this output shows empty `TelemetryHost` and `TelemetryWebsiteID` fields, the binary operates in local-only mode regardless of environment variables. The initialization logic in [`internal/telemetry/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/telemetry.go) requires non-empty host strings before creating any HTTP clients, ensuring no accidental remote connections.

## Summary

- **Read-surface telemetry** remains **local-only** by default, storing throttled, anonymized metrics in `<NM_HOME>/telemetry_gate.json` via the implementation in [`internal/telemetry/readgate.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/readgate.go).
- **Mutation-surface telemetry** only transmits to remote Umami instances when `TelemetryHost` and `TelemetryWebsiteID` are embedded during build via [`internal/buildinfo/version.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/buildinfo/version.go).
- **Runtime opt-out** is absolute via `NO_MISTAKES_TELEMETRY=0`, which forces a no-op telemetry client as verified by `TestDefaultDisablesTelemetryWhenEnvIsOff` in [`internal/telemetry/config_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/config_test.go).
- **No sensitive data** (prompts, diffs, arguments, or file contents) ever enters the telemetry pipeline according to the sanitization logic in [`internal/cli/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/telemetry.go).
- **Verification** is possible by inspecting the local gate file path returned by `TelemetryGateFile()` in [`internal/paths/paths.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/paths/paths.go) or checking build-time constants in the binary.

## Frequently Asked Questions

### What data does no-mistakes collect by default?

By default, `no-mistakes` collects only high-level interaction counts and timestamps for read operations, stored locally in [`telemetry_gate.json`](https://github.com/kunchenguid/no-mistakes/blob/main/telemetry_gate.json). No remote data transmission occurs unless the binary was explicitly built with the `TelemetryHost` and `TelemetryWebsiteID` variables defined in [`internal/buildinfo/version.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/buildinfo/version.go). Mutation events remain local unless those build-time conditions are met.

### How do I completely disable remote telemetry?

Set the environment variable `NO_MISTAKES_TELEMETRY=0` before running any command. This forces the telemetry client initialization in [`internal/telemetry/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/telemetry.go) to return a no-op implementation, preventing both local gate file updates and network requests. For permanent disabling, build the binary without setting the `TelemetryHost` and `TelemetryWebsiteID` variables.

### Can I use my own telemetry server instead of the default?

Yes. During compilation, export your self-hosted Umami endpoint and website ID:

```bash
TelemetryHost="https://umami.mydomain.com" \
TelemetryWebsiteID="my-uuid-here" \
make build

```

The resulting binary directs all mutation-surface telemetry to your specified instance while maintaining local-only behavior for read-surface data, as controlled by the logic in [`internal/telemetry/telemetry.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/telemetry/telemetry.go).

### Where is the local telemetry data stored?

Local telemetry state persists in a JSON file at the path returned by `TelemetryGateFile()` in [`internal/paths/paths.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/paths/paths.go), typically located at `<NM_HOME>/telemetry_gate.json`. This file contains only event deduplication hashes and timestamps, with no user content, command history, or repository data ever written to disk.