Roadmap
Nine phases. Eight are essentially finished, and the ninth is mostly what stands between a signed-but-unnotarised disk image and one macOS will open without an argument. Items have moved back out of Done before now, after an audit found them unreachable from the running app; one has moved out of Done in the other direction, deleted rather than shipped.
Done
1 · Foundation
- Electron, React and TypeScript, built with electron-vite
- Process ownership, with scrollback replayed across tab switches
- Provider layer — Claude, Codex and Gemini detection, login-shell
PATH - Sidebar, tab bar, status dots, empty state
- Design tokens in dark and light, self-hosted open-licensed fonts
- Atomic JSON store; projects and window bounds persist
- Content-security policy set from the main process
2 · Session intelligence
- Status detection in the main process, so unrendered tabs stay accurate
- Provider picker — per session, per project, global default
- Session resume
- Preferences, and live re-theming that recolours terminals without a restart
- Desktop notifications and sounds — a banner has now been watched appearing, from the installed build, and macOS's own notification store recorded the delivery rather than the screenshot being the only evidence. The earlier failure was never a signing problem, which is what it was believed to be: macOS had put up its authorisation prompt as a banner, with Allow hidden behind an Options disclosure nobody had opened, so every notification was being dropped silently. Clicking Allow was the whole fix.
- Session titles derived from the task, and unread indicators — both driven in the running app on 14 Aug 2026 rather than read off the source. A shell session renamed its own tab from
Session 1to the task echoed into its terminal, and the session left running in the background picked up an unread dot the moment it produced output while another tab was in front.App.tsximportsAutoTitlerandUnreadTracker; when this line first appeared,renderer/unread.tshad no importers at all.
3 · Usage, context and telemetry
- Transcript watcher
- Token accounting per session, project and day, split by fresh input, output, cache read and cache write
- Prices removed, deliberately. The app showed an API cost and it was real arithmetic, but almost everyone running it is on a subscription and a flat monthly fee does not become a per-session dollar figure — and no plan publishes a token allowance to compute the other number from. One was misleading, the other unknowable, so both are gone and the app says nothing about money.
- Token and context-window monitoring with a bloat warning
- Session inspector — timeline, token breakdown by model, cache hit rate, tool-usage statistics
- Deep search across past transcripts, from the command palette
- Smart alerts for missing tools, context bloat and session health
4 · Project workspace
- Git status watcher and git panel
- File tree and viewer with syntax highlighting
- Quick open and command palette
- GitHub integration through
gh - AI readiness score with one-click fixes
.deckignorewith gitignore semantics, read by the file tree — quick open and the watchers still do not consult it
5 · Dashboard
- Customisable project overview on a drag-and-drop widget grid
- Widgets for readiness, sessions, usage, git and GitHub
- Kanban board removed, code and all. It was built — three columns, search, tag filtering, and cards that could start or resume a session — and then deleted on 15 Aug 2026, along with its state module, its main-process store, its overview widget, its menu item and its shortcut. Not wanted: a task board is a thing you keep up to date by hand, and nothing else in this app asks that of you. It went in one piece because a half-removed feature leaves rows that open nothing, which is worse than the feature was.
6 · Many sessions at once
- Swarm mode
- Accounts with isolated logins, per agent — Claude Code through
CLAUDE_CONFIG_DIRand Codex CLI throughCODEX_HOME, both measured against the real CLI. Gemini CLI is listed and refused, because its token sits in one keychain slot no configuration directory moves - Full keymap and a shortcut reference sheet
7 · Integrations
- Hooks installed into each provider's settings, namespaced so they never collide with another tool's
- MCP client and inspector
- Embedded browser with element inspect
- An agent that can drive that browser — through the browser's own debugging protocol with a real actionability loop, not through screenshots. One page, and the two of you take turns on it: any real interaction of yours takes it back at once, and while you hold it every command is refused, reads included, because a screenshot taken while you type a password is the leak
- Draw on a page and send it to an agent, alongside inspect and record
- Chrome configuration import
7b · The copilot
- An assistant for the deck itself, built as a real session rather than a hidden service — its folder, instructions, memory and transcript are all files you can open
- Sandboxed like any session started from another device, including from us, and proved against
sandbox-execrather than asserted. It starts signed out, because the keychain is closed to it, and it says so - Routines — saved instructions triggered by a session finishing or failing, git state changing or a file changing. A schedule is one trigger among several, not the foundation
- Agents you add yourself: name a command and it runs, with the caveat on the row that an agent nobody here has characterised gets a terminal and not a model picker
8 · Away from the desk
- Pairing by six-digit code — sixty seconds, single use, dead after five wrong guesses, and it only ever produces a pending device a human approves on the machine itself
- QR codes and pairing links deleted. The QR did not work, and a link is a live bearer secret that has to travel through a messaging app to be useful. Both are gone from every client, along with the camera permissions they needed.
- Our own rendezvous relay at
relay.terminaldeck.dev— both ends dial out, nothing is port-forwarded, and no VPN or other network has to be set up - Noise IK sealed channel, written four times in four languages and byte-identical across all of them, so the relay carries ciphertext it cannot read
- Web client at
app.terminaldeck.dev— session list and a real terminal in any browser, installable as a PWA, light and dark - Native iPhone client on TestFlight — VT100 emulator, key bar and grid, gesture scrolling and selection, automatic reconnect
- Android client — a signed APK published with every release and offered on the download page
- The headless host, installed rather than built. One line puts it on a machine with no screen: it fetches its own Node when there is none, writes nothing outside your home directory and never runs as root. It has been left running in a WSL distribution under a user service, holding real agent sessions a phone drives.
- One phone can hold several machines at once, each with its own sealed channel
- Localhost tunnel — reach a dev server on the desktop from the phone, over a raw TCP pipe, on macOS and Windows both
- Per-device folder grants, deciding where each paired device may start a session
- Split panes — the split view renders now, and is reachable from a toolbar button as well as
⌘D, with⌘⌥←/⌘⌥→to move between panes and a draggable divider. This line spent a long time under “Not done” for the right reason: the layout code and the chords existed and nothing drew them. - Updating in place — on macOS and on Windows both. The app reads the feed and, on your say-so, downloads the release, verifies it and swaps the app, through to the relaunch. The Windows half was exercised on a real PC: an installed build found the next release, pulled it through electron-updater's differential downloader and relaunched itself on the new version. The portable executable remains the one case that cannot be replaced in place, and it says so instead of offering an update it cannot install.
Not done
9 · Ship
- Notarisation, and Windows code signing. The packaging is done and macOS signing is done — CI signs the
.dmgwith an Apple Developer ID certificate on every tag. What is left is notarisation, which Apple refuses for this account with statusCode 7000, “Team is not yet configured for notarization”, so Gatekeeper still needs the Open Anyway step. There is no Windows certificate either, so SmartScreen still needs the More info override. - The iPhone client on the App Store. It is on TestFlight, internal testing only, and no submission has been made. The blocker is honest and specific: a reviewer owns no machine running Terminal Deck, so a pairing screen is a dead end for them.
- Voice dictation. The app cannot transcribe — no on-device model in this Electron, and the browser speech API starts and then emits nothing. The microphone is off by default and hands over to the operating system's own dictation when switched on.
- A Mac talking to a Windows PC. Machine-to-machine pairing has been run end to end against the real relay, the real trust store and the real pairing desk — with both ends in one macOS process on loopback, which is where every seam that has broken before lives. Across the internet, between two operating systems, it is the same code and it has not been run.
- The Android client on Google Play. The signed APK ships with every release and the download page offers it, so there is a build to install. There is no Play listing, which is what would let it update itself.
- Translations. The app is English only.
A Linux window is not on this list because it is not scheduled — electron-builder has no desktop target configured for it. Linux is not absent from the product: the headless host above is what makes a Linux server or a WSL distribution a machine your phone and your desktop can open a session on. Windows does have a desktop target, and every release ships an x64 installer and a portable executable, both built and tested on Windows in CI.
Known follow-ups
Two things are known and not fixed. Both are debts the repository tracks rather than features:
- The chunked transcript reader is written three times over — once each for usage, insights and search. All three are tested and working, so lifting them into one helper carries regression risk for no user-facing gain, and it waits.
- Escape-to-close on dialogs is correct in code but has never been confirmed by a real keypress, because synthetic key events were not delivered during testing.
Open questions
- How closely the published host should track the desktop. It is on npm and one line installs it, but it is released on its own schedule, so the version the install script gives you can sit behind this release.
terminaldeck --versionsays which one you have.