Terminal Deck 0.15.0

Privacy

Terminal Deck collects nothing. There is no account, no analytics, no telemetry and no crash reporting. The app makes one network request of its own, and it is not about you: it fetches the public release feed on GitHub to see whether a newer version exists. It also holds a link to a rendezvous relay so a paired phone can reach this machine; that link says only that the machine is online, and it can be switched off. Both are described below.

That is a short claim, so the rest of this page is the long version: what is written to your disk and where, what the app reads without copying, and the things that do reach the network — none of which are the app talking about you.

Last updated 14 August 2026 · applies to version 0.15.0

What is not here

Most privacy policies describe data collection. This one has to start by listing the collection that does not happen, because otherwise the rest reads as evasion.

  • No account. There is nothing to sign up for and no sign-in screen anywhere in the app.
  • No analytics or telemetry. No usage events, no feature counters, no anonymous identifiers, no first-run ping. The source contains no analytics SDK of any kind.
  • No crash reporting. Electron's crash reporter is never started. When something goes wrong it is written to a local log file and nowhere else.
  • One update check, and it carries nothing. Twenty seconds after launch, and again when you come back to the window but never more than once an hour, the app fetches the release feed — a public file on GitHub, requested the same way your browser would request it. No identifier, no version history, no machine fingerprint is attached; GitHub sees an IP address and a user agent, as it does for anyone downloading the app. Nothing is downloaded or installed unless you press the button in Settings → Help.
  • No credential handling. There is no API key field. Agent CLIs sign you in themselves, inside the terminal, and keep their credentials where they normally keep them — on macOS, the Keychain.

What is stored, and where

Everything the app writes lives in its own folder under ~/Library/Application Support/, apart from the hook backups. Settings → Advanced lists the real paths on your machine and opens them in Finder, which is more reliable than a path printed on a web page.

settings.json
Everything in the settings window: theme, notification choices, agent defaults, browser preferences, shortcut overrides.
state.json
The project folders you have opened and when, your preferences, and the window's size and position.
profiles.json, profiles/
Your agent accounts — a name, a colour and a configuration directory each — and the configuration directories for the ones the app created. The file keeps its original name on disk. What goes inside those directories is written by the agent CLI, not by this app.
dashboards/
Your dashboard widget layouts, one file per project.
copilot/, copilot-layer/, copilot-log/
The copilot's working folder, the instructions and memory it is handed before it starts, and a log of what it did. The last two are outside the folder it can write to, on purpose: an audit log the audited party can rewrite is not an audit log.
routines/, routine-state.json
The routines you saved and when each last ran.
remote/
The devices paired with this machine and the keys that seal the channel to each. Empty until you pair something.
logs/
A rotating application log, capped at roughly 1.5 MB in total. It records what the app did — which module failed, how long a call took — not what you or the agent said, and every line is passed through redaction before the Debug panel shows it.
Browser partition
The embedded browser tab's cookies, storage and cache, in a partition folder of their own. See the browser section.
Hook backups
Before the app first edits an agent CLI's settings file, it copies that file to ~/.terminaldeck/hook-backups/.

None of this is synchronised, uploaded or backed up anywhere by the app. Deleting the application-data folder deletes all of it.

What it reads without copying

Several features work by reading files that already exist on your machine. They are read in place; nothing is duplicated into the app's own storage.

Claude Code transcripts

Token and context usage, the session inspector and session search all read the JSONL transcripts Claude Code writes under ~/.claude/projects/ — or under the config directory of whichever profile a session runs as. The app tails those files and keeps totals in memory. It does not copy them, move them, edit them or delete them.

Your MCP configuration

The MCP inspector reads the servers you already configured, at user, project and local scope, rather than keeping a second list of its own. Connecting to a server spawns it as a local process; only stdio servers are dialled from here.

Agent settings files, when you install hooks

Installing hooks writes into Claude, Codex or Gemini's own settings file. Each entry is tagged so only entries this app created are ever removed, the write is atomic, the file's permissions are preserved rather than widened, and a backup is taken before the first edit. Anything the app cannot parse as strict JSON is left alone.

Your project folders

The file tree, viewer, search and git panel read the folders you open. Search is restricted to project roots you have added, files over 2 MB are refused rather than loaded, symlinks that leave the project are refused, and .deckignore is honoured by the file tree.

What leaves your machine

The app sends nothing about you. It fetches its own release feed, it dials a relay so a paired phone can reach this machine, and three things running inside or beside it reach the network on their own account.

The relay a paired phone reaches you through

The desktop dials the Terminal Deck rendezvous relay at relay.terminaldeck.dev at launch and holds the link open, so a phone you have already paired has something to attach to rather than finding a machine that was restarted and never came back. The phone dials out too and the relay staples the two sockets together. Nothing is forwarded, nothing listens for an inbound connection, and there is no other network for you to set up. The switch is in the Remote panel in the sidebar, and switching it off is remembered.

An open link on its own moves nothing. The relay learns that a host is online; a device has to have been paired here and approved here before one byte passes between it and this machine.

The relay is treated as hostile, because it is a machine on the public internet with every byte passing through it. The two ends run a Noise IK handshake and each payload is sealed under keys derived from material the relay never sees. It learns that a host is online, that some device connected, and how many bytes went each way and when; it cannot read a command, cannot inject a keystroke, and cannot sit in the middle of the handshake without failing to decrypt on the first frame. A file or photo sent from a phone lands in a folder named after the app inside your Downloads, where you can see it.

