Skip to content

Privacy & Analytics

Kangentic collects anonymous usage analytics, and crash and error reports, to help improve the product. No code or task content is ever collected.

Two vendors do two jobs, and both answer to the same kill switch: Aptabase counts product events, and Sentry groups and symbolicates errors so a crash is diagnosable rather than merely counted.

Usage analytics are powered by Aptabase, a privacy-first, open-source analytics platform designed for desktop apps.

EventWhen it firesProperties
app_launchApp startsPlatform, architecture
app_heartbeatEvery 30 minutes while at least one agent session is active; skipped when idle. Also fires once right before system sleepActive, suspended, queued, and total session counts
app_closeGraceful quit, Ctrl+C, SIGTERM, or OS shutdown/reboot/log-offDuration in seconds
app_errorUncaught exception, unhandled rejection, renderer crash, UI error boundary, updater failure, or a failed terminal spawnSource, sanitized message, plus per-source extras (see below)
project_createNew project created(none)
project_moveProject folder moved via Settings > General > Move(none)
project_relocateProject re-pointed at a moved or renamed folder(none)
session_spawnAgent session reaches running state (board or transient)Agent, whether the session is transient, the resolved permission mode, whether it ran in a git worktree
task_completeTask moves to DoneAgent, model, permission mode, duration, cost (USD), input/output tokens, tool calls
session_exitAgent session finishesExit code, duration, agent, model, cost (USD), tool calls, and whether the exit was intentional (a deliberate kill or suspend) rather than the agent stopping on its own
transient_session_spawnTransient session launched from command terminalAgent
onboarding_milestoneOnce per install, per funnel stepWhich step: first project, first task, first spawn, first completed task
feature_first_useThe first time you touch one of ten curated features, once per installWhich feature
feature_usedOnce per curated feature per UTC dayWhich feature
board_snapshotOnce per project per app run, when a project is opened coldColumn count, whether the columns differ from the seeded default, a bucketed task count, number of Board Profiles
update_outcomeNext launch after the app version changedApplied or rolled back, and the from/to versions
spawn_failedAn agent session failed to startAgent, and which path failed (create, auto-spawn, resume, unknown agent, CLI not found)

The costUsd, token, and tool-call properties are cumulative session metrics, omitted when not yet available - they are counts and totals only, never any code or content.

The curated feature vocabulary is exactly ten entries: command terminal, worktree session, board profile, pop-out window, browser pane, MCP server, mobile bridge, usage dashboard, Quick Find, and settings. Each contributes at most one feature_used event per day, and the event says only that the feature was touched - never what you used it for. Renderer-reported features cross a single IPC channel and are re-validated against that list in the main process, so a drifted renderer cannot invent new event names.

board_snapshot sends counts only. Column names and task content never leave the machine, and the task count is bucketed (0, 1-9, 10-49, 50-199, 200+) rather than sent exactly.

An app_error’s source says which failure path it came from: uncaughtException, unhandledRejection, render-process-gone (adding the crash reason and exit code), error_boundary (adding which of the three reporters caught it, the failing panel’s label, and a trail of React component names), updater, and pty_spawn (adding the shell, whether the shell and working directory exist, the errno, and the platform).

A UI error’s component trail sent to Aptabase is names only. The raw React component stack does not go there, because a production stack frame embeds a file:// URL containing your home directory; Kangentic reduces it to component names in the main process, and a name cannot carry a path. Sentry receives the real stack instead, with paths normalized first - see Crash and Error Reports.

The Aptabase SDK also records: OS name, OS version, locale, app version, and country (derived from IP, then immediately discarded).

The app_launch event alone carries clientId, a non-reversible id Kangentic derives from your OS install (an HMAC-SHA256 digest of already-hashed machine and home-directory identifiers, keyed with a fixed salt). It is attached only to app_launch - the one authoritative per-launch install signal - so unique installs can be counted without inflating every other event with a high-cardinality string. It contains no raw machine identifiers, paths, or usernames.

It is, however, stable: the same value across app updates, and unchanged by an uninstall and reinstall. It is unique per OS user account. A stable identifier of that kind is ordinarily personal data under the GDPR, so it is described here rather than filed under “nothing personal”. It shares the same KANGENTIC_TELEMETRY control as every other event - there is no separate opt-out.

