Reference
Troubleshooting
Find your symptom, get the cause and the command. If you only read one thing on this page, read the next paragraph.
Start with the health checks. Open Settings, then Machines & accounts and click the machine's row. Its page runs the checks under Health, and Run checks again repeats them. It reports one row per check with the fix attached, and it never claims something is fine when it could not read it. Most of what follows is that report, explained.
Signing up
The confirmation email never arrived
Check your spam or promotions folder first. Then open Settings, then Account and choose Resend email above the account details; the window names the address the link went to. If that address is wrong, choose Change address there and the link goes to the new one. With a card on your plan you can connect a machine while you wait, so the email does not hold up setup.
The confirmation link says it expired
A link works for 7 days. If it is older than that, opening it sends a new one to the same inbox and the login page says so; open the newest email. If the login page instead asks you to send one yourself, log in and use Resend email in Settings, then Account. Work mail scanners often open links before you do: if your address is already confirmed, the link says Your email is confirmed rather than calling it expired.
GitHub sign-in sends me back to the login page with an error
The login page says which of three things happened. Cancelled means Cancel was pressed on GitHub's screen; choose Continue with GitHub again. Took too long or lost its cookie usually means the sign-in started in an app's built-in browser or sat open for more than 10 minutes; open termdeck.io in your regular browser and try again. Did not finish is on GitHub's side or ours; wait a moment and retry, or sign up with an email and a password instead.
Log in says invalid email or password, but I signed up with GitHub
An account made with GitHub has no password until you add one. Choose Continue with GitHub, then Set a password under Settings, Security & login. Or choose Forgot? and follow the emailed link to set one. If Settings asks you to sign in again first, that is because setting a first password needs a sign-in from the last 15 minutes: choose Sign in again, then come back to the page.
Sign up says too many sign-ups from this network
A network can create a handful of accounts an hour, and a shared office or mobile connection shares that allowance. Typos and too-short passwords do not count against it. Wait for the countdown on the button, or choose Continue with GitHub, which is not limited this way.
I left myself signed in somewhere
Open Settings, Security & login, Active sessions from any browser you are signed in on. Find the one you left by its browser, system, location and last active time, and choose Log out on it. If you cannot tell which it is, choose Log out of all other sessions; only the browser you are using stays signed in. Either way its push notifications stop too. If you think someone else has used it, change your password as well.
Signed out unexpectedly after a password change
Changing or setting a password logs out every other browser signed in to your account, on purpose: it is what you would want after a password leaked. Sign in again on each device with the new password, and turn push notifications back on there under Settings, then Notifications. If nobody on your account changed the password, reset it with Forgot? on the login page, then check Active sessions for browsers you do not recognise. Your machines stay connected through all of this; they do not use your password.
Installing
Checkout says Vortiq LLC, not Termdeck
Checkout is run by Airwallex, our payment provider, and its page is headed by the legal merchant, Vortiq LLC, the company behind Termdeck. It is the right page. The payment page can take a few seconds to load after you press a plan's button; the trial screen says Opening secure checkout… until it does.
I signed up and cannot connect a machine
A new account is on Free, which connects one machine once your email address is confirmed: open the link in the confirmation email, or choose Resend email in the window that asks. Free holds one machine, so a second one is refused until you start a Starter or Pro trial from Settings, then Billing. If you had a paid plan and it lapsed, your first machine keeps working and subscribing again from the same page brings the rest back.
Sign up says to tick the box above
Sometimes the human check needs a click. A Verify you are human box appears above the button, and the button reads Tick the box above to continue until you tick it. Once you do, the form carries on by itself; there is no need to press the button again. If the box never appears, a blocker or a strict network may be stopping challenges.cloudflare.com.
Sign up says the email address is not accepted
Sign up refuses throwaway inboxes from temporary mail services, and addresses at a domain that cannot receive mail. Use an address you keep, such as your work or personal mailbox, or sign up with GitHub instead. Private relay addresses from services like Proton, iCloud or Firefox Relay are fine. If an address you use every day is refused, email [email protected] from it.
Log in says Too many attempts
Several tries in a short time from one network or for one address pause the form for a while. The button counts down and comes back on its own when the wait is over, so there is nothing to reload. If you have forgotten the password, Forgot? on the log in page emails a reset link, and Continue with GitHub works throughout if your account uses it.
Add machine says to confirm your email first
Without a card on your plan (for example, a plan from a redeemed code), connecting a machine needs a confirmed address, so the wizard stops until the link we emailed you has been opened. The window that stops you names the address the link went to and has Resend email on it. Nothing in the inbox after a minute or two, spam folder included, usually means the address is not the one you think it is.
Choose Change address in that same window, type the right one, and we send a new link there. If you closed the window, the pencil on the Email row of Settings, then Account opens it again. Any link already sent to the old address stops working the moment you change it.
An address that is already confirmed cannot be changed this way, because a confirmed address is what password resets go to. Email us to move one.
The install command says Node.js is required
Node 18 or newer is not on the path for the shell you ran the command in. Install it from nodejs.org and check with node --version.
If Node is installed through a version manager such as nvm, it may exist in your interactive shell and not in a background service. Install a system wide Node as well, or point the agent at the right one.
Set TERMDECK_AGENT_TOKEN first
The command was run without its token, usually because it was retyped rather than copied. Go back to the connect wizard and copy the whole line. If the wizard is gone, open the machine's page and choose Regenerate token under Manage.
The install stops partway with a 404 or a curl error
Usually a network or proxy problem between the machine and Termdeck. Check the machine can reach it at all:
curl -fsSL https://termdeck.io/VERSION
If that fails, the machine cannot reach termdeck.io and nothing else will work until it can. On a corporate network, allow outbound HTTPS to that host.
npm fails while installing ws and chokidar
Scroll up in the output for npm's own error, which is the real one. Common causes are a proxy that npm is not configured for, a registry that is unreachable, and a permissions problem in the npm cache.
After fixing it, run the repair command rather than the installer, so a half written install is cleared first:
curl -fsSL https://termdeck.io/heal.sh | sh
Windows: the watchdog task was not registered
Task Scheduler denied access, so the agent is running for this session only and will not come back after a restart. Open PowerShell as administrator and run the install command again.
The machine's row will keep showing a stops at restart badge until this is fixed.
macOS: the installer says macOS did not start it as a background service
The agent is running for now, but it will not come back after a restart or a logout. Open System Settings, General, Login Items and Extensions, turn on io.termdeck.agent under Allow in the Background, then run the install command again.
The machine's row will keep showing a stops at restart badge until this is fixed.
The machine is offline
A Mac comes online for a minute, then drops, about once an hour
The Mac is asleep. macOS wakes a sleeping Mac briefly about once an hour for its own housekeeping; the agent reconnects in that window and the Mac falls asleep again a minute later. Wake the Mac and it stays connected.
While a chat is running, the agent keeps the Mac from going to sleep on its own, and lets it sleep again once the chat is done. Closing the lid still sleeps it. To keep a Mac working with the lid closed, run it on power with an external display connected.
A Mac went offline right after an update, or says it needs a repair
Agents older than 0.1.956 stopped on a Mac when they updated and did not start again until the next login. The update itself was installed, so this happens once. Log out and back in, restart the Mac, or run the repair command on it to bring it back now:
curl -fsSL https://termdeck.io/heal.sh | sh
From 0.1.956 on, the agent restarts itself after every update. See Updating.
It says Connected but nothing on it works
Look for a two agents badge on the machine's row. Two agent processes connected with one token knock each other off the connection, so the machine reports online while every request to it times out.
The usual cause is the install command pasted on a second computer. A token belongs to one machine; the second one needs its own from Add machine. Stop the agent you did not mean to run and the machine settles within a minute.
Without that badge, a timeout usually means the agent is busy with a long turn, or is restarting to apply an update. Both clear on their own. If neither is true, the machine's page has Run checks again under Health.
One thing that looks like a timeout is not one. If a single feature answers straight away with agent is out of date, the rest of the machine is fine: that machine is running an older agent than the feature needs. It updates itself, usually well within the hour. Updating covers doing it now.
The sidebar says a machine is catching up
The machine is connected and still reading its chat history, which happens right after it connects and again after a Termdeck update. Its chats fill in on their own, usually within seconds, and the chats on your other machines are already listed. If it stays on catching up for minutes, the machine is up but slow to answer, and a laptop on a weak connection is the usual reason: give it a moment, or check that machine's connection. See Machines and fleet.
It went offline and has not come back
Work through these in order.
- Is the machine awake? Sleep is by far the most common answer. A closed laptop is an offline machine.
- Does the machine's row carry a warning badge? Then it died at a logout or a restart and the badge names the fix.
- Is the service running?
# Linux
systemctl --user status termdeck-agent
# macOS
launchctl list | grep termdeck
Get-ScheduledTask -TaskName TermdeckAgent
- Can it reach Termdeck?
curl -fsSL https://termdeck.io/VERSION - Still nothing? Run the repair command. It reuses the token already on the machine.
It goes offline every time I log out
A systemd user service without lingering. Systemd shuts your user services down at logout unless lingering is enabled. Run this once on the machine:
sudo loginctl enable-linger $USER
The installer attempts this and can only fail when sudo needs a password it cannot prompt for, which is normal for curl | sh.
It goes offline every reboot
Nothing is registered to start it. Rerun the installer, on Windows from an elevated PowerShell. The stops at restart badge on the machine's row disappears once a proper service exists.
A project's chats are still listed but the folder is gone
Termdeck checks each added folder once per page load and marks the folder name on that project's rows when the machine says it is not there. The chats stay listed, because their transcripts are still on disk and still readable. What will not work is starting a new chat in that folder.
Either put the folder back where it was, or remove the project in Settings, then Projects (its ⋯ menu, then Remove) and add it at its new path with Add folder.
The machine shows online but nothing works
Online means the agent is connected, not that the machine can run a turn. The agent brings no coding agent with it. Check Coding agents on the machine's page: a machine with no CLI installed, with one installed but signed out, or with a saved login the provider has since refused, is connected and useless. The dashboard says which of the three it is, above the chat list, and the New chat page repeats it before it lets you type.
Two agents seem to be running on one machine
Re-run the install command on that machine. It stops the agent that is already running, retires any old launch agent left over from an earlier install on macOS, and starts one fresh agent. A second agent started on the same machine does not connect: the agent log shows a line saying it is standing by for the running one, and it takes over only if that one stops. If the two agents are on different computers sharing one token, see the two agents badge on the machines page.
An agent started from anywhere other than its install folder, such as a copy of the code you are working on, refuses to connect with this machine's token, and its log says Not connecting. Give that copy its own token from Add machine. Such a copy also never repairs launcher files, changes the scheduled task or installs updates in the folder it runs from.
Engines and models
A CLI shows Not installed, or its Install button fails
Open the machine's page in Settings, then Machines & accounts and press Install on the CLI's row under Coding agents. If the row has no Install button, the machine's agent is older than the feature; it updates itself, and the button appears once it has. If the install fails, the row says why. The usual reason is a machine without npm: install Node.js there (it includes npm) and press Try again.
On a Mac, a CLI installed with Homebrew's npm used to show as Not installed even though it worked in a terminal, because the agent starts with a short path. Current agents look in those folders. Press Recheck.
Grok shows Not installed, but grok runs in my terminal
The grok there is @vibe-kit/grok-cli, a different program with the same name, which earlier Termdeck instructions installed. Termdeck drives xAI's own CLI. Press Install on the Grok row to swap it, or run npm uninstall -g @vibe-kit/grok-cli and then npm install -g @xai-official/grok, and sign in with grok login. See xAI Grok.
Add account is off, or a sign in says Claude Code isn't installed
The machine could not find the Claude Code CLI, so there is nothing to sign in to. Press Install on its row under Coding agents on the machine's page in Machines & accounts, or install it on the machine yourself and press Recheck, then add the account. Older agents showed this as spawn claude ENOENT.
# macOS, Linux, WSL
curl -fsSL https://claude.ai/install.sh | bash
# Windows PowerShell
irm https://claude.ai/install.ps1 | iex
The model picker is empty, or says it failed to fetch models
This is the most reported symptom and it nearly always has one cause: the CLI is not signed in, so it cannot list models. The menu itself names the machine and prints its reason, and the Fix this in Machines & accounts button under it opens that machine's page with the sign ins for that engine already showing. The machine's Health checks name the same thing, with the CLI's own reason attached.
claude # starts the Claude Code login
codex login
grok login
If the login is fine and the catalog still fails, the reason string on the check row is the CLI's own and is the thing to act on.
A chat shows "Claude is signed out on this machine" or "Usage limit reached"
The model never answered: Claude Code got an error back instead and wrote it into the chat. Termdeck shows it as a notice rather than a reply, with Claude Code's own sentence and the next step. Signed out means the login on that machine expired: run claude there and sign in with /login, or switch to another saved account under Accounts on that machine's page in Settings, then Machines & accounts. A usage limit says when it resets; send again after that, or switch account. For a model that is not available, pick another one. Anything else is a failed request, and sending the message again retries it.
An engine is installed but Termdeck says it is not
Termdeck looks the binary up the way your shell does. A background service does not inherit your login shell's environment, so a CLI that only works after your shell profile has run will not be found.
Name it explicitly in ~/.termdeck/agent.env and restart the agent:
TERMDECK_CLAUDE_EXE=/full/path/to/claude
TERMDECK_CODEX_EXE=/full/path/to/codex
TERMDECK_GROK_EXE=/full/path/to/grok
Signing in from Termdeck hangs and never finishes
Check whether the machine has two copies of that CLI on the path, for example an npm global and a package manager install. When it does, the lookup that runs turns and the lookup that drives the sign in can land on different binaries, and the sign in never completes.
Remove the copy you do not want, or pin the right one with the executable variables above.
An engine shows Couldn’t verify
The machine did not answer the status question. This is not the same as signed out and Termdeck will not treat it as such. It usually clears on its own. If it persists, look at the agent log: View logs on the machine's page.
Turns
The composer is locked and says the session is in use
Another process is attached to that session, typically a terminal running the CLI on the same chat. Two writers on one transcript would fork it, so Termdeck goes read only instead.
Exit the CLI in that terminal, or start a new chat in the same folder. The composer unlocks by itself once the other process lets go.
A turn will not start
In order of likelihood:
- The machine is offline. The sidebar and the machine's row both say so.
- The chat says the machine's agent is out of date. Claude turns need an agent from a recent release. It updates itself as soon as nothing is running on the machine, usually within a minute; press Update agent on the machine's page to do it now, then send again.
- The engine is not signed in on that machine.
- The engine has a saved login the provider refused. The card reads Sign in expired. Run the engine once on the machine to refresh it.
- The session is attached to another process, so the composer is locked.
- A run is already in progress. On a paid plan the message is queued instead of refused.
- On Free, the month's 30 browser turns are used, or another session is already running. Turns you type in a terminal still work. Start a Starter or Pro trial, or subscribe again, from Settings, then Billing.
A turn seems stuck with nothing happening
Check for a waiting approval first, in the transcript or on the Approvals page. A blocked run looks exactly like a slow one until you find the card.
If the engine is retrying a failed provider call, the transcript says so with an attempt count rather than sitting silent. If neither applies and it has genuinely stopped moving, press Stop and send the prompt again.
A running command shows no output until it ends
On Grok that is expected: it does not pass on a command's output while it runs, so the row shows how long it has been running and the output arrives when the command returns. On Codex the output shows under the row as it prints. On Claude Code it does too, except when Claude runs several commands side by side or a sub-agent is working in the same turn; then the output arrives when the command returns. If a single command on Claude Code stays blank while it prints, update the agent on that machine (Install). See Sessions.
A tool call never happened and nothing was asked
Three candidates:
- A hard deny refused it. The transcript says which guard and why.
- A PreToolUse hook in your CLI settings blocked it before Termdeck saw it. The machine's Health checks list armed hooks.
- A settings file does not parse, so the engine is ignoring it entirely along with everything configured in it. The Health checks flag this as a failure, and it is the highest value row there.
An MCP tool failed because its request was cancelled
The server asked for input mid call, a form or a sign in link, and Termdeck cannot show that prompt yet, so it answered cancelled rather than leave the turn waiting. For a sign in, authenticate the server once from /mcp in a terminal on that machine. See When a server asks you something.
I turned an extension off and a running chat still uses it
The line under the Extensions tabs says where each change applies. Applies to new chats means a chat already running keeps what it started with: start a new chat, or resume this one after its turn ends. Every Codex change is like this. A Claude MCP server switched off is also pushed to running chats in that project, and the line says how many. See Turning things off and on.
Extensions says an MCP server failed but it works in my terminal
The check runs on the machine as the agent's user, with the agent's environment and in the project you picked. A server that reads a variable from your shell profile, or needs a login only your terminal session has, can fail there and work for you. Open the row to see the reason, then put the variable in the agent's environment (see Agent environment variables) and press Recheck.
The switches in Extensions are greyed out
Either the machine has TERMDECK_CONFIG_READONLY set, which the list says at the top, or the row is managed by a plugin or by your organisation, in which case its button names the owner. On Free a switch opens the upgrade panel instead. See When the switches are locked.
I closed the tab and lost the run
You did not. Closing a tab, losing a connection, sleeping a laptop, and a Termdeck release all leave the process running on your machine. The agent keeps the run going and catches you up on what you missed when you come back.
A run with nobody attached is kept for a few minutes. Past that it is stopped, and everything it wrote is still on disk in the transcript.
The context bar says the chat is nearly full
Press Compact, or send /compact. The engine summarises the conversation so far and continues with the shorter version.
Compacting loses detail. If the chat has drifted a long way from what you want, a fresh chat in the same folder is usually better than compacting a long one.
Approvals
A chat in Full access says full access is turned off on this machine
That machine has TERMDECK_FULL_ACCESS=off in its agent settings, so it refuses Full access on every engine. Pick another mode from the composer and send again. To allow Full access there, remove the line from ~/.termdeck/agent.env and restart the agent. See Turning Full access off.
It keeps asking me the same thing
Turn it into a rule. Settings, then Approvals, Add rule beside Saved rules: name the tool, a glob that matches the command, and a maximum risk cap. Or pick a ready one from the Suggested card. It stops asking from the next turn.
Keep the glob tight. npm test is a rule; * is a permission mode with extra steps.
My rule does not fire
Three things to check, in order:
- The risk cap. A rule only fires when the computed risk is at or below its cap. A command that scores high under a low capped rule will still ask.
- The tool name. The rule must name the tool the engine actually used.
- The glob. It matches the command for shell tools and the path for file tools.
Termdeck refused something I wanted to run
A hard deny guard tripped. The message names which one. If your work genuinely needs it, for example a chat whose job is provisioning a machine, switch that guard off on the Always refuse card in Settings, then Approvals and switch it back on afterwards.
Guards cannot be switched off from anywhere else, and no auto allow rule can override one.
My rules stopped applying
Auto approve needs a paid plan. When a trial ends, saved rules are paused rather than deleted, and the settings page says paused instead of pretending they are still in force. They resume the moment you subscribe.
A lost browser connection shows Connection lost. Reconnecting…. It changes to Back online once the connection returns. No refresh is needed; the open chat catches up automatically.
Notifications
Nothing arrives on my iPhone
Safari only allows web push for a site added to the home screen. Add Termdeck from the share menu, open it from that icon, and enable push there. A subscription made in a Safari tab does not carry over.
My phone stays quiet while I am away from my desk
A Termdeck window you are using keeps push off on every device. Leaving it, or three minutes with no typing, clicking, or mouse movement in it, hands alerts back to your phone. See while you are using Termdeck.
They worked before and stopped
Browsers expire push subscriptions, especially after a long idle period or a data clear. Toggle push off and on in Settings, then Notifications to register a fresh one for that device.
No popup or sound for one kind of event
Popups and the sound are chosen per event. In Settings, then Notifications, open that event's menu under Notify me about and tick In-app or Sound. A menu that says Off sends nothing. The Play a sound switch in quick settings turns the sound on or off for every event at once. See what can notify you.
I cannot tick Push for an event
Push has to be on for this browser first: select Enable beside Push on this browser. If the button is greyed out and the line under it says blocked, notifications are blocked for the site in your browser's settings. Allow them there, then reload.
The tab title shows a count but nothing needs me
The count, the bell, and the Approvals page are all computed from one list, so they cannot disagree. What counts is a waiting permission, a waiting question or plan, and a turn that failed. Open the bell to see the entries.
The interface
My chats are not in the sidebar
Chats appear only for folders you have added. Add them in Settings, then Projects, from Available folders or with Add folder. If chats you started in a terminal are missing specifically, check the visibility switches in Settings, then Chats.
A chat running in a git worktree is folded into its base repository rather than appearing as a separate project. An old project entry saved for a worktree folder is replaced by its repository the next time Termdeck loads. That includes a Codex chat that makes a worktree in a folder beside the repository and moves its work there: it stays listed, and pinned, under the project you started it in.
On Starter you can add 2 projects. A chat started in a third folder runs, but stays out of the sidebar until you remove a project or move to Pro. Plans and limits has the limits.
If a folder you added is in Your projects but its chats are not in the sidebar, the row says why: the machine is offline, the machine is no longer on your account, or that machine has no chats in the folder any more. Remove it (the row's ⋯ menu, then Remove), or fix the machine, whichever the line asks for.
The dock says it could not load a file's diff
The request for that file's diff did not reach the machine, usually because the connection dropped for a moment. The file's contents still show underneath. Press Try again or open the file again. If it keeps failing, check that the machine is online (Machines).
Reviewing changes has more on the dock.
An upgrade prompt opened when I added something
Starter has limits Pro does not: 1 machine, 2 projects, 2 saved logins per engine, the last 7 days of usage, and 4 terminals in a window. Adding past one of them opens the prompt instead. Nothing you already have is removed. Remove something to make room, or move to Pro from Settings, then Billing, with Change plan.
A Usage link opens a different date range
A link with an invalid calendar date, such as February 31, opens the default range instead. Choose a preset or enter the dates again, then copy the corrected URL. See Usage date ranges.
A chat vanished
Check Settings, then Archived chats, and use Unarchive to bring a chat back. Auto archive moves anything untouched for the period you set, and nothing is ever deleted. Termdeck does not delete transcripts under any circumstances: they belong to the CLI and live on your disk.
A Terminals pane says "Could not load"
The pane asked its machine for the chat and got no answer in time, usually because the machine's agent was reconnecting. Click the message to load it again. If it keeps failing, check the machine is online in Settings, then Machines & accounts. See Terminals.
The dock's Files tab shows no file tree
The Explorer section is closed. Its close button sits beside its maximise button in the Explorer's own title bar, and closing it leaves the file reader on its own, saying "Select a file to view it" over an empty panel. The choice is remembered per browser, so reopening the dock, switching chat or reloading the page will not undo it.
Bring the tree back with the folder button at the left of the reader's title bar, or by pressing the Files tab.
The dock shows an error in a chat I just started or branched
A brand new or just branched chat can take a few seconds to appear on the machine, and the dock may say "Session not found" or "Request failed" in that time. Wait: it asks again on its own and fills in the tree and the changes once the chat is there. If the error is still showing after about half a minute, the machine really cannot read that folder. Check that the machine is online and the folder still exists.
The page looks wrong after an update
A stale cached asset. Do a hard reload. If that does not settle it, Settings, then Data controls clears this browser's local Termdeck data. Nothing on your machines is affected: layout and preferences are per browser, and everything that matters is on disk.
Add machine is disabled
You are at your plan's device limit: Free holds one machine. Remove a machine you no longer use, or move to a plan with more room. The dashboard also lists machines currently being refused for being over the cap, since that refusal otherwise happens in a terminal nobody is watching.
When none of this helps
If you have an exact error string, Fixes keeps one page per symptom: what the line means, which process printed it, and the command that confirms the diagnosis before you change anything.
Email [email protected] with as much of this as you have. It is usually enough to answer without a second round trip.
- The machine name, its platform, and its agent version, all on the machine's page.
- The Health checks on that machine's page.
- The last part of the agent log, readable from View logs on the machine's page.
- Which engine and model, and whether it also fails in a terminal.
- What you expected, and what happened instead.
The last one matters more than it sounds. "The turn did not start" and "the turn started and produced nothing" are different problems with different answers.