Skip to main content

Overview

Auto-Skill includes privacy-first anonymous telemetry to track skill usage and effectiveness. Telemetry helps measure which skills work best, identify improvement opportunities, and guide skill graduation decisions.
Privacy First: No PII, no content capture, no user tracking. Only aggregate metrics (counts, timing, outcomes).

What’s Collected

Telemetry records aggregate data only:

Skill Usage

  • Skill name (not content)
  • Usage count
  • Session ID (random)

Outcomes

  • Success/failure status
  • Duration (milliseconds)
  • No error messages or stack traces

Agent Context

  • Agent ID (e.g., “claude-code”)
  • No session content or file paths

Timestamps

  • ISO-8601 timestamps
  • No timezone tracking
Never Collected:
  • Usernames, emails, IPs
  • File paths or project names
  • Code content or search queries
  • User input or agent responses
  • Any personally identifiable information

Privacy Principles

From the source code documentation:
/**
 * Anonymous telemetry follows privacy-first principles:
 * - No PII collected (no usernames, IPs, file paths, or identifying data)
 * - No content capture (no search queries, file contents, or user input)
 * - Aggregate only (counts, timing, scores -- not specific values)
 * - Fire-and-forget (never blocks, silent failures)
 * - Transparent opt-out via environment variables:
 *     export AUTO_SKILL_NO_TELEMETRY=1   (tool-specific)
 *     export DO_NOT_TRACK=1              (universal standard)
 * - Automatically disabled in CI environments
 */

How to Disable

Telemetry is automatically disabled in CI environments and can be disabled manually:
export AUTO_SKILL_NO_TELEMETRY=1

Auto-Disable in CI

Telemetry is automatically disabled when any of these environment variables are set:
const CI_VARS = [
  "CI",
  "GITHUB_ACTIONS",
  "GITLAB_CI",
  "CIRCLECI",
  "TRAVIS",
  "BUILDKITE",
  "JENKINS_URL",
];
export function isTelemetryDisabled(): boolean {
  if (process.env.AUTO_SKILL_NO_TELEMETRY) {
    return true;
  }
  if (process.env.DO_NOT_TRACK) {
    return true;
  }
  return CI_VARS.some((v) => !!process.env[v]);
}

Fire-and-Forget Implementation

Telemetry never blocks or surfaces errors:
export function track(
  event: string,
  data?: Record<string, string | number>,
): void {
  if (isTelemetryDisabled()) {
    return;
  }

  try {
    const params = new URLSearchParams({
      t: TOOL_ID,
      e: event,
      v: TELEMETRY_VERSION,
      node: process.version,
      os: process.platform,
    });

    if (data) {
      for (const [key, value] of Object.entries(data)) {
        params.set(key, String(value));
      }
    }

    const url = `${TELEMETRY_ENDPOINT}?${params.toString()}`;

    // Fire-and-forget: ignore the response entirely
    const req = https.get(url, { timeout: 2000 }, (res) => {
      res.resume(); // Drain to free resources
    });
    req.on("error", () => {
      // Silent failure -- telemetry must never surface errors
    });
    req.end();
  } catch {
    // Silent failure
  }
}
2-second timeout: Telemetry requests time out after 2 seconds and never block your workflow.

Data Storage

Local Database

Telemetry events are stored locally in SQLite: Location: ~/.claude/auto-skill/telemetry.db Schema:
CREATE TABLE skill_telemetry (
  id TEXT PRIMARY KEY,
  skill_id TEXT NOT NULL,
  skill_name TEXT NOT NULL,
  session_id TEXT NOT NULL,
  agent_id TEXT NOT NULL DEFAULT 'unknown',
  duration_ms INTEGER,
  outcome TEXT NOT NULL,
  timestamp TEXT NOT NULL
);

CREATE INDEX idx_telemetry_skill ON skill_telemetry(skill_id);
CREATE INDEX idx_telemetry_timestamp ON skill_telemetry(timestamp);

Remote Beacon

Anonymous beacons are sent to:
const TELEMETRY_ENDPOINT = "https://t.insightx.pro";
const TELEMETRY_VERSION = "3.0.2";
const TOOL_ID = "auto-skill";
Beacon Format:
GET https://t.insightx.pro?t=auto-skill&e=skill_used&v=3.0.2&outcome=success&agent=claude-code&ms=1234

Usage

Record an Event

import { createTelemetryCollector } from "auto-skill";

const telemetry = createTelemetryCollector();

const event = telemetry.recordEvent({
  skillId: "react-testing",
  skillName: "React Testing Patterns",
  sessionId: "session-abc123",
  outcome: "success",
  agentId: "claude-code",
  durationMs: 1234,
});

console.log(`Recorded: ${event.id}`);

Get Effectiveness Report

const reports = telemetry.getEffectivenessReport();

for (const report of reports) {
  console.log(`${report.skillName}:`);
  console.log(`  Total Uses: ${report.totalUses}`);
  console.log(`  Success Rate: ${Math.round(report.successRate * 100)}%`);
  console.log(`  Avg Duration: ${report.avgDurationMs}ms`);
  console.log(`  Agents: ${report.agentsUsed.join(", ")}`);
  console.log(`  Last Used: ${report.lastUsed}`);
}
export interface EffectivenessReport {
  skillName: string;
  totalUses: number;
  successCount: number;
  failureCount: number;
  successRate: number;
  avgDurationMs: number | null;
  agentsUsed: string[];
  lastUsed: string; // ISO-8601
}

Get Raw Events

// Get last 100 events for a specific skill
const events = telemetry.getEvents("react-testing", 100);

for (const event of events) {
  console.log(`${event.timestamp}: ${event.outcome} (${event.durationMs}ms)`);
}

API Reference

createTelemetryCollector(dbPath?)

dbPath
string
Path to SQLite database file.Default: ~/.claude/auto-skill/telemetry.db

Methods

recordEvent
(params) => TelemetryEvent
Record a skill usage telemetry event.Parameters:
{
  skillId: string;
  skillName: string;
  sessionId: string;
  outcome: string; // "success" | "failure" | "partial" | "skipped"
  agentId?: string;
  durationMs?: number;
}
Returns: The recorded TelemetryEvent
getEffectivenessReport
(skillName?) => EffectivenessReport[]
Get effectiveness reports for skills.Parameters:
  • skillName?: string - Optional filter to a specific skill
Returns: Array of reports sorted by total uses descending
getEvents
(skillName?, limit?) => TelemetryEvent[]
Get raw telemetry events.Parameters:
  • skillName?: string - Optional filter to a specific skill
  • limit?: number - Maximum events to return (default: 100)
Returns: Array of events, newest first

CLI Commands

View Telemetry Status

npx auto-skill telemetry status
Telemetry Status: ENABLED

Local Database: ~/.claude/auto-skill/telemetry.db
Total Events: 1,234
Remote Endpoint: https://t.insightx.pro

To disable telemetry:
  export AUTO_SKILL_NO_TELEMETRY=1

Privacy Policy:
  - No PII collected
  - No content capture
  - Aggregate metrics only

View Effectiveness Report

npx auto-skill telemetry report

Disable Telemetry

npx auto-skill telemetry disable
Adds export AUTO_SKILL_NO_TELEMETRY=1 to your shell config.

What Events Are Tracked

Fired when a skill is executed.Data: { outcome, agent, ms }
Fired when a new skill is generated.Data: { source, agent }
Fired when a skill graduates from external to local.Data: { from_source, confidence }
Fired when a workflow pattern is detected.Data: { confidence, tool_count }

Integration with Graduation

Telemetry data drives skill graduation decisions:
import { createGraduationManager, createTelemetryCollector } from "auto-skill";

const telemetry = createTelemetryCollector();
const manager = createGraduationManager("...", "...");

// Get effectiveness reports
const reports = telemetry.getEffectivenessReport();

// Convert to graduation stats format
const stats: Record<string, Record<string, unknown>> = {};
for (const report of reports) {
  stats[report.skillName] = {
    source: "external",
    confidence: report.successRate,
    usage_count: report.totalUses,
    success_count: report.successCount,
  };
}

// Detect graduation candidates
const candidates = manager.detectCandidates(stats);

See Also

Skill Graduation

How telemetry drives skill graduation

Lock File

Integrity verification for skills

Build docs developers (and LLMs) love