Crash monitoring is separate from product analytics and goes to Sentry. Aptabase’s app_error stays a coarse error-rate pulse; Sentry is what turns a crash into something diagnosable, with grouping, deduplication, and a readable stack trace instead of a truncated string.

  • Paths are normalized before anything leaves your machine. The Sentry SDK rewrites stack-frame paths and URLs relative to the app root, so your home directory does not travel with a stack trace. Personally identifiable data collection (sendDefaultPii) stays off, and Sentry’s own server-side data scrubbing is on.
  • Errors only. Release-health session tracking is filtered out, and performance tracing and session replay are never enabled.
  • The renderer has no network path of its own. Renderer errors travel to the main process over internal IPC, and the main process is the single point of egress - the same shape as the analytics funnel.
  • Errors that used to be counted are now reported. Deliberate catch sites that previously emitted only a sanitized count (updater failures, terminal spawn failures, silent agent-spawn catches) send the real error, so a hidden problem is fixable rather than just visible as a number.
  • Affected-install counts use the same clientId described above, attached as the Sentry user id so an issue’s user count means “installs affected”. It carries no personal data and shares the same opt-outs.
  • Source maps never ship. They are uploaded at release time and deleted from the build output, so stack traces resolve on Sentry’s side rather than from anything in the app you installed.
  • Task titles, descriptions, or any user-generated content
  • Project names or code
  • File paths: analytics events never carry one, and stack-frame paths in an error report are normalized to the app root before it is sent
  • Usernames, emails, or personally identifiable information
  • Mid-board task moves (only completion is tracked)
  • What you did with a feature: feature_used records that a feature was touched on a given day, never the content of that use

KANGENTIC_TELEMETRY is the superset switch - setting it to 0 disables usage analytics and error reporting. KANGENTIC_ERROR_REPORTING controls error reporting alone.

VariableValueBehavior
KANGENTIC_TELEMETRY0 or falseAll telemetry disabled: analytics and error reporting
KANGENTIC_TELEMETRY1 or trueTelemetry force-enabled, even in dev builds (useful for local testing)
KANGENTIC_TELEMETRY(unset)Enabled in production builds, disabled in development
KANGENTIC_ERROR_REPORTING0 or falseError reporting disabled; usage analytics unaffected
KANGENTIC_ERROR_REPORTING1 or trueError reporting enabled even in dev builds, unless KANGENTIC_TELEMETRY=0
KANGENTIC_ERROR_REPORTING(unset)Follows whatever KANGENTIC_TELEMETRY resolves to

Open Settings > Privacy to see a summary of what is and isn’t collected. The Privacy tab is informational - opt-out is controlled exclusively by the environment variables above. It also points to the Memory tab for the (fully local) conversation-search controls described below.

Two of Kangentic’s newest features process your data with local, on-device models and no API key:

  • Conversation Memory indexes your agents’ past conversations so you can search and recall them. Indexing is fully local: only the structured conversation turns are indexed (never the raw terminal scrollback), the index lives inside each project, and searching never leaves your machine. Indexing is on by default and can be turned off; the optional semantic-search layer is opt-in. The only network access is a one-time download of a local embedding model (from Hugging Face) the first time you enable semantic search - after that it runs offline. Manage it under Settings > Memory, including a Rebuild index action.
  • Dictation transcribes push-to-talk voice to text on-device by default (an optional cloud endpoint can be configured for the final refinement pass only; the live preview always stays local).

Neither feature sends your code, task content, or conversations to Kangentic or any analytics backend.

  • All telemetry leaves from the main process - the renderer never opens a network path of its own, for analytics or for error reports
  • Error messages are sanitized to strip file paths before transmission, and error-report stack frames are rewritten relative to the app root
  • Aptabase uses no cookies, and its own session IDs are random and rotate daily. Kangentic separately attaches a non-reversible clientId (see above) so it can count unique installs; it is not an Aptabase feature
  • The analytics request reveals your IP address to Aptabase, which resolves it to a country and then discards the address
  • All analytics calls are fire-and-forget and never block the app
  • Analytics retention follows Aptabase’s privacy policy; error reports follow Sentry’s plan retention for the Kangentic organization

Kangentic stores your task, session, and conversation data locally on your own machine, so most data requests are things you can act on yourself. Deleting a project’s .kangentic/ directory removes that project’s tasks, sessions, board history, and conversation index. Global settings and debug logs live outside it, in the platform config and log directories listed under Configuration and Troubleshooting. The only data that leaves your machine is the anonymous analytics and error reports described above, which carry no identifier that could be traced back to you.

If you have a question about this policy, or a request that needs a human, email hello@kangentic.com.

See also:

  • Privacy Policy - the formal policy covering desktop, mobile, and this website
  • Settings - the in-app Privacy tab summarizing collection
  • Auto-Updates - what’s checked when the app polls for new versions

Kangentic is free and open source. A star helps other people find it.

Star on GitHub