Terminal over the Mesh

Open a real terminal on one of your machines from another, with no remote-desktop session.

Embed
Preview of the card
<a href="https://forumulate.com/p/gaiadesk/docs/terminal-over-the-mesh"><img src="https://forumulate.com/api/public/orgs/gaiadesk/spaces/docs/pages/1390e2d0-ca5e-4f7e-bcba-b5aac895d217/social-card.svg?v=3e7ae33eec8b" alt="Terminal over the Mesh" width="600" height="315"></a>

Open an interactive terminal on another of your machines, the way ssh does, without a remote-desktop session: from the GaiaDesk app (Terminal next to a device) or from the command line (gaiadesk-cli shell). Keystrokes, Ctrl-C, arrow keys and window resizing all go to the remote shell, and full-screen programs such as vim, htop and less work.

The target's screen is never shared or even read: a terminal session carries the shell and nothing else. The person at the target is still told that someone opened a terminal on it.

It works wherever you are. GaiaDesk tries the lightest route first:

  1. GaiaDesk Mesh, if both machines are on it;

  2. your local network, if the target is paired with this device;

  3. the GaiaDesk server, as the account you're signed in with — the route for a machine on another network, or signed into a different account.

Mesh and a shared network are optional; being signed in is enough. The target can be a Mac, a Windows PC or a Linux machine.

Before you start

  • GaiaDesk is running on the target machine.

  • You have its 9-digit address (the desk ID) and its unattended password (see Unattended access). The 6-digit one-time code works too, but then someone at the target has to click Allow (the prompt says it's a terminal).

  • The target runs a GaiaDesk recent enough for terminal-only sessions. An older one is refused with a message saying so, rather than sharing its screen: update it, or connect normally and open the terminal from the session toolbar.

The shell is authenticated like any other connection: the same password check, allow-list and approval prompt, whichever route it takes. Nobody can open a shell on your machine by being on the same network or mesh.

From the app

In Devices, press Terminal next to a device (with a saved password it opens straight away). Or on Home, type the address and password and press Terminal beside Connect. The terminal opens as a tab of the session window. The line above it says how it's connected (LAN, Mesh or the GaiaDesk server) and the machine's name. Copy with Ctrl+Shift+C and paste with Ctrl+Shift+V (⌘C / ⌘V on a Mac). Closing the tab ends the shell.

From the command line

gaiadesk-cli shell does the same in your own terminal. When you leave, your terminal is put back as it was, even if the connection drops. Its first line says which route it took.

The connection stays open for 10 minutes after you leave, so the next shell or exec to the same machine starts at once (--persist 0 turns that off; gaiadesk-cli disconnect --desk-id <id> closes it now). See connection reuse.

Put the command on your PATH (once)

macOS: open GaiaDesk → Settings → Terminal over the Mesh → Add the gaiadesk command. macOS asks for your password once. It adds gaiadesk and gaiadesk-cli to /usr/local/bin, pointing into the app, so app updates update the command too.

Windows: the installer adds GaiaDesk's folder to your PATH. Open a new terminal window (PowerShell, Command Prompt or Windows Terminal) after installing or updating.

Linux (.deb / .rpm): nothing to do. The package installs /usr/bin/gaiadesk-cli.

Linux (AppImage): an AppImage's files only exist while it runs, so it can't put a command on your PATH. Install the .deb or .rpm instead, or unpack the AppImage once and run the tool from the unpacked folder:

./GaiaDesk_*.AppImage --appimage-extract >/dev/null
LD_LIBRARY_PATH="$PWD/squashfs-root/usr/lib" ./squashfs-root/usr/bin/gaiadesk-cli shell --desk-id 123456789

Open a terminal

From a Mac:

gaiadesk shell --desk-id 123456789

From Windows (PowerShell, Command Prompt or Windows Terminal):

gaiadesk-cli shell --desk-id 123456789

From Linux:

gaiadesk-cli shell --desk-id 123456789

You're asked for the target's password, which isn't echoed. After that you're at a prompt on the other machine. To leave, type exit. On a Mac or Linux target, Ctrl-D also works.

What you land in depends on the target:

Target

Shell

macOS

your login shell (usually zsh), in your home folder

Linux

your login shell ($SHELL), in your home folder

Windows

Command Prompt (cmd.exe). Type powershell to switch

The password without typing it

For scripts, set GAIADESK_CODE in the environment instead of typing the password:

# macOS / Linux
GAIADESK_CODE='your-password' gaiadesk-cli shell --desk-id 123456789
# Windows PowerShell
$env:GAIADESK_CODE = 'your-password'
gaiadesk-cli shell --desk-id 123456789

Every command (shell, exec, cp, …) refuses --code <password> on the command line, because every user on your machine can read a command line (with ps or Task Manager). If you accept that, add --allow-code-in-argv. For a program, a scoped agent token is better than the password: see agent tokens.

One command, no session

To run a single command and get its exit code back, use exec:

gaiadesk-cli exec --desk-id 123456789 -- df -h

exec works like ssh host cmd: no terminal is involved, so the command's stdout and stderr come back separately and unaltered, its stdin is closed (-i forwards yours), and it is stopped after --timeout (30 minutes by default). --json, --shell cmd|pwsh|sh|none and everything else for scripts and agents is in The CLI for scripts and AI agents.

Exit codes

Code

Meaning

0–255

the remote shell's (or command's) own exit code (253–255 can also mean the rows below)

124

--timeout ran out and the command was stopped (exec, non-interactive shell)

130

interrupted with Ctrl-C; the command was stopped

253

shell only: a remote error — the connection was lost mid-session, or the desk ended the terminal

254

the target refused (wrong password, allow-list, no control, a token without exec, …)

255

could not connect: desk offline or not found, unreachable, timed out (exec: a lost connection too)

shell always prints the reason on stderr, and never exits 0 unless the remote shell did. Not on a terminal — shell -- <command>, or a script piped in — it runs like exec (plain pipes, the remote exit code, --json); see The CLI for scripts and AI agents.

Troubleshooting

  • "could not reach desk …": no route reached the target. The message lists what each route said, one line per address tried, for example:

    • "isn't paired with this device": the target answered on your network but was never paired with this device (it may be signed into another account). GaiaDesk tries the server next, and that needs you signed in.

    • "no answer on that UDP port": GaiaDesk isn't running on the target, or a firewall (Windows Defender Firewall, for example) is blocking it.

    • "not signed in to GaiaDesk on this machine": the server route needs the account. Sign in to the GaiaDesk app on this machine, or set GAIADESK_TOKEN_FILE.

  • "desk … is offline (last seen …)": one of your account's or team's machines isn't connected. Wake it, or check GaiaDesk is running there.

  • "no desk … is online, and none by that id belongs to your account or team": check the ID.

  • "desk … refused the connection: …": the target said no. Check the password and the target's allow-list.

  • "… older GaiaDesk that can't open a terminal without sharing its screen": update GaiaDesk on the target.

  • "the desk closed the terminal" / "this session may not run commands": the session was admitted without control permission (view-only), so no shell or command is allowed.

  • A Windows target that never answers exec: a Windows terminal asks where its cursor is before it starts, and older versions left that unanswered. exec no longer uses a terminal at all; update GaiaDesk on both machines.

Updated