Legal
Privacy Policy
This policy covers the Kangentic desktop app, the Kangentic Mobile companion app, and this website. It explains what each one collects, what it deliberately does not, and what you can turn off.
The short version
Kangentic is a desktop app that runs coding agents on your own machine. Your boards, tasks, and agent transcripts are stored on your device and are never uploaded to a Kangentic server.
Five things do leave your machine, and only these:
| What leaves | Where it goes | Can you turn it off |
|---|---|---|
| Anonymous usage analytics, desktop | Aptabase | Yes, KANGENTIC_TELEMETRY=0 |
| Crash and error reports, desktop, including native crash dumps | Sentry |
Yes, KANGENTIC_ERROR_REPORTING=0 (or KANGENTIC_TELEMETRY=0, which turns off both)
|
| Update checks, desktop | GitHub Releases | No setting |
| Announcement checks, desktop | GitHub (raw.githubusercontent.com) | No setting |
| Crash reports, mobile official builds | Sentry | Yes, build from source |
Separately, the coding agents Kangentic launches are third-party tools that talk to their own providers under your own accounts. That traffic is between you and them; Kangentic does not proxy it and never sees it. See Coding agents you run.
There is no Kangentic account, no login, no licence key, and nothing to sign up for. We do not sell data and we do not run advertising or cross-site tracking.
What stays on your device
The desktop app keeps its data in a local SQLite database in your operating system's application-data directory:
%APPDATA%\kangentic\on Windows-
~/Library/Application Support/kangentic/on macOS -
$XDG_CONFIG_HOME/kangentic/on Linux, defaulting to~/.config/kangentic/
That local data includes:
- Your projects, tasks, and backlog items
- Agent session transcripts, which are a copy of the agent's terminal output with colour codes stripped
- A compressed copy of each agent conversation, kept so it stays readable after the agent's own tool deletes its transcript file
- The search index of your conversations, tasks, and commits, plus task summaries and your code when you turn those Knowledge Graph sources on
- Absolute paths to your projects and git worktrees
- Usage and cost figures for your own sessions, and for the agent calls Kangentic makes for you, such as checking an automation's condition or naming a task
Each project folder also gets a .kangentic/ directory,
which Kangentic adds to the project's .gitignore. It holds
that project's settings, its git worktrees, per-session files, the files
and images you attach to tasks, and logs.
None of this is transmitted to Kangentic. It is also not encrypted at rest: the database is an ordinary file protected by your operating system's file permissions, so it is only as private as the machine and user account it sits on. Credentials you supply for optional integrations, such as an Asana or Azure DevOps personal access token, are encrypted using your operating system's secure storage (Keychain on macOS, DPAPI on Windows, and on Linux the desktop's secret portal or a Secret Service keyring such as GNOME Keyring or KeePassXC, with KWallet as a fallback). On a system where that secure storage is unavailable, Kangentic warns and falls back to storage that anyone who can read the file can decode, in which case you must trust the local filesystem.
Kangentic does not store API keys for any AI provider. The agent CLIs use their own credentials, which they manage themselves.
Desktop app: usage analytics
The desktop app sends anonymous usage analytics through Aptabase, a privacy-focused analytics service for desktop apps. Analytics are enabled by default in official packaged builds and disabled in development builds.
Events are high-level counters: the app launching or hitting an error; a project being created, moved, or re-pointed; an agent session starting, finishing, or failing to start; a task reaching Done; how many processes a finished task's agent left running and how many were stopped; an update being applied; the shape of a board when it is opened; and whether one of eighteen named features has been touched today. Their properties are counts, durations, exit codes, the agent and model identifier, permission mode, and token and cost totals. Error messages are stripped of file paths and truncated before being sent, and no stack traces are included in an analytics event.
There is no event for the app closing. Instead, each launch reports how long the previous run lasted and whether it ended normally, was force-quit after hanging, or stopped without warning. That is a duration and a label; it says nothing about what you did during the run.
Once per run the app also sends a settings snapshot: which of fifteen named global settings you have changed away from their default, and what you changed them to. It exists to tell us whether a default is right. It can read only those fifteen settings, and each one can leave only as a fixed value type: a yes or no, a choice from a known list, a number reduced to a range, or a short value checked against a pattern. Anything that does not fit is sent as the word "other" rather than as what you typed. Free-text settings are outside the list entirely, so server addresses, credentials, file paths, startup scripts, and keyboard shortcuts cannot be read by it. A machine running stock settings sends the event with nothing in it.
Counts are counts, never content. A board snapshot sends how many columns a project has and a bucketed range for how many tasks, never their names. A feature event says a feature was used on a given day, never what it was used for. No task titles, descriptions, file paths, project names, code, or agent output is ever included in an analytics event.
Two things in this stream are worth stating plainly rather than filing under "anonymous":
- A stable installation identifier. One event per
launch carries a
clientId, as do the two events that fire at most once for the life of an installation (the first time you use a named feature, and each onboarding step you first reach). It is a non-reversible digest derived from your operating system's machine identifier and your home directory path. It contains no raw machine identifier, path, or username, and it is not used to build a profile of how you use the app. It is, however, stable: it is the same value across app updates, and it stays the same if you uninstall and reinstall. It is unique per operating-system user account. - Your IP address. As with any network request, the analytics request reveals your IP address to Aptabase, which resolves it to a country and then discards it. The country is retained; the address is not.
A stable identifier and an IP address are ordinarily personal data under the GDPR, so we describe them here rather than claiming the stream contains nothing personal at all.
Turning analytics off
Set the KANGENTIC_TELEMETRY environment variable to 0 or false. This disables every analytics
event, including the installation identifier, and it disables error
reporting too. To keep usage analytics and switch off only the error
reports, set KANGENTIC_ERROR_REPORTING=0 instead. There is
no in-app opt-out: the Privacy tab is informational only, so the
environment variables are the control.
To make it permanent, add it to your shell profile or your system environment variables. For the full event table and per-platform instructions, see Privacy & Analytics in the documentation.
Desktop app: update and announcement checks
On every platform the app checks GitHub Releases for a new version shortly after launch and then every four hours. Each check reveals your IP address, the app version, and your platform to GitHub, in the same way visiting any web page would. Updates are downloaded only after a newer version is found, and installed when you quit the app.
Linux is the exception to that last step: a packaged Linux build checks and downloads like the others, but installing needs your package manager, so the update stays staged until you choose Restart to update. See Auto-Updates for details.
Separately, the app downloads a small file of product announcements, announcements.json, from the project's public GitHub
repository on raw.githubusercontent.com. It checks 10 seconds after
launch and then every four hours. The request is a plain download:
Kangentic adds no version, platform, or identifier to it, and picks the
entries meant for its own version and platform only after the file
arrives. Like any request, it reveals your IP address to GitHub. KANGENTIC_TELEMETRY does not affect it, and development
builds make it too. See In-app announcements
for what the app shows.
Desktop app: crash and error reports
When the desktop app crashes or hits an unexpected error, it sends an error report to Sentry, the same third-party error-monitoring service the mobile app uses, so the fault can be found and fixed. This is diagnostics, not analytics: it is about the app breaking, not about you using it.
A crash inside native code produces a crash dump: a snapshot of the failing program's memory and loaded libraries at the moment it stopped. A dump for a child process that fails while the app is running is sent then; a dump left behind by a crash that took the whole app down is found and sent on the next launch.
Two safeguards apply before one is sent. Kangentic checks that the dump
is actually its own: on macOS, a program Kangentic starts can write its
crash into Kangentic's dump directory. The app clears its crash handler
before it starts a terminal's program or a shell, and the check stays
for anything that still gets through. A dump whose list of loaded code
can be read and contains none of Kangentic's own is never uploaded,
because it holds another program's memory. In its place Kangentic sends
a single warning that a foreign program crashed, without the dump or the
trail of recent app events. The warning names that program only when it
ran from a location that installers and package managers use, such as a
system directory, Homebrew, or a per-user toolchain directory; otherwise
it reads
user-binary. A program of your own that you installed into
one of those locations, for example with cargo install,
keeps its name. A dump that
cannot be read is sent as Kangentic's own, deliberately, so that a fault
in the reader cannot silently discard real crashes. And a dump of
Kangentic's own is filed against the app version that crashed rather
than the version that happened to upload it.
An error report contains the error type, its message, the stack trace,
the app version, and the platform. Before it leaves your machine, the
Sentry SDK rewrites every stack-frame path and URL relative to the
application root, so your home directory does not travel with the
trace, and the app replaces your home directory with ~ in
every other string of the report, such as an error message.
Personally identifiable data collection is switched off in the SDK,
Sentry's own server-side scrubbing is on, and performance tracing and
session replay are never enabled.
A native crash's stack is assembled on Sentry's servers from the uploaded crash dump, beyond the app's own rewriting. A rule on our Sentry project replaces home-directory paths in those fields. One field is not reached by it: the install location of the app itself, which on a per-user install sits inside your home directory. Sentry does not store the IP address a report arrives from, but it keeps the city it derives from that address.
A page you open in the app's built-in browser pane runs inside the app, so its crash would otherwise be reported as the app's. Such a crash is reported as a bare warning that a browser page crashed, with the page's address, its stack, and the crash dump removed.
A report also carries a short trail of what the app did just before the error. Each entry is filtered on your machine before it is recorded. Console output is dropped except for a short list of diagnostic lines, which are rebuilt with paths redacted and without error text. Clicks lose their title and label text. A network request keeps its address only when it is one of Kangentic's own, and never its query. When a program the app started fails to launch or exits with an error, the entry keeps the program's file name but not its folder. Anything the filter cannot judge is dropped.
The report carries the same anonymous clientId described
above as its user identifier, so an issue can be counted as "installs
affected" rather than left as an unbounded number of reports. It is the
same non-reversible digest, with the same properties and the same
opt-outs, and it is not used to build a profile of how you use the app.
The anonymous app_error analytics event described above
still fires alongside it, and it is deliberately narrower: it carries a
sanitised message and no stack trace. A user-interface error adds two
fields that say where it happened: which of the three reporters caught
it, and the failing panel's label. The React component stack is never
sent to Aptabase at all, because a production stack frame embeds a file:// URL containing your home directory. It does not
leave the process that produced it; the readable stack goes to Sentry
instead, with paths rewritten first.
One error report carries free text rather than a stack trace: when one
of Kangentic's own background helper processes crashes, the report
includes the last 8 KiB of that helper's error output, because an exit
code alone cannot say why it stopped. Your home directory is replaced
with ~ in that text at the moment it is captured.
Set KANGENTIC_ERROR_REPORTING to 0 or false to switch error reporting off while leaving usage
analytics on. KANGENTIC_TELEMETRY=0 switches off both.
Mobile app: crash reports
When the mobile app crashes or hits an unexpected error, official builds send a crash report to Sentry, a third-party error-monitoring service, so the fault can be found and fixed. This is diagnostics, not analytics: it is about the app breaking, not about you using it.
A crash report contains the technical details of the failure, and nothing about what you were doing in the app:
- the error type, message, and the stack trace showing where in the app's code it happened. When the app catches a failure and shows you an error instead of crashing, the message is replaced by a fixed label naming the part of the app that caught it. A message is kept when the app itself crashes, including when a screen fails to draw, because that text is written by the app rather than by anything you typed or received
- the app version, plus the standard device diagnostics that accompany any crash report: your device model, its operating system version, and the ordinary technical state alongside them (things like battery level, free memory and storage, screen size and orientation, and device timezone)
- when the crash is caught by the operating system rather than by the app's own code, a short trail of technical state changes leading up to it: the app moving to the foreground or background, battery level and charging state, the screen turning on or off, and network conditions such as connection type, whether a VPN is active, signal strength, and approximate data throughput. These describe the app's and device's technical state, never yours
- a note that the system warned the app it was running low on memory, and how many such warnings there had been since the app started. It is a count and nothing more. The system can shut the app down for using too much memory without producing a crash report at all, and without the note there is no way to tell that apart from the app freezing or you closing it. In practice this applies to iPhone and iPad: recent Android versions no longer send this kind of low-memory notice, and the app does not count the notice they send when you switch away, so it never records how often you moved between apps
- an approximate location, at the level of a city and country, which Sentry works out from the IP address the report arrives from. The app never reads your location and has no location permission; this is Sentry's own lookup when the report reaches it. It is kept because where a failure happens can matter to fixing it, for example a network problem limited to one region
It deliberately does not contain your session content. No screenshots, no screen recording, no on-screen text, no keystrokes, no console output, no network request details, no transcripts, terminal output, code or diffs, no notification content, and no pairing or encryption keys. Those are not stripped out afterwards; they are never collected in the first place.
There is no account to attach an identifier to, and the app sends no account, email, username, or user profile with a crash report, and does not use crash data to build any picture of how you use the app. A crash report does carry one identifier: a random ID generated on your device by the crash-reporting software itself, not by Kangentic. It resets if you uninstall and reinstall the app, it is not your device's hardware ID or an advertising ID, and it is not used to identify you or to link a crash report to any other data. When the crash is caught by the operating system rather than by the app's own code, that same random ID is also recorded as the report's user field, which is why it is declared to both app stores.
Builds you compile yourself from the open-source repository have crash reporting switched off entirely and send nothing.
Mobile app: camera, microphone, notifications
- Camera. Used only to scan the QR code the desktop app displays during pairing. Camera frames are processed on-device to read the code and are never stored or transmitted.
- Microphone. Used only when you tap dictation in the message composer, to turn speech into text via your device's built-in speech recognition. Audio is not stored or transmitted by Kangentic. Your device's speech engine may itself send audio to its own provider, for example Google or Apple, to produce the transcript; that processing is governed by your device provider's privacy policy, not this one.
- Notifications. The app registers for push notifications so the desktop can alert you to activity in your agent sessions. Push payloads are end-to-end encrypted ciphertext plus a generic placeholder; Kangentic's servers and any relay never see the plaintext content, and decryption happens only on your device.
Pairing your phone, and the relay
Pairing a phone to a desktop links them directly. Because the desktop usually sits behind a home or office router, both devices connect outward to a small relay server that forwards bytes between them.
Everything that crosses the relay is end-to-end encrypted between your phone and your desktop. The relay forwards opaque ciphertext and has no ability to decrypt it: it holds no keys, and the encryption is negotiated directly between your two devices inside the tunnel it forwards. Session content is never written to a Kangentic server or to any third-party service.
Being blind to content is not the same as being invisible, so here is what a relay operator can still observe, including Kangentic when you use the hosted one:
- Source and destination IP addresses of both peers.
- Connection timing: when each peer connects, disconnects, and reconnects.
- Frame sizes and frequency, which is traffic shape rather than content.
- The pairing graph: which connections were rendezvoused together.
This is inherent to operating any relay and is not specific to Kangentic's. The relay writes nothing to disk, and its logs contain no connection identifiers and no client IP addresses. On the hosted instance, TLS is terminated by Cloudflare, which therefore sees the connection URL and the routing identifier it carries. You can remove Kangentic from this picture entirely by running your own relay: it is open-source and self-hostable, and pointing your desktop at it is a single setting. See The Hosted Relay and Self-Hosting the Relay.
Push notifications are delivered through Expo's push service and the platform push networks, which are Firebase Cloud Messaging on Android and APNs on iOS. Those services see your device's push token and delivery timing. They receive only the encrypted payload and a generic placeholder title, never the decrypted content.
On the phone, pairing keys and trust anchors are stored in your device's hardware-backed secure storage: the Keychain on iOS, the Android Keystore on Android. Session content lives only in memory on your device while the app is running.
Coding agents you run
Kangentic launches coding-agent command-line tools that you have already installed, using the credentials you have already configured for them. Supported agents are Claude Code, Codex, Gemini, Cursor CLI, GitHub Copilot CLI, Grok Build, Antigravity CLI, Goose CLI, OpenCode, Aider, Qwen Code, Kimi Code, Factory Droid, Warp (Oz CLI), and Ollama.
With the exception of Ollama, which runs models locally, these tools send your prompts, your code, and their tool output to their own providers, under your own account with that provider. That is what they are for. Kangentic does not proxy those requests, does not hold the API keys, and does not see the traffic. What you send to each provider is governed by that provider's own privacy policy and your agreement with them.
Kangentic does read and store the resulting session transcripts locally, as described in What stays on your device, and it writes task titles and descriptions into the agent's terminal when you start or hand off a session.
Kangentic also runs an agent itself for a few small jobs, once you choose one as the Automation agent in Settings > Workflows: checking an automation's condition against the agent's last reply, deciding whether a workflow task's work in a column is done, and naming tasks and Command Terminals. Each of those calls sends that text to the chosen agent's provider in the same way. Nothing runs until you choose an agent.
Optional features that use the network
These are off unless you turn them on or connect them:
- Cloud dictation. Voice dictation transcribes on-device by default and needs no network access. If you explicitly configure a cloud transcription endpoint, the recorded audio clip is uploaded to the URL you specify, using the API key you supply. The live preview still runs on-device. This is off by default and fails closed when no endpoint is configured.
- Speech and embedding model downloads. Enabling dictation or the Knowledge Graph downloads model weights from Hugging Face, and again only when you pick other models or an update replaces the ones you run. The models run offline. Indexing and searching your conversations is fully local and never leaves your machine.
- Knowledge Graph questions and task summaries. When you ask the Knowledge Graph a question, or let it write summaries of finished tasks, the app sends the relevant text to the AI agent you chose for it in Settings: passages from past conversations, task titles, descriptions, and figures, and, if you turned on source code, the closest passages of your code. That agent's own provider handles the text the same way it handles any task you give that agent. Nothing is sent until you choose an agent, and none of it goes to Kangentic.
- Backlog import. Connecting GitHub Issues, GitHub
Projects, Azure DevOps, or Asana contacts those services using
credentials you provide, to read the issues you ask it to import. For
GitHub this is delegated to the
ghcommand-line tool, so Kangentic never handles your GitHub token. - Git operations. Fetching and pushing contacts whichever git remotes your repositories are configured with.
- The embedded browser. Pages you or an agent navigate to in the built-in browser pane are ordinary web requests to those sites.
This website
kangentic.com uses Umami for basic traffic analytics: page views, referrers, coarse device and country information, and a count of clicks on the "Star on GitHub" links. Umami is cookieless and does not track visitors across other websites, so there is no advertising profile and no cross-site identifier.
The site is hosted on Cloudflare Pages. As with any web host, Cloudflare processes the network requests needed to serve pages to you, including your IP address.
The home page and the app figures in the documentation load the product demo from GitHub Pages (kangentic.github.io) when the figure scrolls into view, so GitHub sees your IP address and browser details for that request, with no referrer and no cookies. The demo itself runs on a sample install and makes no further requests.
What Kangentic never does
- No account. There is no sign-up, no login, no licence key, and no entitlement system, so there is no account data to collect.
- No selling of data. We do not sell or rent personal data, and we do not share it with data brokers.
- No advertising or cross-site tracking. No ad networks, no tracking pixels, no advertising identifiers.
- No reading of your content. Kangentic operates no service that can read your tasks, code, or agent transcripts. The relay carries ciphertext it cannot decrypt, and crash reports and analytics carry no session content.
Retention
- Local data stays on your device until you delete it.
Deleting a project in Kangentic removes its database and its
.kangentic/directory, along with thekangentic.jsonboard file in the project folder. Deleting the application-data directory removes every project's database but leaves each project's.kangentic/directory in place. - Crash and error reports, desktop and mobile, are retained by Sentry under the organisation's plan retention, 30 days on the current plan, and then deleted.
- Desktop analytics are retained by Aptabase under their own retention policy. Events carry no account identifier.
- Relay traffic is not stored. The relay forwards bytes between two live connections and keeps no database or message history.
Your choices
Because there is no account, most privacy controls are things you can do directly rather than requests you have to make of us:
-
Turn off all desktop telemetry with
KANGENTIC_TELEMETRY=0, or just the error reports withKANGENTIC_ERROR_REPORTING=0. -
Delete your local data by removing the application-data directory
listed above and each project's
.kangentic/directory, or by deleting a project in Kangentic, which removes both for that project along with itskangentic.jsonboard file. - Avoid Kangentic's relay entirely by self-hosting your own, or by not pairing a phone at all.
- Leave cloud dictation unconfigured, which is the default, to keep all voice transcription on-device.
- Build from source to get a mobile app with crash reporting compiled out.
We hold no account, email address, or user profile, so there is no per-user record for us to look up, export, or delete on request. Crash reports carry no identifier that can be traced back to a person and expire on their own within 30 days. If you have a question about data you believe relates to you, contact us using the details below and we will help as far as the data allows.
Changes to this policy
If this policy changes, the date at the top of this page will change and the revised policy will be published at this same URL.
Contact
Kangentic is a product of VORPAHL LLC.
Questions about this policy can be sent to support@kangentic.com or raised on the project's GitHub repository . Use email for anything involving logs or private project details.
To report a security vulnerability, use GitHub's private vulnerability reporting on the relevant repository, or email security@kangentic.com.
For a technical breakdown of every desktop analytics event and its properties, see Privacy & Analytics in the documentation.