# How Desktop Commander's Usage Tracker Collects and Reports Telemetry Data

> Discover how Desktop Commander's Usage Tracker collects and reports telemetry data. Learn about session statistics and anonymized event forwarding for better insights.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-08-06

---

**Desktop Commander tracks tool interactions through the `UsageTracker` class in [`src/utils/usageTracker.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/usageTracker.ts), which records session-based statistics locally and forwards anonymized events via the `capture` helper in [`src/utils/capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts).**

The `wonderwhy-er/DesktopCommanderMCP` repository implements a comprehensive telemetry pipeline that balances detailed usage analytics with user privacy. This system captures granular metrics about tool execution while ensuring sensitive data never leaves the user's machine, providing the development team with actionable insights without compromising security.

## Local Data Collection via UsageTracker

The `UsageTracker` class serves as the central hub for aggregating interaction data before any network transmission occurs.

### Session Management and Timeouts

Each user interaction belongs to a `UsageSession` object that tracks temporal boundaries. The system defines a **30-minute inactivity threshold** (`SESSION_TIMEOUT`) to determine session boundaries.

When a tool executes, `isNewSession()` checks if the elapsed time since the last activity exceeds this threshold. If so, `updateSession()` instantiates a fresh session object recording the start time, last activity timestamp, and command counter. This segmentation allows the team to analyze user engagement patterns and session duration metrics.

### Tool Call Metrics and Categorization

Every tool invocation updates granular counters through `trackSuccess()` and `trackFailure()` methods. The tracker maintains:

- **Global counters**: `totalToolCalls`, `successfulCalls`, `failedCalls`
- **Per-tool tallies**: `toolCounts` mapping individual tool names to execution counts
- **Category aggregations**: `filesystemOperations` and other domain-specific groupings

This categorization enables the product team to identify which capabilities see heavy adoption versus those requiring improvement.

### Non-Blocking Persistence

To prevent telemetry I/O from degrading tool responsiveness, statistics persist asynchronously via `saveStats()`. The method invokes `configManager.setValueNonBlocking('usageStats', …)`, ensuring that write operations to the local configuration store never block the critical path of tool execution.

### Feedback and Onboarding State

Beyond raw usage metrics, the tracker manages user journey states through methods like `markFeedbackPrompted()` and `markOnboardingShown()`. These respect explicit opt-out flags including `feedbackGiven` and `telemetryEnabled`, ensuring the system honors user preferences regarding prompt frequency and data collection.

## Remote Telemetry Reporting

While `UsageTracker` handles local aggregation, the `capture` function in [`src/utils/capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts) manages network transmission to the analytics infrastructure.

### Kill Switches and Privacy Controls

The telemetry pipeline implements multiple guardrails to respect user privacy. Before transmitting any data, `captureBase()` and `sendToTelemetryProxy()` verify:

1. The environment variable `DESKTOP_COMMANDER_DISABLE_TELEMETRY` is not set
2. The configuration flag `telemetryEnabled` remains true

Additionally, the system excludes UI-origin calls entirely through the `isInsideUiOriginCall()` guard:

```typescript
if (isInsideUiOriginCall()) return;

```

This prevents telemetry noise from interface rendering while capturing meaningful tool execution events.

### Data Sanitization and Anonymization

Before transmission, all payloads undergo rigorous scrubbing via `sanitizeError()`. This function strips path-like keys and error objects that might contain Personally Identifiable Information (PII). The sanitization ensures that file system paths, user directories, or error stack traces containing local system details never reach remote servers.

### Payload Enrichment

The `buildEventProperties()` function enriches events with contextual metadata:

- **Platform identification**: `os.platform()` output and container metadata from [`src/utils/system-info.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/system-info.ts)
- **Runtime detection**: Source identification (docker, npx, smithery)
- **Client attribution**: `client_name` and `client_version` from the current or remote client context
- **Remote signaling**: `remote: true` flag when `currentCallIsRemote` indicates the invocation originated from a remote device
- **Engagement metrics**: Static `engagement_time_msec` values for session analysis

### Transport and Retry Logic

Events POST to the primary endpoint `https://telemetry.desktopcommander.app/mp/collect` with a **3-second timeout** to maintain UI responsiveness. The implementation uses fire-and-forget semantics—errors do not bubble up to the user interface.

If the primary proxy fails, the system falls back to a Cloud Run URL defined in the configuration. Each payload includes a unique anonymous client ID generated via `configManager.getOrCreateClientId()`, enabling longitudinal analysis without identifying individual users.

```typescript
const payload = JSON.stringify({
  client_id: uniqueUserId,
  timestamp_micros: Date.now() * 1000,
  events: [{ name: event, params: eventProperties }],
});
// POST to proxy (fallback on error)

```

## Practical Implementation Examples

The following patterns demonstrate integrating the telemetry system into tool implementations:

```typescript
// Record a successful tool execution
import { usageTracker } from './utils/usageTracker.js';

async function executeReadFile(filePath: string) {
  try {
    const content = await fs.readFile(filePath, 'utf-8');
    await usageTracker.trackSuccess('read_file');
    return content;
  } catch (error) {
    await usageTracker.trackFailure('read_file');
    throw error;
  }
}

```

```typescript
// Emit custom telemetry events
import { capture } from './utils/capture.js';

async function handleUserOptOut() {
  await capture('server_telemetry_opt_out', {
    reason: 'user_request',
    timestamp: new Date().toISOString()
  });
}

```

```typescript
// Conditional feedback prompting
async function checkFeedbackEligibility() {
  if (await usageTracker.shouldPromptForFeedback()) {
    const { variant, message } = await usageTracker.getFeedbackPromptMessage();
    await usageTracker.markFeedbackPrompted();
    return { variant, message };
  }
  return null;
}

```

## Summary

- **Local tracking** occurs through `UsageTracker` in [`src/utils/usageTracker.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/usageTracker.ts), which manages session state (30-minute timeout), tool success/failure counters, and asynchronous persistence via `configManager`.
- **Privacy controls** include the `DESKTOP_COMMANDER_DISABLE_TELEMETRY` environment variable, the `telemetryEnabled` config flag, and automatic exclusion of UI-origin calls.
- **Data sanitization** removes PII through `sanitizeError()` and path stripping before network transmission.
- **Remote reporting** happens via `capture()` in [`src/utils/capture.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/capture.ts), which enriches events with platform/container metadata and posts to `https://telemetry.desktopcommander.app/mp/collect` using fire-and-forget semantics with a 3-second timeout.
- **Non-blocking architecture** ensures telemetry operations never degrade tool responsiveness, using asynchronous writes for local storage and background HTTP requests for remote reporting.

## Frequently Asked Questions

### How can users completely disable telemetry in Desktop Commander?

Users can disable telemetry by setting the environment variable `DESKTOP_COMMANDER_DISABLE_TELEMETRY` or by setting the `telemetryEnabled` configuration flag to `false` via the application's settings. When either condition is met, the `capture()` function returns early without transmitting data, though local usage statistics may still be collected for session management purposes.

### What specific data does the usage tracker record about tool executions?

The tracker records the tool name, success or failure status, categorical groupings (such as `filesystemOperations`), and temporal metadata including session start time and last activity. It explicitly excludes file paths, error stack traces, and other PII through the `sanitizeError()` function before any network transmission occurs.

### Where are the telemetry events sent and how reliable is the delivery?

Events are sent to `https://telemetry.desktopcommander.app/mp/collect` as the primary endpoint, with an automatic fallback to a Cloud Run URL if the primary request fails. Delivery uses fire-and-forget semantics with a 3-second timeout, meaning the system prioritizes UI responsiveness over guaranteed delivery—failed transmissions do not retry or alert the user.

### How does Desktop Commander distinguish between different user sessions?

The system creates a new `UsageSession` object after 30 minutes of inactivity, defined by the `SESSION_TIMEOUT` constant in [`src/utils/usageTracker.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/usageTracker.ts). The `isNewSession()` method compares the current timestamp against the `lastActivity` property, resetting session counters when the threshold is exceeded, which enables accurate engagement time calculations without requiring user authentication.