meshTerm 2.3.4 - User Guide
For iPhone and iPad.

1. Overview

meshTerm is an SSH client for iOS and iPadOS. It connects to remote servers over standard SSH, with built-in Tailscale networking, SFTP, port forwarding, and a fast Metal terminal.

For sessions that outlive a disconnect, meshTerm offers three levels of persistence, chosen per host: tmux (your shell survives on the server using software already on most machines, with tmux windows and panes shown as native panes), mtRoam (the optional open-source mtRoam daemon on your own host, for full persistence that survives network changes, app suspension, device switches, and daemon restarts), and None (a plain SSH shell that ends with the connection). See Persistent sessions for the walkthrough and Halo for how mtRoam's persistent ring buffer works.

Beyond the terminal, meshTerm includes:

  • Multiple concurrent sessions per host, with attach modes for sharing or watching.
  • A predictive-echo overlay that makes typing feel native on slow links.
  • A browseable view of the host's shell history, plus a chip strip of inline suggestions.
  • An SFTP file browser that integrates with the iOS Files app.
  • A customisable macro bar and a searchable Snippet Vault.
  • Native Tailscale integration for keyless SSH on your Tailnet.
  • A Containers tab for Docker, Podman and Portainer on your own servers, and Install Key and herdr sessions for Windows hosts.

2. What's new

meshTerm is currently at version 2.3.4. The headline additions since 2.1.2:

2.3.4 2.3.4

  • Valid compose files deploy again: the compose check in New Stack and Edit Compose no longer blocks files that use YAML anchors and aliases, extends, block scalars (| and >) or quoted strings over several lines. The host's own compose still checks the file before it deploys. See Deploying.
  • Smart punctuation is a warning: curly quotes or dashes pasted from the web inside a value now show as a warning instead of stopping the deploy. A curly quote that opens a value, such as image: “nginx”, still blocks, because compose would keep the quotes.

2.3.3 2.3.3

  • Default shell: choose the shell each host starts in, such as zsh, fish or PowerShell 7, without changing anything on the server. meshTerm connects with your login shell, then starts the one you chose, from the shells it finds on the host. On a new host the palette offers the choice on first connect; change it later in Edit Host > Shell & Environment > Default Shell. See Default shell.
  • Switch one session's shell: the palette's Shell tile now switches only the session you are in. Without tmux or psmux, the tab reconnects in the shell you pick and keeps it until you close the tab, even after the app restarts. With tmux or psmux, it opens a new window in that shell. New sessions still start in the host's default shell. See Switching one session.
  • psmux on Windows hosts: with psmux 3.4.0 or later, a tmux for Windows that installs for your account with no admin rights, sessions on a Windows host keep running after you disconnect. See psmux on Windows hosts.
  • Notifications you can check: in Edit Host, the notification status row shows whether alerts are installed on the host, or what is missing. Install Now sets the host up straight away, and Send Test Alert checks that alerts from that host reach this device. See Set up and test a host.
  • "Has questions" alerts: when Claude asks a question or asks you to approve a plan, or Codex asks for input, the alert says so, for example "Claude has questions." Tap it and answer in the terminal. See Notifications.
  • Alerts from Windows hosts: Claude Code and Codex alert for questions, approvals and finished turns in psmux sessions, and agy (Gemini) for finished turns. Windows needs nothing extra installed. On Linux and macOS, alerts need Python 3.5 or later and curl, and meshTerm also looks for python3 from Homebrew, pyenv, asdf and conda. See Host requirements.
  • herdr alerts setup card: a host's herdr dashboard offers Turn on herdr alerts for this iPhone (or iPad). If you installed the meshTerm herdr plugin yourself and no device is set up, herdr can remind you, at most once a week. See herdr.
  • Rootless user ID ranges: when a rootless Podman user has no user ID ranges, meshTerm offers one step that adds a free range. When the ranges are too small, it says so, and Docker 101 shows an administrator how to enlarge them safely. See User ID ranges.
  • Back to the prompt from copy mode: in tmux, or psmux on a Windows host, the return-to-prompt pill also leaves copy mode after you scroll up. See TUI return-to-prompt pill.

2.3 2.3

  • Containers: a new tab for the Docker, Podman, nerdctl and Apple container workloads on your own servers, over the SSH connections you already have. An overview of every host with an engine, a screen for each host and container with status, CPU and memory charts, logs and a Shell, and start, stop, restart and recreate with a confirmation first. Containers is part of Pro, with a free preview. See Containers.
    • New Container and New Stack: an image browser with Docker Hub search, a command preview, a Compose editor with checks, a Review screen and deploy progress that survives leaving the screen. See Deploying.
    • Templates: ready-made stacks, including Super Stacks, from a signed list. See Templates.
    • The Vault: container secrets kept in this device's Keychain and sent to the host only when you deploy. See The Vault.
    • Topology: a map of how a host's containers, networks and volumes connect, with a list version for VoiceOver. See Topology.
    • Ask an Agent: ask Claude on your host, or your own API key, why a container is failing, after you agree to what is sent. See Ask an Agent.
    • Portainer: add a Portainer server beside your own hosts. See Portainer servers.
    • iPad: the Containers tab becomes a split view with the host list in the sidebar. See iPad.
  • Windows hosts: Install Key now writes to the file Windows' SSH server reads, and with herdr 0.9.4 or later a Windows host can keep sessions running after you disconnect. See Windows hosts.
  • herdr on Windows: with herdr 0.9.4 or later, a Windows host can keep sessions running after you disconnect. Set Up herdr installs it with one tap, with no admin rights. See herdr on Windows.
  • Links that wrap in herdr and tmux splits: when herdr, or a tmux split, draws a long link across several rows (such as a sign-in URL), tapping any row now opens the whole link. meshTerm asks first and shows the site in bold, so you can check it before you open it. The palette's Links list shows the whole link too. See Tapping links in herdr and tmux.
  • A brand-new server, step by step: the common first-connection problems now say what happened in one line and offer a fix that can work.
    • A rejected key offers Copy Public Key, the line to add it on the server, and Install Key where that can work. RSA keys can't be used, so the import error offers Generate an Ed25519 Key Instead, and Add Host can generate a key.
    • When SSH is refused or times out, Server Setup Help shows how to turn on SSH and open the port for your system.
    • Add Host accepts user@host:port, ssh:// addresses and IPv6 in brackets, and says plainly when a hostname isn't valid.
    • A host with no SFTP server fails at once with the fix, instead of hanging. A tunnel that sshd blocks says to set AllowTcpForwarding.
    • The Sessions list offers Install tmux in Terminal when tmux is missing, and finds a tmux installed by Homebrew.
    • Run in Terminal now types a long fix into a terminal on the host, and brings you back to where you started when it finishes. Install lines match the host's system and your account (root, sudo, or su), and say so when your account can't install software.
    • Agents: sign-in fails fast with the CLI's own reason; a missing working folder offers Create Folder or Use Home Folder; notifications check that python3 and curl are on the host; Claude and Codex launch on macOS hosts, and on a host without procps Codex says so and offers Install procps.
    • Keep Tools on PATH: after you install a tool into ~/.local/bin, one tap makes new terminals and new tmux panes find it. See Keep Tools on PATH.
    • A host with no tmux or mtRoam sessions shows a prominent New Session.
    The commands are collected in Troubleshooting.
  • Install and fix commands stay current: the lines meshTerm shows for installing tmux, Docker, Podman, agents and herdr, and for the common fixes, come from a signed list that the app refreshes from github.com, with a copy built in. A broken command for one Linux distribution can be corrected without an app update.
  • Spanish and accessibility for Containers: Containers has a Spanish translation, and works with Dynamic Type up to the largest accessibility sizes, VoiceOver, Reduce Motion, Light mode and High Contrast.

2.2

  • herdr: meshTerm now works with herdr, which keeps Claude, Codex, Gemini and other agents running in panes on your host. Set Up herdr checks a host and installs herdr's official build in one tap. The Agents tab gains a herdr side with every herdr session on every host, alerts when an agent needs you, and approvals you can answer from your phone. herdr is free on your host: one herdr session at a time, on top of your one live session, with unlimited agents, tabs and workspaces inside it. Pro adds more hosts and parallel sessions. See herdr.
  • Native tmux: on hosts with tmux 3.2 or newer, meshTerm now talks to tmux directly (tmux "control mode"). Your tmux panes become real native panes: side by side with draggable dividers on iPad, one at a time on iPhone with a pane switcher in the top-right corner. Reconnects put you back in the same session at the same size. Control mode is on by default; a per-host tmux attach setting can choose Legacy, and meshTerm falls back to the classic attach by itself if a host's tmux is too old. See tmux sessions.
  • tmux page in the palette: a new palette page manages tmux windows and panes: switch, add, rename and close windows; split right or down, zoom, make a pane wider, narrower, taller or shorter, and even out the layout. On iPad your windows show as a row of chips.
  • Persistence picker: every host has one Persistence choice, tmux, mtRoam or None (Edit Host > Session). Check persistence on a host's Details shows whether tmux and mtroamd are installed, where, and which versions. See Choosing persistence.
  • mtroamd installs move to your package manager: installing mtroamd from the app is deprecated from iOS 2.2. Install it with your server's package manager (apt, dnf, apk, AUR, Nix) or from source. Copies the app installed earlier keep their Update, Repair, Restart and Uninstall actions. See Installing mtroamd and Switching to a package.
  • Clearer mtRoam fallbacks: if a host set to mtRoam has no mtroamd, meshTerm connects through tmux and offers Switch to tmux. If mtroamd is installed but can't be reached, you choose Retry or Open with tmux instead.
  • Settings, regrouped: Settings is organised into panes with a search field that jumps straight to the row you need, and many rows have plainer names, such as End session, Open read-only, Take control, Trusted servers, Left-handed layout, Back-to-prompt button and Full-screen apps. See Settings reference.
  • A friendlier first run: a short welcome tour (replay it from Settings > General > Show Welcome Tour), a "How do you connect?" step for Tailscale or SSH, and a clear waiting screen with an Open Admin Console button while your tailnet approves a new device.
  • Easier host editing: Edit Host is split into Connection, Session, Shell & Environment and Tunnels screens, each with its own Save, and when Save is disabled the screen says why. A password host with no saved password on this device can still be saved, with a reminder to enter it before you connect.
  • Tidier SFTP uploads: uploaded file names are cleaned up, for example dropping the cid: prefix Mail gives attachments and replacing characters that break paths or tools.
  • Firewall rules moved: the mtRoam Direct firewall rules now sit behind a Firewall setup screen in Edit Host.
  • Feedback and feature requests: a new Settings pane to report a bug, request a feature, ask a question or rate the app. See Feedback and feature requests.
  • Claude Fullscreen Mode removed: meshTerm no longer sets Claude Code's fullscreen option, so Claude Code's own default applies.
  • Faster, more reliable resume and reconnects.

2.1.11

  • Agent notifications - meshTerm can now tell you the moment an agent needs you. Get a push when Claude Code, Codex or Gemini asks for an approval or finishes a turn, even while the app is in the background or fully closed, and tap it to jump straight to that exact session. You opt in per host, choose whether approvals, turn-completions, or both notify you. Alerts come through Apple Push Notification service (APNs) via our relay, over encrypted connections, and carry nothing that identifies you, your hosts or your work. See Agent notifications.
  • Tap to resume - a notification, the lock-screen Live Activity, or a return-to-prompt tap now drops you back into the right session, and for an agent the right conversation.
  • Tappable agent sign-in - when an agent prints a long sign-in URL that wraps across several lines, meshTerm treats it as one link you can tap to open.
  • Sharper terminal - app-defined terminal palettes render true to the program's own colors, text selection keeps the word you grabbed as you extend it, agent history holds more scrollback, and warm resumes recover a dropped link even faster.