It holds no account and no database. There is no login, because a login would mean a user table, which would mean the relay held something worth stealing. A desktop claims its name by proving it knows a secret the relay only ever hashes, and the mapping from that name to an open socket exists in memory for exactly as long as the socket does. Nothing about it survives a restart of the relay — every desktop simply reconnects.

To be precise about what we are not claiming: the relay program keeps no per-connection log, but it sits behind an ordinary HTTPS reverse proxy on a rented server, and we do not represent that no infrastructure anywhere records that a connection happened. The guarantee is about content, and it is structural: the keys are not there, so the stream cannot be read no matter who is looking.

The agent CLIs

A session is the real claude, codex or gemini binary running as a subprocess. When it contacts its provider, it is doing exactly what it would do if you had typed the command in your own terminal. Terminal Deck is not in the path of those requests: there is no proxy, no wrapper and no interception. Your prompts, your code and your files are handled under that provider's policy, not this one.

Your own git and gh

The git and GitHub panels shell out to the tools you installed and signed in yourself. The app holds no GitHub token and never asks for one; if gh is not authenticated, the panel says so and shows the command that fixes it. Nothing about your repositories is stored by the app between runs.

Pages you open in the browser tab

The embedded browser is a browser. Whatever you point it at loads normally and makes whatever requests that page makes. Navigation is restricted to http and https, downloads are blocked, and every permission request — camera, microphone, location, notifications, clipboard — is refused without asking you, because there is no dialog here to ask with.

One thing worth knowing before you type: text in the address bar that is not a URL becomes a web search, sent to DuckDuckGo. A bare hostname or a host:port is treated as an address and stays local.

The one listener. When agent hooks are installed, the app opens a small HTTP server so those hooks have somewhere to report. It binds to 127.0.0.1 on a port the operating system picks, requires a token generated fresh on every launch and never written to disk by the app, and refuses any request whose Host header is not a loopback address. Nothing outside your machine can reach it. The security page describes it in full, including what that token is and is not worth.

The embedded browser's data

The browser tab has its own cookie jar, kept apart from everything else the app stores. It persists between launches on purpose — a dev server behind a login should not need signing into again every morning. Turn off "keep cookies and logins" in Settings → Browser and the partition's cookies, storage and cache are cleared when you quit.

A tab can also be marked isolated. An isolated tab gets a partition of its own that exists only in memory: nothing is written to disk for it, it shares no cookies with the other tabs, and its data is gone when the tab closes or the app exits. That is what makes signing into the same dev app as a second user possible.

Cookie import is the one place this app reads another program's secrets. If you ask it to, it can copy cookies from an installed Chromium browser into its own partition so you do not have to sign in twice. It happens only when you start it, macOS prompts for keychain access naming the app, and a denied or unanswered prompt is reported as exactly that rather than as an empty profile. Cookie values never appear in a log, an error message or anything sent to the interface — the record kept so you can later remove them holds only the name, domain, path and secure flag. Chrome's own profile is opened read-only, through a temporary copy, and is never written to.

Diagnostics you choose to share

The app can produce a support bundle: version numbers, which agent CLIs it detected, where it keeps its files, which parts of the app wired themselves up, and the tail of the local log. It is generated only when you ask for it, copied to your clipboard, and sent nowhere. What you do with it afterwards is up to you.

Because a bundle exists to be pasted somewhere public, everything in it is passed through redaction first, and it reports how many substitutions were made. IPC call arguments are never recorded at all — the timings are useful, and the arguments are where your prompts and file contents would be. Environment variables are listed by name; the only values included are a short allowlist that carries no secrets. Redaction is careful but it is still software: read a bundle before you post it.

This website

terminaldeck.dev runs no analytics and makes no request to any other host — the two typefaces are served from this domain, and there is no embedded video, no comment widget, no tag manager and no font CDN. There is nothing here to track you with, which is why you were not asked to consent to anything.

Cookies. Reading this site sets none. Signing in to the store sets two, and only those two. td_session is your session: HttpOnly so no script on the page can read it, Secure, SameSite=Lax, and its contents sealed with AES-256-GCM so a copy taken off the wire is unreadable without the server’s secret. td_in beside it is a plain flag with one job — telling the page which header to draw before the first paint — and it carries no identity and grants nothing. Signing out clears both, and neither is used for advertising or measurement.

The site is hosted on Vercel, and the store is a database and a set of small functions run for it. Those see the ordinary request information any web server sees. That is between you and them; it is not collected, joined to anything, or used to build a picture of you.

The rest

Children

Terminal Deck is a developer tool for running coding agents and is not directed at children. It collects no personal information from anyone, so there is nothing collected from a child either. The agent CLIs it runs have their own age requirements; those apply as they normally would.

Changes to this policy

If the app ever starts collecting something, this page changes first and the change is visible in the repository's history before the release that makes it true. The date at the top is the last edit. There is no mailing list to notify you, so a version that added any kind of data collection would say so in its release notes as well.

Contact

Questions about this page, or a claim on it you think is wrong, belong in the repository: the issue tracker. The source is public, so every statement here can be checked against the code rather than taken on trust — if a claim does not match the code, the claim is the bug. Suspected vulnerabilities should go through the security page instead of a public issue.