Skip to content

feat: add PostHog telemetry to CLI with privacy controls & UX stabilisation#32

Merged
JaySym-ai merged 2 commits into
mainfrom
ux-stabilisation
Apr 10, 2026
Merged

feat: add PostHog telemetry to CLI with privacy controls & UX stabilisation#32
JaySym-ai merged 2 commits into
mainfrom
ux-stabilisation

Conversation

@JaySym-ai
Copy link
Copy Markdown
Collaborator

Summary

Adds anonymous usage analytics to the CLI via posthog-node, with full privacy controls and opt-out support. Also includes prior UX stabilisation work on this branch.

Telemetry Implementation

Events captured

Event When Key properties
cli_test_started Test session begins provider, persona, platform, deviceProfile, cliVersion
cli_test_completed Test session succeeds Above + durationMs, findingsCount, passed, failed, warnings
cli_test_errored Test session throws provider, persona, platform, error (scrubbed), cliVersion

Privacy & security

  • Anonymous-only: random UUID per machine, no person profiles ($process_person_profile: false)
  • PII scrubbing: error messages are stripped of file paths, home directories, and emails before sending
  • No sensitive data sent: no URLs, project names, code, or test content
  • First-run notice: users see a one-time stderr notice explaining what's collected and how to opt out
  • File permissions: ~/.getwired/telemetry.json written with 0o600 (owner-only)
  • Input validation: telemetry config is validated on load; malformed files are regenerated

Opt-out (3 ways)

  1. Dashboard: Settings → Telemetry → Disabled (persisted in .getwired/config.json)
  2. Config file: "telemetry": false in .getwired/config.json
  3. Environment: GETWIRED_TELEMETRY=0 or DO_NOT_TRACK=1

Build-time env injection

  • PostHog API key and host are stored in packages/cli/.env (gitignored)
  • Injected at build time via tsup's env option — not hardcoded in source
  • .env.example committed as a template for contributors

Other changes

  • Version bumped to 0.0.20
  • Fixed flaky update.test.ts that hardcoded version 0.0.19 — now uses 99.0.0 so it's version-agnostic
  • All 30/30 unit tests passing

Files changed

  • packages/cli/src/telemetry.ts — new telemetry module
  • packages/cli/src/orchestrator/index.ts — capture events on test start/complete/error
  • packages/cli/src/config/settings.tstelemetry boolean on GetwiredSettings
  • packages/cli/src/components/App.tsx — telemetry toggle in dashboard settings
  • packages/cli/tsup.config.ts — load .env for build-time injection
  • packages/cli/.env.example — template for PostHog credentials
  • packages/cli/tests/unit/update.test.ts — fix version-dependent test
  • packages/cli/tests/unit/security-payloads.test.ts — add telemetry to mock settings

Pull Request opened by Augment Code with guidance from the PR author

Add withStreamGuards wrapper that detects provider rate limits, token
exhaustion, and idle timeouts (5min) with automatic error yielding.
Integrate guards into all test session stream loops (web, desktop,
native) and surface error chunks as thrown errors.

Enhance HTML report findings with "Why this matters" context based on
severity and category, and generate fix prompts with reproduction steps.

Improve streaming UI with rotating activity messages, elapsed timer,
chunk counter, and better empty/connecting states. Add clickable
file:// links to HTML reports in CLI output across all test flows.
Expand finding cards in terminal views to show full descriptions,
URLs, and step sequences.
Integrate PostHog for anonymous telemetry to track test starts, completions, and errors across web, desktop, and native platforms. Add telemetry toggle to settings UI with clear privacy messaging that no URLs, code, or file paths are collected. Load environment variables during build for API key injection. Update tests to reflect new telemetry configuration field.
@snyk-io
Copy link
Copy Markdown

snyk-io Bot commented Apr 10, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@JaySym-ai JaySym-ai marked this pull request as ready for review April 10, 2026 16:58
@JaySym-ai JaySym-ai merged commit af2dbb6 into main Apr 10, 2026
5 of 7 checks passed
@JaySym-ai JaySym-ai deleted the ux-stabilisation branch April 10, 2026 16:58
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented Apr 10, 2026

🤖 Augment PR Summary

Summary: Adds anonymous PostHog telemetry to the GetWired CLI with opt-out controls, plus several UX and stability improvements.

Changes:

  • Introduced a new telemetry.ts module that persists an anonymous machine UUID and sends cli_test_started, cli_test_completed, and cli_test_errored events (with basic PII scrubbing).
  • Added a per-project telemetry setting (default on) and exposed it in the CLI dashboard Settings UI.
  • Instrumented the orchestrator to emit telemetry at test start/finish/error and to shutdown the telemetry client on completion.
  • Added withStreamGuards to wrap provider streams with idle-timeout and rate/token-limit detection to improve resilience.
  • Improved CLI UX: richer “Findings” rendering, clearer provider streaming status (elapsed time/activity messages), and clickable file:// links to generated HTML reports when present.
  • Updated build to load PostHog credentials from a local .env via tsup env, and added .env.example for contributors.
  • Bumped CLI version to 0.0.20 and stabilized the version-dependent update unit test.

Technical Notes: Telemetry is disabled via config, GETWIRED_TELEMETRY=0, or DO_NOT_TRACK=1, and uses $process_person_profile: false to avoid person profiles.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

process.stderr.write(
"\n" +
" ℹ GetWired collects anonymous usage analytics to improve the product.\n" +
" No private data, URLs, code, file paths, or error details are ever sent.\n" +
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first-run notice says “No … URLs … or error details are ever sent”, but captureTestErrored() does send a scrubbed error field and stripPii() doesn’t remove URLs. Consider aligning the notice text with the actual payload to avoid over-promising on privacy guarantees.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.


function stripPii(text: string): string {
return text
.replace(HOME_RE, "~")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stripPii() replaces the home directory with ~ before path scrubbing, which can leave ~/… / ~\… paths intact (and PATH_RE won’t match single-segment paths like /tmp). That means local path fragments could still end up in the cli_test_errored telemetry payload.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

/max.?tokens/i,
/capacity/i,
/overloaded/i,
/429/,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RATE_LIMIT_PATTERNS includes /429/, which can match incidental output (e.g., a random number) and incorrectly trigger a rate-limit error. Tightening this match to a more specific “HTTP 429”/status-code pattern would reduce false positives.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

isTimedOut: () => boolean,
): AsyncGenerator<T> {
while (true) {
if (isTimedOut()) return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raceTimeout() returns on timeout without closing/canceling the underlying gen, and the losing gen.next() from Promise.race() can remain pending. This may leave provider streams/subprocesses running after a timeout and could cause resource leaks or hangs in long-running sessions.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

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