2.1.5

  • Faster, steadier reconnects - returning to the app is quicker and more reliable. meshTerm refreshes stale network paths the moment you wake, re-probes a dropped link in about a second, and no longer double-reconnects on a deep link. Your sessions snap back where you left them.
  • Clean reattach for full-screen tools - Claude Code, vim, htop, and other full-screen apps now repaint correctly when you return to a session. No more blank screen, split screen, or missing prompt after backgrounding, locking, or switching devices.
  • Secret Profiles, delivered live - inject a bundle of environment variables and keys straight into the session you are already in, with one tap. Nothing is typed and nothing is left on screen. It works over plain SSH, MTRoam, and tmux. See Secret Profiles.

2.1.4

  • Agent mode - run Claude Code, Codex, and Gemini on your own hosts, driven from a native in-app chat: streaming replies, per-tool approvals that stay pinned until you answer, plan mode, model and thinking-effort pickers, token-usage chips, slash commands, and file attachments from iOS. Agent sessions survive app restarts and network drops, and you can resume any previous conversation. See Agent Mode.
  • Approvals and sandboxing - Codex and Claude ask before commands and edits, and the request waits for you instead of scrolling away. Gemini's Sandbox mode pauses writes outside the working directory for your approval, with optional bubblewrap kernel hardening on the host.
  • The keyboard palette - the accessory keyboard is now a three-page palette: a features page (files, buffer and history search, snippets, tunnels, agents), a keys page built from your own key groups, and a sessions page for one-tap switching. See Keyboard.
  • One-tap tunnels - add a port forward straight from the Tunnels sheet on a running session. It starts immediately with no reconnect and persists on the host for every future connect.

2.0 to 2.1.2

  • All-new Metal terminal - the renderer was rebuilt from scratch for smoother output and rock-steady layout. Live content stays pinned above the keyboard and the grid holds steady through rotations, with nothing to configure.
  • iCloud Sync (Pro) - hosts, known-host trust, your SSH key list, macros, snippets, Tailscale profiles, session tags and preferences sync across your devices. Secrets ride iCloud Keychain (end-to-end encrypted). Opt-in, off by default.
  • Port forwarding / Tunnels - local (-L) forwards and a dynamic SOCKS5 (-D) proxy, configured per host, with an in-app browser for local web forwards.
  • Session takeover - open a session on one device and take it over from another with a single tap; the displaced device drops to read-only with a Take Over banner.
  • Sessions tab - the old Hosts tab is retired; your hosts and their live and resumable sessions now live together under Sessions, with per-host CPU, RAM and storage stats.
  • Tailscale, deeper - browser sign-in (no auth keys to paste), multiple named profiles with per-host binding, an in-app device browser, and fully in-process networking (no Tailscale app required). Headscale and self-hosted control servers are supported.
  • Retro color modes - Green, Blue and Red phosphor plus Monochrome, alongside True Color, with diff-aware brightness so additions stay bright and removals dim.
  • Agent-aware terminal - a return-to-prompt pill for Claude Code and Codex, a "Claude may be idle" banner with one-tap Save & Restart, and a fullscreen mode for agent TUIs (removed in 2.2).
  • Reconnect hardening - faster, quieter resumes after a network change or a long spell in the background, with anti-flood backoff.
  • In-place host-key re-trust and SSH key file import.

3. Getting started

The welcome tour 2.2

On first launch meshTerm shows a short welcome tour: tap Get Started, skim What it does, then answer How do you connect?:

  • Tailscale (Recommended): sign in to your tailnet, then pick a device to add. If your tailnet requires an admin to approve new devices, meshTerm shows Waiting for device approval with an Open Admin Console button; the connection completes by itself once the device is approved.
  • SSH: add a host with a key or password (below).
  • Continue skips this step and goes straight into the app.

Replay the tour any time from Settings > General > Show Welcome Tour.

Adding your first host

  1. On the Sessions tab, tap + in the top right (or the globe icon to browse and add a host from your Tailnet).
  2. Where is it? Fill in the connection details:
    • Label: a friendly name (for example demo).
    • Hostname or IP: the address of your server.
    • Port: defaults to 22.
    • Username: your account on the server.
  3. How do you sign in? Pick an authentication method: password, SSH key, or (if the server runs Tailscale SSH) Tailscale SSH.
  4. Session preferences: pick the host's Persistence: tmux, mtRoam or None (see Choosing persistence). You can change it later in Edit Host > Session.
  5. Ready to connect: check the summary and tap Connect.

Connecting

Tap any host in the list to open a terminal session. On first connect to a new host, meshTerm asks you to verify its host-key fingerprint (see Trusted servers) - tap Trust & Connect to proceed.

4. Managing hosts

Editing a host

Long-press a host card and tap Edit. Edit Host opens on a short list of screens:

  • Connection: address, authentication, tags, operating system, and (for an mtRoam host) the mtRoam transport.
  • Session: the Persistence picker and the settings of the chosen option (see Choosing persistence).
  • Shell & Environment: the Default Shell 2.3.3 (the shell every new session on the host starts in), working directory, the per-host Back-to-prompt button setting, and environment variables.
  • Tunnels: port forwarding rules.

Below them, Changes on this host lists what meshTerm leaves on the server, such as agent notification hooks, and lets you turn them off or remove them where that is possible.

