# What Kind of Telemetry Data Does Context Hub Collect? A Complete Technical Breakdown

> Discover the telemetry data Context Hub collects: anonymous usage analytics and user feedback. Learn about event names, CLI version, ratings, and comments with this technical breakdown.

- Repository: [Andrew Ng/context-hub](https://github.com/andrewyng/context-hub)
- Tags: deep-dive
- Published: 2026-03-20

---

**Context Hub collects two distinct categories of telemetry data: anonymous usage analytics via PostHog (including event names, platform metadata, and CLI version) and explicit user feedback containing ratings, optional comments, and contextual information about documentation or skills, with both streams respecting user opt-out settings.**

The Context Hub CLI tool, maintained in the `andrewyng/context-hub` repository, implements a transparent telemetry system designed to balance product improvement with user privacy. Understanding what kind of telemetry data Context Hub collects requires examining the source code in [`cli/src/lib/analytics.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/analytics.js) and [`cli/src/lib/telemetry.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/telemetry.js), which handle the two distinct data streams.

## Anonymous Usage Analytics via PostHog

### What Gets Tracked

The analytics system captures **event-based telemetry** through the `trackEvent` function in [`cli/src/lib/analytics.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/analytics.js). Each event includes:

- **Event name** – Caller-defined identifiers such as `command_run`, `search`, `doc_fetched`, `skill_fetched`, or `fetch_error`
- **Caller-provided payload** – Context-specific data supplied by the CLI command (e.g., search parameters, document IDs, error types)
- **Global properties** – Automatically appended metadata including `platform` (operating system), `node_version` (Node.js runtime version), and `cli_version` (Context Hub CLI version)

The system uses a **stable client ID** generated by `getOrCreateClientId()` in [`cli/src/lib/identity.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/identity.js) for deduplication purposes. This identifier is a machine-specific UUID, not a personal identifier or user account.

### Implementation Details

The `trackEvent` function lazily initializes a PostHog client and fires fire-and-forget events:

```javascript
// cli/src/lib/analytics.js (simplified)
export async function trackEvent(event, properties = {}) {
  const client = await getClient();      // Returns null when disabled
  if (!client) return;
  const { getOrCreateClientId } = await import('./identity.js');
  const distinctId = await getOrCreateClientId();

  client.capture({
    distinctId,
    event,
    properties: {
      ...properties,
      platform: process.platform,
      node_version: process.version,
      cli_version: _cliVersion || undefined,
    },
  });
  await client.flush();                  // Immediate send due to short CLI lifecycle
}

```

Because the payload is entirely controlled by the calling code, no user-generated content is transmitted unless explicitly included by the CLI command implementation.

## Explicit Feedback Collection

### Feedback Payload Structure

When users run the `chub feedback` command, the `sendFeedback` function in [`cli/src/lib/telemetry.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/telemetry.js) transmits structured data to the Context Hub API. The payload includes:

- **Entry identification** – `entry_id` and `entry_type` (e.g., `openai/chat`, `doc` or `skill`)
- **User rating** – `"up"` or `"down"` indicating satisfaction
- **Documentation context** – Optional `doc_lang`, `doc_version`, `target_file`, and `labels`
- **User commentary** – Optional free-text `comment` and structured `labels`
- **Agent metadata** – Auto-detected or provided `agent` object containing `name`, `version`, and `model`
- **Client information** – `cli_version`, `source` registry, and `X-Client-ID` header (the stable UUID)

### The sendFeedback Implementation

The feedback system requires explicit opt-in and performs an enabled-check before transmission:

```javascript
// cli/src/lib/telemetry.js (simplified)
export async function sendFeedback(entryId, entryType, rating, opts = {}) {
  if (!isFeedbackEnabled()) return { status: 'skipped', reason: 'feedback_disabled' };
  
  const { getOrCreateClientId, detectAgent, detectAgentVersion } = await import('./identity.js');
  const clientId = await getOrCreateClientId();
  
  const res = await fetch(`${getTelemetryUrl()}/feedback`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Client-ID': clientId,
    },
    body: JSON.stringify({
      entry_id: entryId,
      entry_type: entryType,
      rating,
      doc_lang: opts.docLang || undefined,
      doc_version: opts.docVersion || undefined,
      target_file: opts.targetFile || undefined,
      labels: opts.labels || undefined,
      comment: opts.comment || undefined,
      agent: {
        name: opts.agent || detectAgent(),
        version: detectAgentVersion(),
        model: opts.model || undefined,
      },
      cli_version: opts.cliVersion || undefined,
      source: opts.source || undefined,
    }),
  });
  // ... response handling
}

```

## Opt-Out Mechanisms and Configuration

### Environment Variables vs Config File

Both telemetry streams respect dual opt-out mechanisms. The `isTelemetryEnabled()` and `isFeedbackEnabled()` functions in [`cli/src/lib/telemetry.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/telemetry.js) check environment variables before falling back to configuration file settings:

```javascript
// cli/src/lib/telemetry.js
export function isTelemetryEnabled() {
  if (process.env.CHUB_TELEMETRY === '0' || process.env.CHUB_TELEMETRY === 'false') return false;
  const config = loadConfig();
  return config.telemetry !== false;
}

export function isFeedbackEnabled() {
  if (process.env.CHUB_FEEDBACK === '0' || process.env.CHUB_FEEDBACK === 'false') return false;
  const config = loadConfig();
  return config.feedback !== false;
}

```

