Terminal Deck 0.15.0

Privacy

Terminal Deck keeps your chats, sessions and tasks on your Mac. The iPhone and Android apps connect to the Mac you pair. There are no analytics or automatic crash reports. If you choose to report an AI reply, the phone app sends us your selected reason and, if you include it, that reply’s text.

This page explains what is stored on your devices, what reaches the network through paired connections and the in-app browser, and what we receive when you send an optional report. Reports are not linked to an account or device identifier.

Last updated 29 October 2026 · applies to the Mac app, and to the iPhone and Android apps from version 0.20.2

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.

The iPhone and Android apps

Both phone apps, from version 0.20.2, are chat-first: Hoot, your agents’ chats, terminal sessions, tasks, projects and a browser, all for the Mac you paired. They talk to your own Mac and to nobody else, with three exceptions that only happen when you start them: speaking instead of typing, opening a public web page, and reporting an AI reply. Each one is described here.

No account, no ads, no analytics, no crash reporting

There is nothing to sign up for. Neither app has an advertising identifier, an analytics or crash-reporting library, or tracking of any kind, and neither sends us anything on its own. The only thing either app ever sends us is a report you choose to send, described in the next section.

One connection, to your own Mac, end to end encrypted

You pair once, with the six-digit code your Mac shows. From then on the app connects only to that Mac, through our relay at relay.terminaldeck.dev. Everything you see and send in the app travels encrypted end to end between your phone and your Mac: Hoot and agent chats, terminal sessions, tasks, projects, approvals, pictures and your Mac’s own websites. The relay passes it along and cannot read it; the relay section below says exactly what it does learn.

The pairing keys stay on the phone. On iPhone they are in the Keychain, for this device only, so they are not synced to iCloud or moved to a new phone. On Android they are encrypted with a key held by the Android Keystore.

Hoot and your agents run on your Mac

What you type to Hoot or to an agent, and your answers to their questions, go to your Mac. The reply is produced there, by the AI account you signed in to on that Mac (Claude, Codex or Gemini). That provider’s own privacy terms apply to what you send it, exactly as they do when you use it on the Mac. We never see your conversations.

Speaking instead of typing

The microphone is used only while you dictate: tap the microphone to start and tap it again to stop. The app does not keep the recording. Your words are turned into text by the phone’s own speech recogniser, not by Terminal Deck, and the text goes into the message box. Nothing goes to your Mac until you press Send, and neither the sound nor the text is sent to us. Whether the sound leaves the phone depends on the phone:

iPhone
Apple’s speech recognition. Apple may send the recording to its servers to turn it into text, and iOS says so when it asks for permission. Apple’s privacy policy applies.
Android
The phone’s own speech recognition service, which on most phones is Google’s. Depending on the phone and its settings, that service turns speech into text on the phone or sends the recording to its provider to do it, under that provider’s privacy terms.

Alerts

If you switch alerts on, the phone shows a notification when a session needs an answer from you or has finished. The app asks for permission from its Alerts sheet, when you open it, not at launch. Each alert is made on the phone itself, from what the app hears from your Mac while the app is running. There is no push service behind it, so nothing about your sessions passes through Apple’s or Google’s notification servers, and we send no notifications.

The browser

The Browser shows the browser windows open on your Mac and lets you open pages on the phone. Every page opens inside the app’s own browser view, never in Safari or Chrome. Where a page comes from depends on what it is:

Your Mac’s websites
A site running on your Mac, such as a development server on one of its ports, is served by your Mac through the same encrypted connection; the phone does not reach it any other way. The list of your Mac’s browser windows arrives the same way.
Public web pages
A web address on the internet, or words that are not an address (searched with Google), loads straight from the internet into the app’s browser view, as in any browser, and that site’s own privacy terms apply (Google’s, for a search). Nothing about what you browse is sent to us. It reaches your Mac only when you send something from the page to an agent yourself.

What stays on the phone

The app keeps only small things it needs to work: the pairing keys, your settings, a few reminders such as the session you opened last and an unsent draft, a cache of the pictures your Mac shows, and, for the pages you open in the app’s browser, their cookies and your browsing history. On iPhone, a login you choose to save in the app’s browser is kept in the Keychain, for this device only. Your chats, sessions and tasks live on your Mac, and the phone shows them while it is connected.

The optional app lock uses the phone’s own screen lock, Face ID or fingerprint: the phone checks it, and the app learns only whether it passed. The Android app is left out of Android’s cloud backup. Removing the app removes everything it stored. To also end the pairing on the Mac’s side, remove the phone there in Terminal Deck.

Reporting an AI reply

The one thing either phone app sends to us, and only when you choose to.

Any AI reply, from Hoot or from an agent chat, can be reported with “Report this reply”. When you send a report, the app sends us, over HTTPS: which app it came from (iPhone or Android), the app’s version, the reason you picked and, only if “Include the reply’s text” is ticked, the text of that one reply. The box starts ticked; untick it to send the reason alone.

Nothing in a report identifies you, your phone or your Mac: there is no account, no device identifier, no location and nothing else from the conversation.

We use reports to look into offensive or harmful replies. They are kept on our own server, shared with no one, and deleted within 90 days. Our server sees your IP address while it receives a report, as any website does; our code uses it only to stop floods of reports and does not store it. To have a report deleted sooner, write to asadiqbalonline@gmail.com.

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.