Repository navigation
Opt-in usage analytics: onboarding prompt + PostHog client integration #2623
Description
Summary
Add an opt-in usage analytics prompt to onboarding, and instrument nodespaced (the daemon, packages/daemon) with a PostHog client to send feature-usage and crash/error events when the user opts in.
Blocked by
- Set up PostHog account and project for NodeSpace usage analytics #2622 (PostHog account/project + API key must exist first)
Why
We want visibility into which features get used and where things crash/error, to prioritize fixes — without ever touching note content. Given NodeSpace's privacy-sensitive, open-source audience, this must be a genuine opt-in (default off), not an opt-out checkbox, and the copy must be specific and auditable rather than a blanket "no data collected" claim.
This must be instrumented at the daemon, not the frontend. nodespaced is a standalone OS-service process (launchd/systemd/autorun) that every client connects to over gRPC: the Tauri GUI (via packages/desktop-app/src-tauri's gRPC client), the standalone nodespace CLI (packages/cli), and external agents via the published skill (packages/skill). The Svelte frontend never talks gRPC directly — it goes through Tauri to the daemon. Instrumenting only the frontend would capture GUI usage alone and miss CLI- and agent-driven usage entirely, which is a real and possibly dominant usage path for this product. PostHog client init, event emission, and the opt-in check must all live in packages/daemon.
Confirmed during investigation: there is currently zero existing telemetry/analytics/crash-reporting code anywhere in the repo. The only superficially similar thing is packages/agent/src/local_agent/otlp_tracer.rs — dev-only OpenTelemetry tracing, off by default, explicitly localhost-only because traces contain full prompts/user content. Useful precedent for "we already treat this class of data as sensitive," not something to build on directly. There's also no existing panic hook in the daemon (main.rs only wraps a panicked gRPC task's JoinHandle in .context(...) and propagates it as an error) — crash reporting means adding a real panic hook, not wiring into something that exists.
Scope
Onboarding UI (Tauri frontend)
- Add an analytics consent step to onboarding, default unchecked
- Copy along these lines (finalize wording during implementation):
Help improve NodeSpace
Share anonymous usage analytics — which features you use, and crash/error reports — so we know what to fix and improve. We never collect your notes, titles, or file contents. Not used for ads or marketing, and you can turn this off anytime in Settings. - Equal-weight "Continue without sharing" path — skipping must not be harder or more buried than opting in
- Persist the choice to a daemon-readable local file (e.g. under
~/.nodespace/), not just frontend local storage/settings — the daemon must be able to read consent state independent of whether the GUI has ever run - Expose a toggle in Settings to change the choice later; toggling must propagate to the daemon (e.g. daemon watches the file, or a gRPC call notifies it) so opt-out takes effect without requiring a daemon restart
CLI / headless first-run consent
- If
nodespacedis started and no consent file exists (e.g. a CLI-only user who never launched the GUI), thenodespaceCLI needs its own first-run consent prompt — do not default to opted-in just because the GUI onboarding was never seen, and do not silently skip consent for this path
PostHog client integration (daemon, packages/daemon)
- Add the PostHog Rust client to the daemon
- Gate client initialization on the stored opt-in flag — do not initialize (even in a buffered/no-op state) until the user has explicitly opted in, to avoid any risk of pre-consent event capture
- Disable autocapture and session recording in the client config (project-level default from Set up PostHog account and project for NodeSpace usage analytics #2622, but also enforce client-side)
- Tag events with client type (GUI / CLI / agent-skill) where derivable from the gRPC call, so usage across all three surfaces is distinguishable, not just aggregated
- Define initial event taxonomy — keep narrow for v1:
- Feature usage: gRPC/tool calls invoked, by client type (exact list TBD during implementation)
- Crashes/errors: daemon panics (via a new panic hook — none exists today), unhandled errors
- Explicitly excluded: note content, titles, file paths, embeddings, any user-generated text or prompt content
- Add a panic hook to the daemon that reports to PostHog (gated on opt-in) instead of only propagating as a
JoinHandleerror - Wire opt-out to fully stop event sending (not just pause) — flip back to opted-out should tear down the client
- Read the API key via build-time config per the distribution decision made in Set up PostHog account and project for NodeSpace usage analytics #2622
Testing
- Unit test: no events fire when opted out (client never initialized)
- Unit test: opting out after opting in stops further events
- Unit test: daemon started with no consent file and no GUI ever run does not silently opt in
- Verify no note content, prompt content, or file paths ever appear in an event payload (spot-check taxonomy against this)
Out of scope
- PostHog account/project provisioning (Set up PostHog account and project for NodeSpace usage analytics #2622)
- Server-side dashboards/analysis setup in PostHog itself
Activity
malibio commentedon Oct 3, 2026
On hold: deferred until after the first release. The current direction is that the daemon and CLI never send telemetry; any analytics in the desktop app would be opt-in. Website and cloud-side analytics may be tracked later, outside core.
malibio commentedon Oct 11, 2026
Closing as not planned in a backlog triage. On hold since early October, and the stated direction is that the daemon and CLI never send telemetry, which this set was written against. If opt-in analytics in the desktop app comes back, it is refiled in that form.