**Environment variables** take precedence:
- `CHUB_TELEMETRY=0` or `false` disables anonymous analytics
- `CHUB_FEEDBACK=0` or `false` disables rating submissions

**Configuration file** settings (in [`config.yaml`](https://github.com/andrewyng/context-hub/blob/main/config.yaml)) provide persistent controls:
- `telemetry: false` 
- `feedback: false`

### Default Settings

According to [`cli/src/lib/config.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/config.js), the default configuration enables anonymous analytics while keeping feedback disabled unless explicitly opted-in:

```javascript
// cli/src/lib/config.js
export const DEFAULTS = {
  telemetry: true,
  telemetry_url: DEFAULT_TELEMETRY_URL,
  feedback: false,
  // ... other defaults
};

```

## Key Source Files and Architecture

Understanding what telemetry data Context Hub collects requires familiarity with these specific modules:

- **[`cli/src/lib/telemetry.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/telemetry.js)** – Core opt-out logic, feedback API client, and telemetry URL handling
- **[`cli/src/lib/analytics.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/analytics.js)** – PostHog wrapper implementation and `trackEvent` function
- **[`cli/src/lib/config.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/config.js)** – Default configuration values and settings merge logic
- **[`cli/src/lib/identity.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/identity.js)** – Client ID generation and agent detection utilities
- **[`cli/src/commands/feedback.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/commands/feedback.js)** – CLI interface that invokes `sendFeedback`
- **[`cli/src/commands/search.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/commands/search.js)** – Example consumer of `trackEvent` for search analytics

## Code Examples: Practical Usage

### Checking Telemetry Status

Determine programmatically whether data collection is active:

```javascript
import { isTelemetryEnabled, isFeedbackEnabled } from './lib/telemetry.js';

if (isTelemetryEnabled()) {
  console.log('Anonymous usage analytics are enabled');
}

if (isFeedbackEnabled()) {
  console.log('Explicit feedback collection is enabled');
}

```

### Emitting Custom Analytics Events

CLI command implementations can emit custom telemetry using the analytics module:

```javascript
import { trackEvent } from './lib/analytics.js';

await trackEvent('search_executed', {
  query: userQuery,
  results_count: results.length,
  duration_ms: elapsedTime,
});

```

Only the global properties (`platform`, `node_version`, `cli_version`) are appended automatically; all other payload fields are caller-defined.

### Submitting User Feedback Programmatically

Integrate feedback collection into custom workflows:

```javascript
import { sendFeedback } from './lib/telemetry.js';

const result = await sendFeedback('openai/chat', 'doc', 'up', {
  comment: 'Excellent code examples provided',
  labels: ['accuracy', 'clarity'],
  docVersion: '1.2.0',
  cliVersion: '2.5.0',
});

if (result.status === 'skipped') {
  console.log('Feedback disabled by user configuration');
}

```

## Summary

- **Anonymous analytics** transmit event names, platform metadata (OS, Node.js version, CLI version), and caller-provided properties to PostHog only when `telemetry` is enabled (default: true)
- **Explicit feedback** sends ratings (`up`/`down`), optional comments, documentation context, and agent metadata to the Context Hub API only when `feedback` is enabled (default: false)
- **Opt-out controls** function via environment variables (`CHUB_TELEMETRY`, `CHUB_FEEDBACK`) or configuration file settings, with environment variables taking precedence
- **No PII collection** occurs; identifiers are stable machine UUIDs, and user content is only transmitted when explicitly provided for feedback purposes

## Frequently Asked Questions

### Is the telemetry data anonymous?

Yes, according to the `andrewyng/context-hub` source code, telemetry data is anonymous. The system uses a stable machine-specific UUID generated by `getOrCreateClientId()` for deduplication, but this identifier is not linked to personal information, user accounts, or repository content. Anonymous usage analytics only capture event types, platform metadata, and CLI versions, while explicit feedback requires user-initiated action.

### How do I completely disable telemetry in Context Hub?

Set the environment variable `CHUB_TELEMETRY=0` or `CHUB_TELEMETRY=false` to disable anonymous analytics, and `CHUB_FEEDBACK=0` or `CHUB_FEEDBACK=false` to disable feedback collection. Alternatively, add `telemetry: false` and `feedback: false` to your [`config.yaml`](https://github.com/andrewyng/context-hub/blob/main/config.yaml) file. Environment variables take precedence over configuration file settings, ensuring you can disable collection system-wide regardless of project-specific configurations.

### What is the difference between telemetry and feedback in Context Hub?

**Telemetry** refers to automatic, anonymous usage analytics sent to PostHog, including events like `command_run`, `search`, and `doc_fetched` along with system metadata (platform, Node.js version). **Feedback** refers to explicit user-initiated ratings (`up`/`down`) and comments sent to the Context Hub API when running `chub feedback`. Telemetry is enabled by default but can be opted out, while feedback is disabled by default and requires explicit opt-in.

### Does Context Hub collect my search queries or code content?

The **anonymous analytics** system in [`cli/src/lib/analytics.js`](https://github.com/andrewyng/context-hub/blob/main/cli/src/lib/analytics.js) does not automatically collect search queries or source code content. The `trackEvent` function only captures event names and explicitly provided properties from the calling command. However, specific CLI commands may choose to include search terms in the properties payload (e.g., the search command may log query parameters). **Explicit feedback** only transmits content you voluntarily provide in the `comment` field or contextual metadata about documentation entries you choose to rate.