Keep Tools on PATH 2.3: a tool installed into a new ~/.local/bin (Claude Code's installer does this on Debian) is not found by terminals and tmux panes that were already open. After such an install, meshTerm offers Turn On Keep Tools on PATH. It adds a marked block to the host's ~/.bashrc or ~/.zshrc (other shells are skipped, and meshTerm says so), and tmux sessions get ~/.local/bin on their PATH when you attach. It is listed under Changes on this host, backed up once, and turning it off removes exactly that block.

Save is available on every screen, so you can save where you made the change. When Save is disabled, a note at the bottom says why (a host needs a label, hostname and username). A password host with no password saved on this device can still be saved; a reminder asks you to enter the password in Connection before you connect.

Deleting a host

Tap Edit at the top of the Sessions tab, then the red minus on a host to remove it (you can also drag to reorder here). A host is also reachable by long-press for a context menu of actions.

Tags & filter chips

Tag hosts in the editor's Tags section (comma-separated, e.g. prod, web). A chip row at the top of the Sessions tab lets you filter by tag.

Host import / export

Settings → Hosts gives you two buttons:

  • Import from .ssh/config - pick a host you can already SSH to. meshTerm reads its ~/.ssh/config over SSH and shows a checklist of entries to mirror. Imported hosts start in password mode with an empty password - set credentials in the editor before connecting.
  • Export to ssh_config - emits a standard OpenSSH config file you can drop into your dotfiles or AirDrop to a laptop. Roam-enabled hosts are exported as plain SSH (the Roam protocol is meshTerm-specific).

Distro / OS icons

Each host card shows a small icon for its operating system - Ubuntu, Debian, Fedora, CentOS / Rocky / Alma, Arch, openSUSE, NixOS, Linux Mint, Gentoo, elementary OS, Void, Solus, Zorin, deepin, macOS (Apple logo), FreeBSD, Android, AIX, and GNU/Hurd. The icon is tinted with the host's per-card hue. Choose the OS in Edit Host > Connection > Operating System; Unknown falls back to the generic Linux icon and shows the host's initials as a monogram.

5. Connecting to a host

Tap any host in the Sessions tab to open a terminal session.

Verifying the host key

On the first connection to a new host, meshTerm shows its host-key fingerprint and asks you to confirm it (trust on first use). Tap Trust & Connect to save the key and proceed. If a host's key changes later, meshTerm does not fail silently: it shows an accept-or-compare sheet so you can review and re-trust the new key in place.

Reconnecting

meshTerm keeps working as you move between networks and background the app; when you return, live sessions reconnect automatically. A plain SSH shell ends when its connection drops. To keep a shell alive across drops, use tmux or mtRoam (see Persistent sessions).

Sessions on a host

For a host that uses tmux or mtRoam, long-press it and choose Sessions… to see the sessions living on the server. Tap one to attach, tap + to start a new one, or swipe a row to the left and tap End session to close it on the host (meshTerm asks first). Inside a tmux session, windows and panes are managed from the palette's tmux page: see tmux sessions.

Windows hosts 2.3

meshTerm connects to the OpenSSH server that comes with Windows. It is built into Windows 10 and 11 and Windows Server 2019 and later. If it isn't running yet, install OpenSSH Server from Settings > Optional Features, then start the sshd service. meshTerm detects a Windows host the first time you connect. You can also choose Windows yourself in Edit Host > Connection > Operating System.

Signing in

Windows decides who may sign in, not meshTerm. Many servers only allow members of Administrators or the OpenSSH Users group (the AllowGroups line in the server's config). If a standard account is refused, ask an administrator to add it to OpenSSH Users.

Tip: an account must have signed in to Windows at least once before it can use SSH. That first sign-in creates the account's profile folder.

Keys on a Windows host

Install Key writes your public key to the file the Windows SSH server really reads:

  • A standard account: usually C:\Users\<you>\.ssh\authorized_keys.
  • An administrator: C:\ProgramData\ssh\administrators_authorized_keys, locked to Administrators and SYSTEM.

If the server's config keeps keys somewhere a standard account can't write to (for example C:\ProgramData\ssh\keys\...), meshTerm tells you which file it is and that an administrator needs to add the key. If the server's config is unusual, meshTerm adds the key but tells you to check that it works. The key help in Getting Connected shows a command for Windows that works in both Command Prompt and PowerShell.

What works differently

  • Working Directory, environment variables and Secret Profiles aren't applied to Windows hosts. The host editor says so.
  • The file browser opens in your home folder. Old compatibility folders such as "My Documents", and folders you don't have access to, can't be opened. meshTerm tells you so.
  • Attachments can't be sent to Windows hosts yet.
  • One-tap fixes in the app are for Linux and macOS hosts.
  • tmux and mtRoam need Linux or macOS. For sessions that survive a disconnect on Windows, use herdr.

Tailscale and Windows

A Windows machine on your tailnet works like any other host. Connect to its tailnet name or 100.x address and sign in with a key or a password. Tailscale SSH (Tailscale's own SSH server, with tailnet sign-in) isn't available on Windows, so meshTerm doesn't offer it for Windows hosts. A device that Tailscale reports as Windows starts on password sign-in.

Checking the host key

To compare the fingerprint meshTerm shows, run this in an administrator PowerShell on the Windows machine:

ssh-keygen -lf $env:ProgramData\ssh\ssh_host_ed25519_key.pub

6. Persistent sessions: tmux and mtRoam

A plain SSH shell ends when its connection drops. To keep your shell running on the host while your phone sleeps, changes network or switches to another device, meshTerm offers three choices per host:

  • tmux: your shell lives in a tmux session on the host, using software already on most servers. This is the default for new hosts.
  • mtRoam: your shell lives in the open-source mtRoam service (mtroamd) on your own host, with its Halo scrollback buffer, named sessions and attach modes.
  • None: plain SSH. The shell ends with the connection.

Choosing persistence for a host 2.2

Pick one in the Persistence picker (tmux, mtRoam or None). It is on the Session preferences step when you add a host, and under Edit Host > Session afterwards.

  • With tmux chosen you can also set a Session name (optional); leave it blank to use a name derived from your device. The tmux attach setting is described in Control mode or Legacy.
  • With mtRoam chosen the picker reminds you that it "Needs the mtRoam service (mtroamd) on the host." and links the Install guide. The mtRoam settings (Keep alive, Session name, and so on) appear below it.
  • A host marked as Windows connects over plain SSH: tmux and mtRoam need a Linux or macOS host. To keep a session running on Windows after you disconnect, use herdr 2.3. See Windows hosts.

New hosts start with the choice in Settings > Sessions > Persistence for new hosts (tmux or None). mtRoam is always chosen per host. If a host's choice differs from that default, Edit Host > Session offers Reset to app default.

Check persistence 2.2

Not sure what a host has installed? Open the host's Details (long-press the host) and tap Check persistence in the Persistence section. meshTerm runs one read-only command over SSH and shows a row each for tmux and mtroamd: the version and where it was found, Not found, or Unknown if the host could not be reached. Nothing is installed or changed.

  • The tmux row says Control mode: ready. for tmux 3.2 or newer, or that it is too old for control mode (see below).
  • For an mtroamd that meshTerm installed itself (in ~/.local/bin), the mtroamd row carries the Update, Repair, Restart and Uninstall buttons. Any other copy shows "Installed by a package manager." instead, with a link to the install guide.
  • Finding mtroamd never changes the host's setting: pick mtRoam yourself in Edit Host > Session if you want to use it.

tmux sessions 2.2

On a host with tmux 3.2 or newer, meshTerm talks to tmux directly through tmux's own control mode. Instead of drawing a tmux client inside one terminal, meshTerm knows every window and pane and shows each pane as its own native terminal, with its own scrollback. When you come back to the app, it reattaches to the exact session you left, sized to your screen. The status line you configured in tmux on the host is left alone (the old tmux Status Bar setting is gone).

If another device takes the session over, your screen shows Detached from another device with a Reattach button to take it back.

Panes on iPad and iPhone

  • iPad: the panes of the current window are laid out side by side as tmux arranges them. Drag a divider to resize the panes (the size is applied when you let go); double-tap a divider to even them out.
  • iPhone: held upright, you see one pane at a time. When the window has more than one pane, a small row of dots sits in the top-right corner of the terminal (top-left with Left-handed layout on): tap a dot, or swipe across the dots, to switch panes. The pane you leave keeps running, so switching back shows its current output straight away.

Windows and panes from the palette

While a tmux session is attached in control mode, the keyboard palette gains a fourth page, marked with the tmux icon. It lists your Windows and the Panes of the current window:

  • Windows: tap a window to switch to it; tap New window to add one. Each window's ... menu has Rename window and Close window. On iPad the windows show as a row of chips.
  • Panes: a small map of the window's layout; tap a pane to focus it. Below it: Split right, Split down and, with more than one pane, Zoom / Unzoom. The ... menu has Rename pane, Fit to this screen (useful when a desktop client left the session another size) and Close pane.
  • Resize: in a window with several panes (and not zoomed), Wider, Narrower, Taller and Shorter resize the focused pane, and Even out evens the whole window.

Closing a window or pane asks first, since it also closes whatever is running in it.

With a hardware keyboard, control mode adds its own shortcuts; see External keyboards.

Control mode or Legacy

Control mode is on by default. Each tmux host has a tmux attach setting in Edit Host > Session (shown while Persistence is tmux) with two choices:

  • Control mode: recommended. Native panes, the tmux palette page and the iPad splits described above.
  • Legacy: "a plain tmux client, without splits or the window palette", the way meshTerm attached to tmux before 2.2. Use it if control mode misbehaves on a particular host.

A control-mode session picks up a change to this setting the next time it reattaches; a Legacy session switches to control mode when you start a new session.

Older tmux, and hosts without tmux

  • tmux older than 3.2: meshTerm notices and automatically reconnects with the classic tmux attach, so the session still persists. Check persistence explains this on the tmux row. After you upgrade tmux on the host, tap Check persistence so meshTerm tries control mode again on the next connect.
  • No tmux: the session opens as a plain shell with a No session persistence banner. Where meshTerm knows your distro's install command, Install tmux pastes it at your prompt for you to review and run.

mtRoam

mtRoam (Roam in earlier versions of this guide) is meshTerm's own persistent-session service, powered by the open-source mtroamd daemon on your host. Your shell survives reconnects, app suspension, device switches, and even daemon restarts, with full scrollback replayed on reattach. Its signature is Halo, the persistent ring buffer described below.

Installing mtroamd

Installing mtroamd from the app is deprecated from iOS 2.2. meshTerm no longer installs the daemon. Install it with your server's package manager (apt, dnf, apk, AUR or Nix) or build it from source, following the mtroamd install page. A copy the app installed earlier (in ~/.local/bin) keeps working, and the app still offers Update, Repair, Restart and Uninstall for it. To move that copy onto a package, see Switching from the app-installed mtroamd to a package.

The install page is the place for the repository and signing-key setup of each package manager. Once the repository is added, the install itself is one line:

SystemInstall
Debian, Ubuntu (apt)sudo apt install mtroamd
Fedora (dnf)sudo dnf install mtroamd
Alpine (apk, x86_64 for now)apk add mtroamd (as root, after adding the repository)
Arch (AUR)mtroamd-bin (prebuilt) or mtroamd (builds from source)
Nix / NixOSThe flake's NixOS module or home-manager module (see Nix below)
Any systemd LinuxBuild from source

The packages come in two channels. Stable is the one the App Store version of meshTerm pairs with, and the one to use. Dev carries pre-releases that pair with TestFlight builds.

On apt and dnf, run the install as your normal login user with sudo: the package then starts mtroamd for that user and keeps it running after you log out. Check it with mtroamd doctor. Then set the host's Persistence to mtRoam in Edit Host > Session and connect.

Updating and maintaining mtroamd

  • Package-managed copy: update it with the package manager, for example sudo apt upgrade mtroamd or sudo dnf upgrade mtroamd. The app shows "Installed by a package manager." in place of the maintenance buttons, adding "Update it with your package manager." when a newer daemon is available.
  • App-installed copy (in ~/.local/bin): when meshTerm needs a newer daemon, the host shows mtRoam service update available with the installed and available versions; tap Update now. The host's Details screen also offers Repair (re-downloads the current release, verifies it and restarts), Restart mtRoam service and Uninstall. Each asks first. Sessions set to persist across restarts are kept through a Repair or Restart; Uninstall ends all mtRoam sessions on the host. Your pairing (certificate and key) is kept either way.
  • If meshTerm has never seen the daemon's version, or does not yet know who installed it, it asks you to run Check persistence before it offers any of these.
Before 2.2, connecting to a Roam host without the daemon opened a Set Up Roam sheet that downloaded and installed mtroamd. That sheet, and the Reinstall button, are gone.

Building from source

On any systemd Linux you can build mtroamd yourself. You need Go 1.26 or newer. Build a release tag (the version shown as "Current stable" on the install page), not an arbitrary development commit: the app requires a minimum daemon version.

git clone https://github.com/AG-Studio-Apps/mtroamd.git
cd mtroamd
git checkout v1.8.0          # use the current stable tag from the install page
make build build-mtroam      # builds ./mtroamd and ./mtroam
sudo install -m 755 mtroamd mtroam /usr/local/bin/

If this host has an app-installed copy, switch it over with /usr/local/bin/mtroamd migrate (see AUR and source builds). Otherwise set up the service yourself:

mkdir -p ~/.config/systemd/user
mtroamd unit print --bin=/usr/local/bin/mtroamd > ~/.config/systemd/user/mtroamd.service
systemctl --user daemon-reload
systemctl --user enable --now mtroamd
sudo loginctl enable-linger "$USER"
mtroamd doctor
Install your build to /usr/local/bin, not ~/.local/bin. A binary in ~/.local/bin is treated as the app-installed copy: the app offers Update, Repair and Uninstall for it, and an update would replace your build with a release download.

To update a source build, check out the new tag, rebuild, install, and restart (a restart keeps live sessions):

git pull && git checkout <new tag>
make build build-mtroam
sudo install -m 755 mtroamd mtroam /usr/local/bin/
systemctl --user restart mtroamd

Switching from the app-installed mtroamd to a package 2.2

If meshTerm installed mtroamd on a host for you (it lives at ~/.local/bin/mtroamd), you can move that host onto a package or a source build. Whatever the method, the daemon's state in ~/.local/share/mtroamd (the certificate the app trusts, and your session state) is kept, so the app reconnects with no re-pairing. There is nothing to change in the app: it finds the new binary on its next connect and dials the same socket (~/.local/share/mtroamd/mtroamd.sock), which every package uses by default.

apt and dnf: automatic

  1. Add the repository from the install page.
  2. As your normal login user, run sudo apt install mtroamd or sudo dnf install mtroamd.
  3. Watch for mtroamd: migrating existing ~/.local/bin install for '<you>' followed by a line saying it migrated with sessions preserved. That's it.

What happens. The package notices the ~/.local/bin copy belonging to the user who ran sudo and runs mtroamd migrate --yes as that user. migrate:

  • rewrites your systemd user service to run /usr/bin/mtroamd, keeping the same ports and socket;
  • restarts the daemon in a way that keeps your live sessions running (they reattach to the new daemon);
  • removes ~/.local/bin/mtroamd only once the new daemon is confirmed running;
  • puts your previous setup back if any step fails, so you are never left half-migrated.

If it didn't migrate. If the installer printed that the user session "isn't reachable from here" or that the auto-migration failed, or you installed as root or from automation (no sudo user), run the migration yourself as your login user:

/usr/bin/mtroamd migrate

Use the full path: until the migration runs, a plain mtroamd may still find the old copy in ~/.local/bin first, which only replies that there is nothing to migrate to. Until you migrate, both copies exist and the old one keeps running, so package upgrades do not take effect.

Several users on one host? Only the user who ran sudo is migrated. Each other user with an app-installed copy runs /usr/bin/mtroamd migrate themselves.

AUR and source builds: run migrate once

These do not migrate automatically. After installing, run migrate as your login user, using the new binary's full path (the old ~/.local/bin copy refuses with "nothing to migrate to"):

/usr/bin/mtroamd migrate          # AUR
/usr/local/bin/mtroamd migrate    # source build
sudo loginctl enable-linger "$USER"   # if not already, so it survives logout and reboot

migrate performs the same safe switch described above: same ports and socket, live sessions kept, the old binary removed only once the new daemon is running, and a rollback if anything fails.

Nix and NixOS

Don't use mtroamd migrate here (it would write a Nix store path into your own service file). Instead, remove the app-installed copy while keeping its state, then let Nix run the daemon:

  1. As your login user:
    ~/.local/bin/mtroamd uninstall --yes
    This stops the old daemon and removes its user service, ~/.local/bin/mtroamd and ~/.local/bin/mtroam, and keeps ~/.local/share/mtroamd. Never add --purge: that deletes the certificate, and the app would have to trust the host again.
  2. Enable the module and rebuild. On NixOS:
    imports = [ mtroamd.nixosModules.default ];
    services.mtroamd = { enable = true; users = [ "you" ]; };
    This also keeps the daemon running after you log out and puts mtroamd on your PATH. With home-manager, set services.mtroamd.enable = true; and, in your NixOS configuration, users.users.<you>.linger = true.
Open mtRoam sessions on the host end when the old daemon stops. Save your work first.

Alpine (apk)

Alpine has no systemd, so there is no migrate step:

  1. As your login user: ~/.local/bin/mtroamd uninstall --yes (keeps your state; never add --purge).
  2. As root, install mtroamd from the apk repository on the install page.
  3. In /etc/conf.d/mtroamd, set MTROAMD_USER to your login user. The daemon starts your shells as that user and uses that user's ~/.local/share/mtroamd, so the certificate the app trusts carries over.
  4. Start it, and enable it at boot: rc-update add mtroamd && rc-service mtroamd start.

As with Nix, open sessions end when the old daemon stops.

Verify

  • mtroamd doctor reports the daemon's health.
  • command -v mtroamd should print the package or source path, not ~/.local/bin. (Open a new shell first if it still shows the old path.)
  • On systemd: systemctl --user status mtroamd. On Alpine: rc-service mtroamd status.
  • In meshTerm, open the host's Details and tap Check persistence. The mtroamd row now shows the new path and "Installed by a package manager." in place of Update, Repair, Restart and Uninstall. (meshTerm also re-checks by itself when you open the host's Details and its last check is more than a day old.) From now on, update with your package manager, or by rebuilding for a source install.

The app-installed companion CLI ~/.local/bin/mtroam is left in place by migrate; you can delete it so the packaged mtroam is used instead.

Choosing a transport (Direct vs SSH Tunnel)

mtRoam can reach the daemon two ways. With Persistence set to mtRoam, open Edit Host > Connection, then mtRoam transport > Transport Details > mtRoam Transport:

  • Direct (QUIC/TCP): meshTerm dials the daemon's QUIC port directly over UDP. Lowest latency, but the daemon's UDP port (49820 by default) has to be reachable from your device. The Firewall setup row under Transport Details opens the exact firewall rules for the host.
  • SSH Tunnel: the mtRoam protocol is carried inside the SSH connection you already authenticated with. Nothing extra to open: it works through any firewall that allows SSH, at a little more latency than Direct.

If you choose Direct and the UDP port turns out to be blocked, meshTerm falls back to the SSH tunnel for that connection, so a session always comes up. Over meshTerm's built-in Tailscale, Direct uses mtRoam over TCP on the tailnet instead (port 49920 by default), and Firewall setup shows the matching rule.

Multiple named sessions per host

Each mtRoam host can hold any number of named sessions: dev, logs, tests, whatever you want. Tap the host and a picker appears showing the existing sessions; tap one to attach, or tap + to start a fresh one.

Manage sessions from the picker:

  • Rename: swipe a row to the right, or long-press it and choose Rename…. Only the label changes; the shell and its scrollback are untouched.
  • End session: swipe a row to the left, or long-press it. Confirmation required.
  • Open read-only: long-press a row to watch a session without taking it over (see Attach modes).

If a host only has one session, meshTerm skips the picker and attaches directly. If it has none, a fresh session is spawned and you connect to it.

Halo: the persistent ring buffer

The thing that makes Roam durable is a per-session ring buffer the daemon keeps for every session. We call it Halo. It is a rolling window of your session's output (up to 4 MiB per session) that lives on the host, independent of whether any client is attached. When your phone drops off, backgrounds, or switches networks, the shell keeps running and its output keeps flowing into the ring, so nothing is lost while you are away.

When you reattach, the daemon replays the ring from the exact byte you last acknowledged and then hands you straight into the live stream with no visible seam. Because the buffer tracks output by byte position, replay resumes precisely where you left off rather than redrawing the whole screen. A few details worth knowing:

  • Recency window. meshTerm asks for only as much replay as your scrollback setting can actually display, so a quick reconnect does not re-stream megabytes you will never scroll back to.
  • Full-screen apps. Inside a full-screen TUI (vim, htop, a pager) the replay budget tightens automatically, since an alt-screen app has no scrollback of its own. The daemon also reconstructs the app's stable bottom rows (status bars, prompts) so they are intact the moment you reattach.
  • Honest truncation. If you were away long enough that the oldest output rolled out of the 4 MiB ring, meshTerm tells you plainly that some output was lost during the disconnect rather than pretending the scrollback is complete.
  • Survives daemon restarts. With Persist across mtRoam service restarts on, the ring is checkpointed to disk, so your scrollback and session come back even after a self-update or a host reboot.

Halo lives entirely on the open-source daemon; nothing about your session travels anywhere but between your device and your own host. The full buffer and replay design is documented in the mtroamd repository.

Default session and pinning

In Edit Host > Session, the mtRoam section (shown while Persistence is mtRoam) holds:

  • Session name: which named session the host opens by default. Tap it to change the session or remove sessions you no longer need. None uses your most recently attached one.
  • Always open this session: pins the host directly to that session, skipping the picker. The picker is still available via long-press > Sessions….
  • Persist across mtRoam service restarts: when on, the session's scrollback is snapshotted to disk so it survives a daemon restart (for example after an update or a host reboot).

Keep-alive (idle timeout)

Keep alive, in the same section, sets how long the mtRoam service holds a session when no client is attached. Options: Default (30 days), 1 hour, 1 day, 7 days, 30 days, or Never (until daemon restart).

Attach modes

When you join a Roam session, meshTerm uses one of three roles:

  • Exclusive (default) - you receive output, you send keystrokes, you own the terminal size. If someone else attaches exclusively, you're handed off to read-only.
  • Read-only - you see everything but your keystrokes are dropped at the daemon. Useful for watching a colleague drive, or for a second device tailing along.
  • Passive - a quiet tail. Same as read-only but invisible to the other clients' "who else is attached" indicators. Used by the mtroam tail command.

Any number of read-only watchers can coexist with a single exclusive driver. The session label in the bar shows your role.

To watch rather than drive, long-press a session in the picker and choose Open read-only. When another device holds the session, your screen shows a Live on another device banner: tap Take control to move typing to this device, and the other device becomes the viewer.

Desktop CLI: mtroam 2.0

The mtRoam daemon ships with a small companion command-line tool called mtroam, installed alongside mtroamd by the packages and by a source build. Use it from any SSH session on the host (or from a laptop with ssh user@host mtroam …) to manage sessions without opening the iOS app.

Subcommands:

  • mtroam list - enumerate sessions on this host (id, name, idle time, attached clients).
  • mtroam session-info <name> - detail for one session, including geometry and idle state.
  • mtroam status - daemon health snapshot.
  • mtroam search <regex> <session> - grep a session's scrollback.
  • mtroam doctor - diagnostic checks for daemon, supervisor unit, and lingering.
  • mtroam tail <session> - passively attach to live output. No input, no replay; just a tail.
  • mtroam new --name <name> - create a new named session without attaching to it. Useful for pre-creating a session before opening the app, or for cron jobs.
  • mtroam attach <session> - attach to a session as the local terminal. Detach with ~. on a fresh line.
  • mtroam kill <session> - reap a session.
  • mtroam rename <session> <new-name> - rename a session. Buffer and active attaches are unaffected.
  • mtroam update - check for and apply a signed self-update from the project's GitHub Releases.
  • mtroam restart - cycle the daemon via its supervisor. In-flight sessions survive the restart.
  • mtroam uninstall - remove the mtroam binary.

On a host where mtroamd came from a package manager, update and remove it with the package manager instead (see Installing mtroamd).

Authentication uses your normal SSH config - ~/.ssh/config, ssh-agent and keys all work. mtroam invokes the system ssh binary, so anything that works for ssh user@host works here too.

Each mtroam invocation accepts --host user@host to pick a target, or reads $MTROAM_HOST, or falls back to ~/.config/mtroam/host.

7. Agent Mode 2.1

Agent Mode runs a coding agent on one of your own hosts and gives you a native chat to drive it from. Start Claude Code, Codex, or Gemini on any host, and instead of watching a raw TUI scroll past, you get a real conversation: streaming replies, tappable approvals, and the agent's tools, all inside meshTerm's own interface.

The agent runs where your code is. meshTerm launches the provider's own CLI on the server, over the same SSH or mtRoam connection you already use, so the model works against your real files, your real environment, and your own API keys or logins on the host. Nothing about your project leaves your host and your device.

Starting an agent

Open the keyboard palette's features page and tap Agents, or start one from a running session. Pick a provider and meshTerm opens the agent chat. From there you type as you would in any chat: your message goes to the agent, and its reply streams back token by token.

Replies, models, and effort

  • Streaming replies - text appears as the model produces it, so you can read along and stop early if it is heading the wrong way.
  • Model picker - choose which model the provider should use for this conversation.
  • Thinking-effort picker - dial how much reasoning the model spends before it answers, where the provider supports it.
  • Token-usage chips - each turn shows what it cost in tokens (or an estimate where the provider does not report exact counts), so a long session never surprises you.
  • Slash commands - the provider's own slash commands work straight from the chat input.

Plan mode

Turn on plan mode and the agent works out an approach and lays out the steps before it touches anything. Review the plan, then let it proceed. It is the safe way to point an agent at a change without it editing files the moment you hit send.

Approvals and sandboxing

Agents ask before they act, and the request waits for you instead of scrolling away:

  • Codex and Claude ask before running a command or editing a file. The approval request appears as a pill in the chat and stays pinned until you answer it, so a prompt never gets lost in a fast-moving conversation. Approve or deny with a tap.
  • Gemini Sandbox pauses any write outside the working directory and surfaces it for your approval, so the agent can read freely but cannot change files elsewhere without a yes from you. On hosts that support it, an optional bubblewrap layer adds kernel-level hardening around the agent's process.

File attachments

Attach files straight from iOS into the agent's workspace. Pick from the iOS Files sheet and meshTerm places them where the agent can see them, so you can hand the model a log, a screenshot, or a document without leaving the chat.

Persistence and resume

Agent sessions are as durable as the rest of Roam. An agent keeps running through an app restart or a network drop and picks straight back up when you return. You can resume any previous conversation, including agent sessions you started from the terminal rather than the chat, so a session you kicked off in a plain shell is still yours to continue in the native chat later.

Notifications 2.3.3

Get an alert when an agent has questions, needs approval or finishes a turn, even with meshTerm in the background or closed. Tap it to open the session. Notificaciones en español.

Alerts work in meshTerm-managed tmux and mtRoam sessions, herdr panes, and chats in the Agents tab on Linux and macOS. On Windows hosts, they come from psmux sessions and herdr panes. A plain SSH tab or a tmux session you started outside meshTerm cannot route an alert to your phone because it has no meshTerm session record linking it to your device.

  • Linux and macOS: Claude Code and Codex can alert for questions, approvals and turn-completion; agy (Gemini) alerts for turn-completion. On macOS, start terminal Codex with codex --no-daemon, including in herdr panes; Codex chats in the Agents tab work without this option.
  • Windows: Claude Code and Codex alert for questions, approvals and turn-completion in psmux sessions; agy (Gemini) alerts for turn-completion. Codex in herdr panes alerts through herdr. Turn on Notify for herdr Agents for alerts from Claude, Codex, Gemini and other agents herdr recognizes.

Codex on Windows and Linux: when two Codex windows share a folder, meshTerm can identify only one, so the other can miss alerts. Launching a window with codex resume <id> always identifies its session for routing. With more than one phone or tablet set up for alerts on the host, only windows launched with codex resume <id> send Codex's background alerts. Use separate folders or resume the specific session; meshTerm skips an alert when it cannot identify the window.

Question alerts: when Claude asks a question (AskUserQuestion) or asks you to approve a plan, or Codex asks for input (request_user_input), the alert says, for example, "Claude has questions." Tap it to open the session and answer in the terminal, never from the alert. Ordinary approvals keep their "needs approval" wording. agy has no question alerts. The herdr plugin cannot distinguish questions from approvals, so alerts sent by the plugin keep the approval wording.

Set up and test a host

In Edit Host, turn on Notify this iPhone (Notify this iPad on an iPad) and save. This is opt-in for each host on each device; it does not sync. The status row shows Installed on this host, Not checked yet, or what is missing, with the last check when available. Not checked yet means there is no saved result, not that installation failed.

Tap Install Now to set up the host immediately, or let meshTerm do it on your next managed session connection or agent launch from the Agents tab. Tap Send Test Alert to check delivery from that host to this phone. It is also available before the first check. Save any edits first. If something is missing, the row explains it and offers the appropriate repair; see Notifications don't arrive.

Setup adds notification hooks to the agents' own configuration. Exit and restart any agent that was already running so it loads the hooks; you can leave its terminal session open. For herdr, also enable Notify for herdr Agents. In Settings > Agents > Notifications, Agent needs approval controls both approval and question alerts; Turn finished controls turn-completion alerts.

Host requirements

  • Linux and macOS: Python 3.5 or later and curl. meshTerm looks for python3 on PATH and in /usr/bin, Homebrew's /opt/homebrew/bin and /usr/local/bin, ~/.local/bin, pyenv's ~/.pyenv/shims, asdf's ~/.asdf/shims, and conda's ~/miniconda3/bin, ~/anaconda3/bin, ~/miniforge3/bin and /opt/conda/bin. Hooks reuse the Python checked at installation. If the only Python on a Mac is /usr/bin/python3, install Apple's Command Line Tools with xcode-select --install; without them that path is only a placeholder.
  • Windows: nothing extra to install for alerts: they use Windows PowerShell 5.1 and the built-in curl.exe. Restricted PowerShell (Constrained Language Mode) blocks setup. The app shows PowerShell Is Restricted and "PowerShell is restricted on HOST, so meshTerm can't turn on notifications there." Ask the host's administrator about its PowerShell policy.

Alerts travel through Apple Push Notification service (APNs) via our relay over encrypted connections. They carry an opaque session tag, the alert kind and agent name, never prompts, agent output, host names or commands. Your phone maps the tag to the session locally. See Privacy.

Notifications follow you. Terminal alerts go to the device that last used the session with notifications on; Agents tab alerts go to the device that sent the message. herdr alerts go to every device with herdr alerts on. Turning alerts off removes this device's notification details from the host when it is reachable; its file stays while herdr alerts are still on.

herdr 2.2

herdr is an open-source terminal workspace for coding agents. It keeps Claude Code, Codex, Gemini and other agents running in panes on your host, whether or not meshTerm is open, and knows when one is waiting for you. meshTerm reads herdr's own status over SSH, so you can see and answer your agents from your phone without opening a terminal.

Free on your host. The free plan includes one herdr session at a time, on top of your one live session, with no limit on the agents, tabs and workspaces inside it. meshTerm Pro adds more hosts and parallel sessions.

Set Up herdr

Open Set Up herdr from the Agents tab (the onboarding card, or + on the herdr side) or from Settings > herdr. Pick a host and meshTerm checks it: whether herdr is installed and which version, whether python3 is there for live status (Linux and macOS), and whether alerts are on. If herdr is missing or older than 0.9.2 (0.9.4 on Windows), Install runs herdr's official installer on the host and shows you its output as it goes. The exact command is shown before it runs:

curl -fsSL https://herdr.dev/install.sh -o ~/.mt-install-herdr.sh && sh ~/.mt-install-herdr.sh && rm -f ~/.mt-install-herdr.sh

It downloads first so a failed download can't look like a success, puts one program in ~/.local/bin, needs no admin rights and changes nothing else. Prefer Homebrew, mise or Nix? Follow herdr's install guide instead. These steps are for Linux and macOS hosts; for Windows see herdr on Windows. The last step turns on alerts for the host and starts your first herdr session.

The Agents tab: Chats and herdr

Once herdr is found on a host, the Agents tab has two sides. Chats are the agents meshTerm runs for you in its native chat. herdr is an overview of every herdr session on every host: what needs you first, then each host's sessions as cards with their agents and status. A slim banner tells you when the other side has something waiting, and the tab's badge counts both. Pull down to check your hosts again.

Tap a session card to open its dashboard: workspaces, tabs and panes, which agent is working, waiting or done, and buttons to open the terminal, add a tab or a workspace. From the dashboard's menu you can pin, end or delete a session. A herdr session's terminal is an ordinary terminal session in meshTerm.

Alerts and approvals

Turn on Notify for herdr Agents for the host, in Set Up herdr or in Changes on this host (it needs Notify this iPhone or Notify this iPad on first), and the agents herdr recognizes, Claude, Codex and Gemini included, alert you when they need you or finish (see Notifications). It adds a small notification plugin to herdr, and every device that turns it on gets herdr's alerts. Alerts come through Apple Push Notification service (APNs) via our relay, over encrypted connections, and carry nothing that identifies you, your hosts or your work. When an agent waits for approval, Review shows the full prompt and lets you approve or deny it from your phone; anything meshTerm can't read safely opens the terminal at that pane instead.

If you installed the meshTerm plugin outside meshTerm and no device is set up for alerts, herdr can show "meshTerm alerts aren't set up" with "Open this host in meshTerm" at most once a week. The plugin's Set up meshTerm alerts action shows setup guidance on demand; on Windows it uses a toast, which depends on herdr's toast settings. In meshTerm, the host's herdr dashboard offers Turn on herdr alerts for this iPhone (or iPad / device). Tap Turn On to enable them, or Not Now to dismiss the card on this device.

herdr in the terminal

In a herdr terminal the keyboard palette has a herdr page that sends herdr's own keys under your host's prefix: new and next tab, splits, zoom, focus moves, workspaces and detach. Settings > herdr > herdr Shortcuts lists them all.

herdr redraws a long link, such as an agent's sign-in URL, across several rows of its pane, so a tap used to open only the first row. Now a tap on any row of such a link shows a sheet with the whole link: the site in bold, Open and Copy. Check the site and how the link ends before you open it, because meshTerm has put the link together from the rows. The same works for links drawn across rows in a tmux split. A link that wraps normally in a plain terminal still opens with one tap, as before. The palette's Links list shows the whole link, and the site of each rebuilt link in bold.

Background checks

meshTerm checks each host for herdr once, then once a day on hosts that have it, when you open Agents or Settings > herdr. It only checks hosts whose host key you've already trusted, at most three at a time, and backs off for a week after a sign-in failure. Turn Look for herdr on my hosts off in Settings > herdr to stop all background checks; pull-to-refresh and Set Up herdr still check when you ask.

herdr on Windows 2.3

herdr 0.9.4 or later runs on Windows hosts (x86_64; ARM isn't covered yet). It is the way to keep sessions running on Windows after you disconnect, since tmux and mtRoam need Linux or macOS.

  • Set Up herdr works on Windows. It checks the host and installs herdr's official Windows build with one tap. It needs no admin rights and installs for your account only, into %LOCALAPPDATA%\Programs\Herdr. It needs curl.exe, which current Windows includes. The exact command is shown in the app before it runs.
  • Keep meshTerm open while herdr installs. On Windows the install runs over your connection and stops if the connection drops. Tap Try Again; running it again is safe.
  • Sessions: list, open, end and delete herdr sessions on a Windows host as you do on Linux. meshTerm starts the session's herdr server for you so it keeps running after you disconnect (a standard Windows account can't do that over SSH otherwise). Opening a stopped session from its row starts it.
  • Live status and the dashboard work on Windows. They update every few seconds and need no python3. Dashboard actions work too: tabs, panes, rename, close, and a new tab or workspace.
  • Alerts: turn on Notify for herdr Agents to receive alerts from Claude, Codex, Gemini and other agents herdr recognizes on Windows. See Notifications.
  • Restricted PowerShell: some company policies set PowerShell to Constrained Language Mode. herdr support can't run on such a host, and meshTerm says so. An administrator can allow it, or you can use herdr in a plain terminal.
  • Administrator accounts: a herdr session started from an administrator account only accepts administrator connections (herdr 0.9.4's own rule). Connect with the same kind of account.
Tip: when you sign in with a key, Windows doesn't give the session your saved credentials. Tools that need the Windows Credential Manager, such as git's credential manager or gh, may fail in that session. Signing in with a password avoids it.
herdr is made by a third party and is free and open source. Every herdr feature in meshTerm is free.

Verified with Claude Code, Codex, Gemini (Antigravity) and OpenCode 1.18.34 on herdr 0.9.3. Windows support was verified with herdr 0.9.4 on Windows Server 2025.

Agents run on your own hardware using your own credentials on the host. meshTerm is the interface; the model, its API key, and its access all live on your server.
Agent Mode is included in the free tier with a one-agent limit. meshTerm Pro lifts it to unlimited concurrent agents. Agents in herdr don't count toward it.

8. Containers 2.3

The Containers tab shows and manages the containers on your own servers. It works with Docker, Podman, nerdctl and Apple's container tool (in beta), over the SSH connections you already have. Nothing is installed on the server except the engine itself: meshTerm runs the engine's own commands. If you are new to containers, read Docker 101 first.

Containers is part of meshTerm Pro. Without Pro the tab is a preview: it lists the hosts where an engine was found, by name, and offers the free trial. The hosts need to run Linux or macOS. Windows hosts aren't checked for containers; a list of only Windows hosts says it needs a Linux or Mac host.

The host overview

The tab opens on Containers, an overview with one card for every host that has a container engine. meshTerm checks your saved hosts in the background, and a pull-down checks them again. Each card shows the engine and how many containers run, and says "All containers healthy" or how many need you. Needs Attention lists the containers that need you. A host with no engine says so, and its host screen shows the install lines for its system (see Docker 101).

  • Hide a host from the overview by long-pressing its card (Hide from Containers), or turn off Show in Containers in Edit Host > Containers. Hidden hosts are never checked or connected for containers. Show them again from Settings > Containers > Hidden Hosts.
  • Hosts on another Tailscale profile are grouped apart. Tapping one switches to that profile first, and asks before it would disconnect your live sessions.
  • The Activity tab has a Containers card with the number of hosts, running, stopped and needing attention, from the last check. Tap it to open the tab.
  • In a terminal, Containers in the keyboard palette opens that host's screen.

A host's screen

Tap a card to open the host. At the top are pills for its engines (and, on a Portainer server, its environments), a summary of the host, and tiles for Containers, Images, Volumes, Networks and Disk Usage, with their sizes. Under them are the host's Stacks (Compose projects) and its containers, running first. A Containers | Topology switch changes what the host shows (see Topology). Compact Rows in Settings lists containers as plain rows without the CPU graph.

The + menu has New Container, New Stack, Templates and Add Host. Lists of images, volumes and networks show what uses each one, and removing something that is in use is refused. Prune actions say what they delete before you confirm.

A container

A container's screen shows its status, CPU and memory charts, recent logs and events, and a grid of actions: Logs, start, stop and restart, Shell, Web UI, Redeploy (Pull Latest and Recreate, Recreate, Edit Environment) and Ask Agent. The More menu adds pause, kill, remove and rename. Every action that changes something asks first, and says what will happen.

  • Logs open in a native viewer: follow, filter, errors only, jump to live, share. Open in Terminal runs the engine's own log command in a normal meshTerm session instead. Log Lines in Settings sets how many lines open.
  • Shell opens a terminal session on the host and enters the container.
  • Web UI opens a container's web page in the in-app browser through your SSH connection (the host's SSH server must allow port forwarding; the app offers the fix if it doesn't). A saved login for a container appears after you confirm with Face ID.
  • Pull Latest and Recreate pulls a newer image and recreates the container with the same settings. The old container is kept until the new one runs, and put back if the new one can't be created.

When a host needs setting up

If an engine is installed but meshTerm can't use it yet (not running, or your SSH user can't reach its socket), the host shows Needs Setup with the reason and the steps. Where the fix can work, one tap does it: Run in Terminal opens a terminal on the host, types the command and returns you to the app when it finishes; Copy copies it. meshTerm never runs a root step on its own. For hosts where the SSH user needs sudo, Edit Host > Containers sets the sudo choice (off, passwordless sudo, a saved sudo password, or the SSH password) and tests it before saving. The commands for each problem are in Troubleshooting.

Deploying

  • New Container: pick an image (on the host, popular images, or a Docker Hub search with tags), then ports, volumes, environment variables, restart policy and, where the engine supports it, always-pull. The exact command is previewed before anything runs. Create and Start makes it natively with progress; Run in Terminal types the same command into a terminal on the host.
  • New Stack: write or paste a Compose file in an editor with syntax colours and checks, or point at a git repository. Review shows the file and the host's check before Deploy, and the progress stays on screen if you leave and come back.
  • Stack screen: start, stop, restart, update images, edit the Compose file and environment (with saved versions to restore), view logs, and remove. Remove keeps volumes unless you choose Remove with Volumes. A stack created outside meshTerm can be started, stopped and removed here; updates run in a terminal, and its files are not changed.

Templates

From the + menu, Templates (or Browse Templates on an empty Stacks list) lists ready-made stacks, with Featured, categories, search and Super Stacks that combine several apps. A template is a Compose file plus a settings form. You fill in the form, review the Compose file exactly as it will be written, and deploy. Passwords the template needs are generated when you deploy and kept in the Vault, and the template tells you which one to use at first sign-in. The template list comes from meshdeck.ag-applications.com, is checked against a signature built into the app before use, and a copy is built in, so the list works offline. A deployed stack keeps the version of the template it came from. Deploying runs on your own server.

The Vault

The Vault keeps container secrets on this device. Turn on Keep in Vault for an environment variable (it is on by default for names that look like secrets) and meshTerm stores the value in this device's Keychain, never synced, and sends it to the host only when the container is created or the stack is deployed. Settings > Containers > Vault lists each secret with where it is used. Reveal and Copy are behind Face ID, and a copied value clears from the clipboard after two minutes. You can add, rename, replace and delete secrets, and Copy from a Secret Profile makes copies of a profile's values. Replacing a value takes effect on a container's next redeploy. Container secrets are for stacks you deploy; Secret Profiles are for shells and agents.

Note: a container's environment is visible to anyone who can inspect the container on the host. A value from the Vault becomes an ordinary environment variable there, and meshTerm says so on the review screen.

Topology

Switch a host to Topology for a living map of how its containers, networks and volumes connect, grouped by Stack, Network or Volumes (Group By), with a glow on unhealthy containers and a callout for broken dependencies. Show As switches between Map and List; the list tells you every relationship the map draws, and is the one VoiceOver reads.

Ask an Agent

Open a container and tap Ask Agent to get likely causes, with the evidence for each, and up to three suggested actions (restart, start, pull and recreate, recreate, open logs, open the topology, or edit a setting). Each action opens its normal confirmation; nothing runs by itself.

  • Who answers. By default, Claude Code on that host, started with its tools off, so it can only read the summary and reply. It sends the summary to Anthropic under the Claude account signed in on that host. Or use your own API key in Settings > Containers > Ask an Agent: Anthropic, OpenAI, Google Gemini or another OpenAI-compatible server. The key stays in this device's Keychain, never syncs, and is sent only to the address you saved it for. Plain http works only for an address on your own network or tailnet.
  • What is sent. A consent screen names the agent, the host and the company that runs the model, and lists what goes: the container's state and settings, up to 200 recent log lines, recent events, CPU and memory, its links to other containers, and the host's name. Secrets are masked and a Vault value is replaced by its Vault name. Logs can contain personal data. Nothing is sent until you tap Ask, and Stop Sending to Claude withdraws consent.
  • Dig Deeper starts a chat in Agent Mode with the container's name, image, status and settings, its dependencies and recent events (never its logs or environment). That agent asks before it changes anything.
  • It needs SSH to the host, so it isn't offered for Portainer environments.

Portainer servers

If you already run Portainer, add the server with Add Host in Containers or Settings > Containers > Portainer Servers, using an access token you create in Portainer (My account, then Access tokens). Portainer must use HTTPS (usually port 9443); if its certificate isn't from a public authority, meshTerm shows it and asks you to trust it. Each server gets a card, with its Docker environments as pills, its containers and stacks, and the Web UI for the server's own Docker environment. Shell, Open in Terminal and Ask Agent need SSH, so they aren't offered there. Portainer holds a stack's values, Vault values included, on its server, and the app says so.

iPad

On a regular-width iPad the tab is a split view: the host list in the sidebar and the chosen host in the detail. Opening a container, its logs or a stack stays in the detail, and wide screens (the web page, a Compose file) hide the sidebar until you go back. On iPhone, and on an iPad in a narrow window, it is the same screens in a stack.

Settings > Containers

  • Find Container Hosts Automatically: when off, a host is checked only when you pull to refresh or tap Check This Host.
  • Hidden Hosts, Portainer Servers, Vault and Ask an Agent, as above.
  • Display: Log Lines, Compact Rows, Popular Images (refresh the list) and Templates (refresh the list).
  • Forget Sudo Password lives in Edit Host > Containers, not here, and works without Pro. Vault secrets can be deleted without Pro too.

Container data is removed by Erase This Device, which reports anything it could not remove. The Containers tab contacts Docker Hub only while you browse images or tap Refresh in Settings (Settings > Containers > Display, Popular Images), and the template list only when you open Templates or tap Refresh there.

9. Authentication

Password

Enter the password when adding or editing the host. Passwords are stored in the iOS Keychain.

SSH key

Pick a saved SSH key from the host editor. The private key never leaves your device - meshTerm signs the authentication challenge locally and sends only the public key to the server. See SSH keys.

Tailscale SSH

For servers on your Tailnet with Tailscale SSH enabled, no password or key is required. Tailscale authenticates the connection at the network layer using your device's identity. See the Tailscale Setup Guide.

10. SSH keys

Manage keys in Settings → Hosts & Network → SSH Keys.

Supported key types

  • Ed25519 (recommended default).
  • ECDSA on NIST curves P-256, P-384, P-521.

RSA keys aren't supported in 2.0; the importer will tell you if you paste one.

Generating a new key

  1. Settings → Hosts & Network → Add Key.
  2. Pick a type and enter a label (e.g. "Work iPhone").
  3. Tap Generate. meshTerm creates the key pair, saves the private half in the iOS Keychain, and shows the public key in OpenSSH format.
  4. If you have saved hosts, an Install on a Host section appears immediately. Pick a host, tap Install Key, and meshTerm appends the public key to ~/.ssh/authorized_keys on that server.
Install on a Host uses strict host-key verification. If you haven't already trusted the target host, the section asks you to connect via the terminal first to accept the fingerprint, then return and install.

On a Windows host, Install Key writes to the file the Windows SSH server reads, which is different for administrators. See Windows hosts.

Importing an existing key

  1. Settings → Hosts & Network → Add Key → Import.
  2. Paste the full OpenSSH-format private key (including the BEGIN and END lines).
  3. If the key is passphrase-protected, enter the passphrase. meshTerm decrypts it on import and stores the seed in the Keychain - there's no second prompt at connect time.
  4. Tap Import.

Copying a public key

Tap the copy icon next to a key to copy the OpenSSH public key to your clipboard. Paste it into ~/.ssh/authorized_keys on any server you want passwordless access to.

Deleting a key

Swipe a key left and tap Delete. The private key is permanently removed from the Keychain. Hosts using that key will fail to authenticate until you reassign one.

Where keys live

  • Private keys are stored in the iOS Keychain. By default they are marked WhenUnlockedThisDeviceOnly, so they stay on this device and never reach iCloud. If you turn on iCloud Sync (Settings; off by default; a Pro feature), your secrets migrate to iCloud Keychain, which is end-to-end encrypted, so they become available on your other devices. Tailscale credentials never sync.
  • Public keys are stored alongside the host record for display purposes.

11. Tailscale

meshTerm has a built-in Tailscale networking stack, so no separate Tailscale app is required. Add your Tailnet credentials and meshTerm connects to your devices directly over WireGuard. SSH, SFTP, Roam, and all auxiliary connections route through the encrypted Tailscale tunnel natively.

Routing modes

Each host uses one of two routing modes. Set the default in Settings → Hosts & Network → Tailscale, and override it per host in Edit Host:

  • Built-in (Tailscale) - meshTerm's own in-process Tailscale node. Works alongside any system VPN and needs a Tailscale profile. This is the recommended default, and it does not depend on the Tailscale app being installed.
  • Device network - uses your device's normal networking: it routes via the Tailscale app if that app is running, or connects directly otherwise.

Setting up Tailscale 2.0.2

  1. Tap the globe icon in the host list (or go to Settings → Hosts & Network → Tailscale) and create a profile.
  2. Tap Sign in with Tailscale - a browser sheet opens and you sign in with your Tailscale account (Google, Microsoft, GitHub, Apple…). No keys to generate, nothing to renew. If your tailnet requires device approval, meshTerm waits and connects the moment an admin approves.
  3. That's it. Tap the globe icon to browse your Tailnet and add devices in a tap - once connected, the device list comes straight from your tailnet, no API token required.

Prefer not to sign in through a browser? An auth key works exactly as before. And an optional read-only API token supplements discovery: it lets meshTerm list your devices even when it isn't connected to the tailnet (or when you route through the Tailscale app in Device network mode).

The embedded Tailscale node starts automatically when you open the app. You can see its status (connected, IP addresses, signed-in identity) in Settings → Hosts & Network → Tailscale.

Tailscale SSH

Devices on your Tailnet with Tailscale SSH enabled connect without passwords or keys - Tailscale authenticates the connection at the network layer using your device's identity. Set the host's authentication method to Tailscale SSH in the host editor. Tailscale SSH isn't available on Windows hosts: see Windows hosts.

Auth keys (alternative to sign-in)

If you'd rather not authenticate through a browser - or you're automating setup - the embedded node can join your Tailnet with a Tailscale auth key instead. Generate one at login.tailscale.com → Settings → Keys:

  1. Click Generate auth key.
  2. Enable Reusable so the key survives app restarts.
  3. Optionally enable Ephemeral so the node auto-removes from your Tailnet when meshTerm isn't running.
  4. Copy the key and paste it into Settings → Hosts & Network → Tailscale → Auth Key in meshTerm.

The auth key is stored in the iOS Keychain. meshTerm uses it to join your Tailnet on each launch - no browser login required. Auth-key profiles browse the device list exactly like signed-in ones: connected = no API token needed.

Multiple Tailscale profiles 2.0

meshTerm can hold more than one Tailscale identity - for example a work tailnet and a personal one, or a separate profile per client. Manage them in Settings → Hosts & Network → Tailscale, where each profile carries its own sign-in (or auth key) and optional read-only API token.

  • Add a profile - tap New Tailscale Profile, name it, and sign in with your Tailscale account (or paste an auth key).
  • Switch profiles - open a profile and tap Connect. Only one profile's node is up at a time, so switching brings the previous one down and the chosen one up. The device browser also offers Connect / Disconnect / switch directly, and warns you first if switching would drop live sessions.
  • Browse per tailnet - the device browser shows whichever profile you pick. The connected profile lists devices straight from its tailnet; browsing a profile that isn't connected uses its read-only API token.

Binding a host to a profile

In the host editor you can bind a host to a specific Tailscale profile. When you open that host, meshTerm switches to its bound profile first - so a work host always comes up on the work tailnet and a personal host on the personal one, with no manual switching. Hosts left unbound use whichever profile is the current default.

12. Port forwarding & Tunnels

meshTerm can forward network ports over an SSH connection, the same way ssh -L and ssh -D do on a desktop. Rules are configured per host and managed from the Tunnels screen.

Rule types

  • Local (-L) - binds 127.0.0.1:<port> on your device and forwards each connection to a host:port reachable from the server. Good for reaching a database, an admin panel, or an internal web app that only listens on the server's own network.
  • Dynamic (-D) - runs a SOCKS5 proxy on 127.0.0.1:<port>; point an app at it and its traffic routes out through the host. Remote (-R) forwarding is not supported yet.

Setting up a rule

In Edit Host → Tunnels → Port Forwarding, tap Add Port Forward, choose Local or Dynamic, and set the local port (and, for Local, the destination as seen from the host). Add a label if you like, then toggle it on.

Managing tunnels

Open Tunnels from a host's long-press menu or the terminal's more-menu. Each rule shows a live status: Listening, Not running, or an error. Tunnels start when the session connects.

For a local web forward, tap its row to open the target in meshTerm's built-in browser; the tunnel stays connected while you browse. For a SOCKS proxy, point an app at 127.0.0.1:<port>.

Tunnels are plain-SSH only (not available over the mtRoam/Halo transport), bind loopback only (reachable just by apps on this device), and are active only while the session is connected and the app is in the foreground. Rules are saved per host and travel with iCloud Sync.

13. Keyboard 2.1

The on-screen accessory above the keyboard is a three-page palette (four pages in a tmux session). Swipe left and right to move between the pages, or tap the page control. Each page keeps a different set of tools within thumb reach.

The pages

  • Features - one-tap access to the things you reach for mid-session: the SFTP file browser, buffer and history search, the Snippet Vault, Tunnels, and Agents. The Shell tile 2.3.3 switches the shell of the session you are in (the host's default stays as it is); see Switching one session.
  • Keys - a custom terminal keyboard built from your own key groups: F-keys, navigation, modifiers, and the keys you use most. This is where Ctrl, Esc, Tab, the arrows, and your top row live.
  • Sessions - your live and resumable sessions, for one-tap switching without leaving the terminal.
  • tmux 2.2: a fourth page, marked with the tmux icon, that appears only while a tmux session is attached in control mode. It manages the session's windows and panes; see tmux sessions.

Customize Keyboard

Open Settings → Keyboard → Customize Keyboard to shape the palette to your hands:

  • Top row - reorder the always-visible row of your most-used keys, and move keys to or from a drawer.
  • Key groups - build the Keys page out of named groups of keys, so related keys sit together.
  • Minimized bar - pick which keys appear on the slim bar when the palette is minimized.

Minimizing and dismissing

Minimize the palette to a slim bar at the bottom edge and hand the rest of the screen back to the terminal for reading long output (logs, man pages, build output). Tap the bar to expand it again, or tap a single key on it to send that key.

To put the keyboard away entirely, swipe down on it, or tap the hide button next to Back. Keyboard when a session opens (Settings → Keyboard) sets the state new sessions start in: Minimised, Keyboard or Remember Last.

Left-handed layout

Settings → Keyboard → Left-handed layout mirrors every bottom-edge control to the leading side of the screen, so the palette's chrome sits under your thumb when you drive one-handed from the left.

External keyboards

Connect a Magic Keyboard, Smart Folio, or any Bluetooth keyboard and the on-screen accessory bar hides automatically. Disconnect and it returns. While an external keyboard is attached, the following shortcuts are available:

ShortcutAction
⌘ TNew session
⌘ KClose current session
⌘ 1 - ⌘ 9Jump to tab N
⌘ [ / ⌘ ]Previous / next tab
⌘ FOpen scrollback search

In a tmux session in control mode 2.2, these extra shortcuts work on windows and panes:

ShortcutAction
⌘ ⌥ 1 to ⌘ ⌥ 9Switch to tmux window N
⌘ ⌥ TNew tmux window
⌘ ⌥ [ / ⌘ ⌥ ]Previous / next pane
⌘ DSplit right
⌘ ⇧ DSplit down
⌘ ⇧ ReturnZoom pane
⌘ KClear screen (in place of Close current session)

14. Predictions & history 2.0

Predictive echo overlay

When you're typing at a shell prompt, meshTerm mirrors your keystrokes on screen immediately and then reconciles them with the echo that comes back from the server. On a slow link, typing feels native - you see the letters appear as you type, not after a 200 ms round-trip.

The overlay arms itself when meshTerm sees a shell prompt (recognised by the trailing prompt character: $, #, >, or %) and disarms when an alt-screen TUI like vim, htop, or less takes the screen. On Roam hosts, the daemon also reports the live state of the shell's echo flag so meshTerm knows authoritatively whether predictions are safe.

If a prediction doesn't match what the shell actually echoed, the overlay rolls back automatically - you'll see a brief flicker as the mirrored characters are erased and the real ones drawn.

History browse

Pull up the keyboard's history panel to see the host's recent shell history in a sheet. Search across commands and tap one to send it to the active session - the panel closes and the command runs.

The history is fetched live from the host's own ~/.bash_history or ~/.zsh_history over the SSH connection. Nothing is stored locally; what you see is what the shell actually ran.

Prediction chip strip

As you type, a strip of matching commands from the host's shell history appears above the keyboard. Tap a chip to commit the rest of that command without finishing the keystrokes. The chip strip is purely a fast path on top of the history sheet - it doesn't surface snippets, macros, or anything else.

15. TUI return-to-prompt pill 2.0

When a full-screen terminal app (TUI) like Claude Code or Codex CLI is running, scrolling up to look at earlier output normally means the prompt scrolls off the bottom of the screen. The TUI return-to-prompt pill is a small floating button that surfaces in those situations and jumps you straight back to the live prompt with one tap.

Three styles, picked automatically by what's running:

  • Claude Code - brand-orange pill with a white icon. Sends Ctrl+End to jump back to Claude's live prompt.
  • Codex CLI - white pill with a black icon. Sends Ctrl+T to toggle the Codex transcript pager.
  • Generic TUI - blue pill. Sends Ctrl+End, which works in most alt-screen TUIs and pagers.

Inside tmux (or psmux, on a Windows host), scrolling up puts the session in copy mode, and the pill then takes you out of copy mode and back to the live prompt. It is green, or wears the agent's colours when Claude Code, Codex or Antigravity is running underneath.

Over a Roam (mtRoam) connection the daemon reports the real foreground process running on the host, so detection is exact. For plain SSH hosts, meshTerm falls back to a lightweight heuristic based on the terminal title.

Per-host override

The Back-to-prompt button picker in Edit Host > Shell & Environment changes the behaviour per host:

  • Auto-detect: detect from what is running (default).
  • Claude Code: force the Claude pill on this host even if the title detection fails (some custom zsh prompts overwrite the title).
  • Codex CLI: force the Codex pill.
  • Off: suppress the pill on this host entirely.

The picker also lists a tmux option.

Turning it off everywhere

The Back-to-prompt button toggle in Settings → Terminal turns the pill off across every host. The pill is on by default.

16. Snippet Vault

The Snippet Vault is a searchable library of terminal commands you can send to the active session in one tap. Open it from the terminal toolbar.

Default snippets

meshTerm ships with two folders of pre-loaded snippets:

  • Linux - common admin commands like ls -lah, df -h, ss -tuln, systemctl status.
  • OpenClaw - commands for the OpenClaw toolkit.

Using a snippet

Tap any snippet to send the command text to the terminal. The Vault closes automatically.

Adding snippets

  1. Tap + in the Snippet Vault toolbar.
  2. Enter a title and the command text.
  3. Optionally pick a folder.
  4. Tap Save.

Secret snippets

When adding a snippet, mark it as Secret to back its command text with the iOS Keychain instead of plain storage. Optionally require Face ID, Touch ID, or your device passcode each time the snippet fires - useful for sudo passwords, API tokens, or anything you don't want appearing in a list of commands.

Folders & search

Tap New Folder to organise. The search bar at the top of the Vault searches across titles, command text, and tags.

17. Secret Profiles 2.1

Secret Profiles are a meshTerm Pro feature. Creating and using them requires an active Pro subscription.

A Secret Profile bundles a set of environment variables and keys under one name, so you can hand a whole environment to a session at once. Tap to inject a profile into the session you are already in: its variables and keys reach the running shell invisibly, with nothing typed into the terminal and nothing left on screen afterward. Injection works over plain SSH, mtRoam, and tmux.

When injected values take effect

Injection delivers the values to the shell, which picks them up at its next prompt. That means they apply to the next command you run, not to a command already in progress. Inject only updates a pane sitting at a shell prompt; a full-screen app or an agent in the foreground is skipped.

A running agent has an important limitation: Claude Code, Codex, and Gemini keep the environment they launched with, because a running process's environment cannot be changed from the outside, and injection only lands at a shell prompt. For that reason the Apply to this session button is disabled while an agent is in the foreground. To give an agent new secrets: return to a shell prompt, tap Apply to this session there, then restart or resume the agent session, which relaunches it with the new values already in place so it reads them on start. New sessions always receive the secrets on connect, so this only affects an agent that was already live when you injected.

Like secret snippets and macros, profile values are backed by the iOS Keychain and can be gated by Face ID, Touch ID, or your device passcode. Profiles are handy for giving an agent or a shell its API keys and tokens without those values ever landing in your scrollback.

Manage profiles in Settings → Hosts & Network → Secret Profiles, or open the Secret Profiles tile on the keyboard palette's Features page.

18. Macro bar

The macro bar is a scrollable row of one-tap commands above the keyboard, available in every session. Tap a macro to send its command followed by Return.

Editing macros

Open Settings → Keyboard → Macros:

  • Add a macro - a short label (what shows on the bar) and the command text.
  • Edit by tapping a row.
  • Reorder by dragging.
  • Delete by swiping.
  • Restore defaults to bring back the built-in starter set.

Hiding the macro bar

Settings → Keyboard → Show Macros turns the row off entirely if you'd rather have the screen real estate back.

Secret macros

Like secret snippets, macros can be marked secret and gated by Face ID. Useful for fast-fire credentials without the macro text appearing in the bar.

19. SFTP file browser

The SFTP browser moves files on and off your servers without leaving meshTerm. It runs over the same SSH transport as your terminal sessions - no additional credentials, no third-party cloud.

Opening the browser

  1. From the host detail screen, tap Browse files.
  2. meshTerm opens an SFTP channel over the existing SSH connection and shows the home directory.

Navigating

  • Tap a folder to enter it; tap Back in the navigation bar to go up.
  • Pull down to refresh.
  • The current path is shown in the title bar.

Downloading

  1. Tap a file to download. A progress indicator shows bytes transferred.
  2. When the download completes, the iOS Files share sheet appears - pick iCloud Drive, On My iPhone, or any Files-compatible provider.

Uploading

  1. Tap Upload File in the browser toolbar.
  2. Pick one or more files from the iOS Files sheet.
  3. meshTerm uploads them to the current remote directory.

File names are cleaned on upload 2.2. meshTerm keeps your name as it is (spaces, accents and leading dots included, so a .bashrc stays a dotfile) but removes what breaks paths or common tools:

  • a leading cid:, the prefix Mail gives attachments you share into the app;
  • / and \ (path separators), : (which scp and rsync read as a host name), and control characters;
  • < > " | ? *, which Windows OpenSSH servers reject in file names.

The cid: prefix is dropped, each of the characters becomes an underscore, and leading or trailing spaces are trimmed. A name left empty (or just . or ..) falls back to a timestamped name such as file-20261001-142530.

File operations

Long-press a file or folder for options:

  • Rename - enter a new name.
  • Delete - confirm and the file or folder is removed. Non-empty folders aren't deleted in one pass - empty them first.
  • New Folder (toolbar) - create a directory in the current path.

21. Color modes

Settings → Terminal → Color Mode sets the terminal's look. Alongside full True Color, meshTerm offers retro single-hue modes for a calmer, CRT-style view:

  • True Color - full 24-bit color.
  • Monochrome - a single neutral hue.
  • Green Phosphor, Blue Phosphor, Red Phosphor - classic terminal glows.

The single-hue modes collapse color to one tint but keep diffs legible: additions render bright, removals dim. The change applies instantly to the open terminal.

22. Security & App Lock

Trusted servers (TOFU)

meshTerm uses Trust On First Use for host-key verification. The first time you connect to a host, the app shows the server's host-key fingerprint and asks you to confirm. Subsequent connects check the fingerprint silently. If it changes (server rebuilt, key rotated, or something more sinister), the connection is blocked with a warning.

Manage trusted fingerprints in Settings → Hosts & Network → Trusted servers. Swipe an entry left to delete it. If a server's key legitimately changed, delete the old entry and reconnect to accept the new fingerprint.

App Lock

Settings → Privacy & Security → App Lock requires Face ID, Touch ID, or your device passcode to reopen meshTerm. Pick one of:

  • Off
  • Immediately - lock the moment the app backgrounds.
  • After 30 seconds / 1 minute / 5 minutes - short app switches pass through.

Cold launch always requires unlock if App Lock is on.

App Lock requires a device passcode to be set. If you haven't set one, iOS will ask you to in Settings → Face ID & Passcode first.

Credential storage

Everything sensitive lives in the iOS Keychain:

  • SSH private keys (Ed25519, ECDSA).
  • SSH passwords.
  • Tailscale API tokens.
  • Secret snippets and secret macros.

By default nothing sensitive is written to UserDefaults, the filesystem, or an iCloud device backup in plaintext. If you enable iCloud Sync, secrets sync only through iCloud Keychain, which is end-to-end encrypted.

23. iCloud Sync

iCloud Sync keeps meshTerm consistent across your iPhone and iPad. It is opt-in and off by default - turn it on in Settings → iCloud Sync - and it is a Pro feature.

What syncs

  • Your hosts, host tags, and known-host trust (the fingerprints you have accepted).
  • Your SSH key list, macros, snippets, and Tailscale profile names.
  • Appearance and terminal preferences. Some are kept per device class, so an iPhone and an iPad can differ where that makes sense.

Secrets

Sensitive material - SSH private keys, passwords, and secret snippets and macros - is never placed in the synced records. It rides iCloud Keychain instead, which is end-to-end encrypted, so it reaches your other devices without ever being exposed to iCloud in plaintext. Tailscale credentials (auth keys and API tokens) never sync; each device signs in for itself.

Turning it off

Turning sync off stops further propagation but never deletes anything already on a device. To remove synced data, use the erase options under Settings → Privacy & Security.

24. Settings reference

A quick map of the Settings tab. Since 2.2, Settings is grouped into panes 2.2. Not sure where something lives? Type into the Search field at the top of Settings: a result opens the pane, scrolls to the row and highlights it for a moment. Search also matches the English name of a row when the app is in Spanish.

  • Subscription (top of Settings): current plan and Restore Purchases.
  • Hosts & Network: Tailscale (profiles, sign-in, auth key, API token, routing), SSH Keys (Add Key, copy, delete), Trusted servers (the known host keys) and Secret Profiles.
  • Sessions: Persistence for new hosts (tmux or None) and Forget closed plain-SSH sessions.
  • Terminal: Color Mode, Font Size, Cursor, Cursor Blink, Haptic Feedback, Bell, Predictions, Back-to-prompt button, Mouse Input (Off, Full-screen apps or Always), Cursor Drag Sensitivity, Scrollback.
  • Keyboard: Customize Keyboard, Left-handed layout, Keyboard when a session opens, Tap-for-Keyboard Reminder, Hardware Buttons, Button Size, Show Macros, Macros, Double-Tap Action.
  • Agents: edit diffs, typing (autocorrect and smart punctuation), Claude session age and size warnings, Notifications, and Stop All Agents.
  • herdr 2.2: each host's herdr state (tap one to check it or set it up), Look for herdr on my hosts, herdr first in session lists, Menu tips and Show Menu Tips Again, and Learn: What is herdr?, herdr Shortcuts and herdr.dev. See herdr.
  • Containers 2.3: Find Container Hosts Automatically, Hidden Hosts, Portainer Servers, the Vault, Ask an Agent and Display (Log Lines, Compact Rows, Popular Images, Templates). Containers needs a Linux or macOS host; Windows hosts aren't checked for containers. See Containers. New to containers? See Docker 101.
  • iCloud Sync: Sync with iCloud, Sync secrets, Sync preferences.
  • Privacy & Security: App Lock, Delete from Keychain, Erase This Device, Clear Connection History.
  • General: Appearance, onboarding (Hide Onboarding Cards, Show Welcome Tour), and About (version, Privacy Policy, Terms of Use, Keyboard Guide, Open-Source Licenses, Reset All Settings).
  • Feedback and Feature Requests 2.2: Share This App, Rate on the App Store, Report a Bug, Request a Feature, Questions and Ideas, Write It with an AI Agent, Copy Details and Contact. See Feedback and feature requests.

Renamed in 2.2: Known Hosts is now Trusted servers; Left-Handed Chrome is Left-handed layout; Open Sessions Minimised is Keyboard when a session opens; the TUI pill toggle is Back-to-prompt button; Mouse Input's TUI option is Full-screen apps; and on session lists Kill / Prune is End session. The tmux Status Bar and Claude Fullscreen Mode settings are gone.

25. meshTerm Pro

One host, one live session plus one herdr session, and one agent are free. Pro lifts those limits and adds Containers, Secret Profiles, iCloud Sync and agent Resume. Everything else is free. In detail:

FreePro
Saved hosts1Unlimited
Concurrent sessions1Unlimited
Concurrent agents (Agent Mode)1Unlimited
Concurrent herdr sessions, on top of the session above1Unlimited
herdr agents, tabs and workspaces inside a sessionUnlimitedUnlimited
Hosts running herdr1Unlimited
herdr overview, dashboard, alerts, approvals, plugin, Set Up herdr, Live Activity countYesYes
Containers, Secret Profiles, iCloud Sync, agent ResumeNoYes
Roam, predictive echo, history browse, TUI pill, wedge recoveryYesYes
SSH key auth (Ed25519, ECDSA), key generation / import / installYesYes
Tailscale SSH and Tailnet device browsingYesYes
Snippet Vault (including secret snippets)YesYes
Macro bar (including secret macros)YesYes
SFTP file browserYesYes
Themes, scrollback search, host import/export, tagsYesYes
App LockYesYes

herdr is free on your host: one herdr session at a time, on top of your one live session, with unlimited agents, tabs and workspaces inside it. Pro adds more hosts and parallel sessions. See herdr.

Subscribing

Tap Upgrade in Settings or on the host-limit / session-limit prompt. Pro is available as monthly or annual; the annual plan is the better value. Free trials, when offered, apply on the first qualifying purchase per Apple ID.

Restoring purchases

Tap Restore Purchases in Settings if you reinstall the app or switch devices.

Cancelling

Manage or cancel a subscription via iOS Settings → Apple ID → Subscriptions, or via the Subscriptions row inside the App Store app.

26. Troubleshooting

This section covers the most common problems in brief. For a detailed, symptom-by-symptom guide to getting connected, keys and host keys, tmux, SFTP, agents, notifications, herdr and Containers, with commands for each system, see the Troubleshooting page. New to containers? Start with Docker 101.

Connection

"Could not resolve [hostname]"

  • Check the hostname is spelled correctly.
  • Check your device has a working internet connection.
  • If using a local hostname (e.g. home-server.local), ensure you're on the same network.

"Could not connect"

  • Verify the server is reachable and SSH is running (default port 22).
  • If you're on a local network address, grant meshTerm Local Network permission in iOS Settings → Privacy & Security.
  • Firewalls and NATs can drop idle SSH; set ClientAliveInterval on the server if drops are frequent.

Connection hangs at "Connecting…"

  • Check your network.
  • If connecting via Tailscale, ensure the Tailscale app is open and connected.
  • Try toggling Tailscale off and on.

Authentication

SSH key auth fails silently

  • Confirm the public key is in ~/.ssh/authorized_keys on the server.
  • The ~/.ssh directory needs permissions 700 and ~/.ssh/authorized_keys needs 600.
  • Check sshd_config on the server has PubkeyAuthentication yes.

"Unsupported key type"

meshTerm 2.1 accepts Ed25519 and ECDSA (P-256, P-384, P-521). RSA keys aren't supported. Generate a new Ed25519 key in the app, or convert: ssh-keygen -t ed25519.

tmux

"No session persistence": tmux isn't installed

The host is set to tmux but has no tmux, so the session is a plain shell that ends with the connection. Tap Install tmux on the banner to paste your distro's install command at the prompt, review it, and press Return. Or install tmux yourself, or set the host's Persistence to None to stop the banner.

tmux is too old for control mode

Control mode needs tmux 3.2 or newer. With an older tmux, meshTerm reconnects with the classic tmux attach by itself, so the session still persists, just without native panes and the tmux palette page. Check persistence on the host's Details says so on the tmux row. A newer tmux usually comes from your distro's backports or EPEL, or a static build. After upgrading, tap Check persistence so meshTerm tries control mode again on the next connect.

Control mode misbehaves on one host

Set Edit Host > Session > tmux attach to Legacy. That host then uses a plain tmux client, as before 2.2, while your other hosts keep control mode. Switch back to Control mode any time.

mtRoam

"mtRoam isn't installed on this host."

The host's Persistence is mtRoam, but mtroamd isn't on the host. meshTerm connects through tmux instead and says "mtRoam isn't installed on this host. Using tmux." Tap Switch to tmux to make tmux the host's setting for good, or Install guide to install mtroamd (see Installing mtroamd). If tmux is missing too, the banner offers only the install guide. After a confirmed "not installed", meshTerm keeps using tmux for that host for up to a day; after you install mtroamd, tap Check persistence on the host's Details to use it straight away.

"Connection Failed" on an mtRoam host

mtroamd is installed but meshTerm couldn't reach it. Tap Retry, or Open with tmux instead to open this one connection through tmux without changing the host's setting. Common causes: the daemon isn't running (check with mtroamd doctor, or systemctl --user status mtroamd), or, with the Direct transport, the firewall port isn't open (see Firewall setup under Choosing a transport, or switch to SSH Tunnel).

No Update, Repair or Uninstall button for mtroamd

Those buttons appear only for a copy meshTerm installed in ~/.local/bin. A copy from a package manager (or a source build) shows "Installed by a package manager." instead: update it with the package manager, for example sudo apt upgrade mtroamd. If meshTerm hasn't learned yet who installed the daemon, tap Check persistence on the host's Details first.

Package installed, but the old daemon is still running

The package's automatic migration didn't run for your user (for example you installed as root, or your user session wasn't reachable). Run /usr/bin/mtroamd migrate as your login user; see Switching to a package. Until then, package upgrades don't reach the running daemon.

"Connected via SSH Tunnel"

With the Direct transport, meshTerm couldn't reach the daemon's QUIC port, so it carried the session inside SSH instead. Sessions persist normally. To use Direct, open the daemon's port (see Firewall setup in Edit Host > Connection).

Tailscale

Tailnet device browser is empty or asks for a token

When meshTerm is connected to your tailnet (Built-in mode), the device list comes straight from the tailnet with no API token needed. A read-only API token is only needed to browse while you are not connected (offline, or a profile you haven't signed into). Add one under Settings → Hosts & Network → Tailscale if you want that. See the Tailscale Setup Guide.

"Invalid or expired token."

Tailscale API tokens expire. If you use one, generate a new one at login.tailscale.com and paste it into Settings → Hosts & Network → Tailscale.

Tailnet devices missing from the browser

  • Only authorised devices appear. Check your Tailnet's device-authorisation settings.
  • Confirm the API token was generated for the correct Tailnet.
  • Pull to refresh.

Security warnings

Host key mismatch

The server's host key has changed since you last connected. This can mean a legitimate change (server rebuilt, keys rotated) or something more suspicious. If you're confident the change is legitimate:

  1. Settings → Hosts & Network → Trusted servers.
  2. Find the entry and swipe to delete.
  3. Reconnect; you'll be asked to trust the new fingerprint.

If you're not sure, do not reconnect. Investigate the server directly first.

App Lock

"meshTerm requires a device passcode."

App Lock can't be enabled without a device passcode. Set one in iOS Settings → Face ID & Passcode, then return to meshTerm.

SFTP

"SFTP subsystem not available"

The server doesn't have the SFTP subsystem enabled. In OpenSSH, ensure /etc/ssh/sshd_config contains Subsystem sftp /usr/lib/openssh/sftp-server (the exact path varies by distro) and restart sshd.

Permission denied on rename / delete / mkdir

Your account needs write permission on the target directory. Some SFTP servers reject cross-filesystem renames - keep the target in the same directory.

Purchases

"Purchase could not be verified."

There was a problem verifying with the App Store.

  • Check your internet connection.
  • Try Restore Purchases in Settings.
  • If the issue persists, contact Apple Support via the App Store.

Still stuck?

Ask in our GitHub Discussions, or report a bug from Settings > Feedback and Feature Requests. See Feedback and feature requests.


meshTerm is developed by James Betchley. For support, contact meshterm@gmail.com.

27. Feedback and feature requests 2.2

Settings > Feedback and Feature Requests gathers every way to reach us. The bug, feature and question rows open our public meshterm-feedback repo on GitHub.

  • Share This App and Rate on the App Store.
  • Report a Bug and Request a Feature: open the repo's Issues with the Bug report or Feature request form.
  • Questions and Ideas: opens the repo's Discussions, with Q&A, Ideas and Show and tell.
  • Write It with an AI Agent: shows a ready-made prompt, with your app details, to copy into Claude, ChatGPT, Gemini or another agent. Add what happened in your own words and the agent drafts the issue in the form's fields.
  • Copy Details: copies your app version, iOS version, device, language, Free or Pro, which features are on, and counts such as how many hosts and sessions you have. Never hostnames, usernames, IP addresses, keys or logs. Paste it into the form's App details box; it is laid out so an AI agent can read it too.
  • Contact: email meshterm@gmail.com.

These rows open GitHub, the App Store or Mail; meshTerm sends nothing itself. The repo is public, so leave out hostnames, IP addresses, keys and logs. For anything private, email meshterm@gmail.com. Report a security issue through the repo's security policy, not in a public issue.