feat(cli): add opt-out anonymous telemetry via PostHog

Add anonymous usage telemetry to help improve the CLI. Uses PostHog's
HTTP batch API directly (zero new dependencies) with a 5-second timeout
and fail-silent behavior — telemetry never breaks the CLI.

What's collected: command names, render performance (duration, fps,
quality), template choices, OS/arch/Node version/CLI version.

What's NOT collected: file paths, project names, video content, or
any personally identifiable information.

Telemetry is:
- Disabled in dev mode (running via tsx)
- Disabled in CI (CI=true) or via HYPERFRAMES_NO_TELEMETRY=1
- Disabled when API key is placeholder (safe to merge before key is set)
- Controllable via `hyperframes telemetry [enable|disable|status]`
- Disclosed on first run with clear opt-out instructions

Config stored at ~/.hyperframes/config.json (0600 permissions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
James
2026-03-25 22:55:56 +00:00
co-authored by Claude Opus 4.6
parent f84df64e64
commit b7c75b814c
9 changed files with 461 additions and 0 deletions
+3
View File
@@ -14,6 +14,7 @@ import { execSync, execFileSync, spawn } from "node:child_process";
import * as clack from "@clack/prompts";
import { c } from "../ui/colors.js";
import { TEMPLATES, type TemplateId } from "../templates/generators.js";
import { trackInitTemplate } from "../telemetry/events.js";
const ALL_TEMPLATE_IDS = TEMPLATES.map((t) => t.id);
@@ -380,6 +381,7 @@ export default defineCommand({
}
scaffoldProject(destDir, basename(destDir), templateId, localVideoName);
trackInitTemplate(templateId);
console.log(c.success(`\nCreated ${c.accent(name + "/")}`));
for (const f of readdirSync(destDir)) {
@@ -498,6 +500,7 @@ export default defineCommand({
const templateId: TemplateId = templateResult;
// 4. Copy template and patch
trackInitTemplate(templateId);
scaffoldProject(destDir, name, templateId, localVideoName);
const files = readdirSync(destDir);