Skip to content

Add anonymous usage telemetry via TelemetryDeck#314

Merged
bguidolim merged 2 commits intomainfrom
bruno/telemetry-deck
Mar 31, 2026
Merged

Add anonymous usage telemetry via TelemetryDeck#314
bguidolim merged 2 commits intomainfrom
bruno/telemetry-deck

Conversation

@bguidolim
Copy link
Copy Markdown
Collaborator

Summary

  • Adds TelemetryDeck Swift SDK to track anonymous CLI usage (command name + version)
  • User identity derived from hardware UUID (IOPlatformUUID), salted and SHA-256 hashed — tamper-proof, never stored on disk
  • Opt-in by default; disable with mcs config set telemetry false
  • First-run notice shown once per machine (marker file in ~/.mcs/)
  • All 13 commands instrumented with type-safe MCSAnalytics.Command enum
  • SDK session tracking disabled (sendNewSessionBeganSignal = false) — unnecessary overhead for short-lived CLI
  • 200ms flush timeout after signal dispatch for reliable delivery before process exit

Files changed

File Change
Package.swift TelemetryDeck SDK dependency
Sources/mcs/Core/Telemetry.swift New — MCSAnalytics wrapper (init, track+flush, anonymous ID, first-run notice)
Sources/mcs/Core/MCSConfig.swift telemetry config key (default: true)
Sources/mcs/Core/Constants.swift Constants.Telemetry enum (app ID, marker filename)
Sources/mcs/Commands/*.swift Instrumentation in all 13 commands
.swiftlint.yml function_body_length warning 150→160

Design decisions

  • Hardware UUID over file-based ID: IOPlatformUUID from IOKit firmware cannot be tampered with by userspace, unlike a file that could be deleted/modified
  • Hardcoded app ID: Accepted tradeoff for open-source (Homebrew model) — low incentive to spoof CLI user counts
  • No separate flush() method: Track and flush are always paired in CLI lifecycle, so trackCommand() handles both to prevent temporal coupling
  • PackCommandContext centralizes init: All 5 pack subcommands share the constructor, eliminating 5 duplicate init calls
  • Hook mode skips telemetry: check-updates --hook runs on every Claude Code session start — tracking it would generate excessive noise

Test plan

  • swift build — compiles without warnings
  • swiftlint — 0 violations
  • swift test — all 953 tests pass
  • mcs config list — verify telemetry key appears with default true
  • mcs config set telemetry false → run any command → verify no network calls
  • mcs sync --dry-run with telemetry enabled → verify signal appears in TelemetryDeck dashboard
  • Verify ~/.mcs/.telemetry-noticed marker file created after first run

- Add TelemetryDeck SDK dependency and MCSAnalytics wrapper using
  hardware UUID (IOPlatformUUID) for tamper-proof anonymous identity
- Track command execution across all 13 commands with type-safe
  Command enum, opt-in by default (disable via `mcs config set
  telemetry false`), first-run notice with marker file
- Integrate into all commands with centralized init in
  PackCommandContext; skip telemetry in hook mode for check-updates
- Fix try?/unchecked createFile violation in first-run notice with
  do/catch and output.warn(), add double-init guard, pass output to
  MCSConfig.load, fix opt-in→opt-out terminology
- Use defer for trackCommand in all commands to track both success
  and failure invocations consistently
- Add isTelemetryEnabled computed property on MCSConfig and tests
  for telemetry key roundtrip, value/setValue, and opt-out semantics
@bguidolim bguidolim merged commit 5918507 into main Mar 31, 2026
4 checks passed
@bguidolim bguidolim deleted the bruno/telemetry-deck branch March 31, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant