Ghostty, tmux, And SSH: A Terminal Workflow That Survives Context Switching

Published · Programming

The worst terminal workflow is not the one with the wrong color theme. It is the one where important work is trapped in a particular set of local windows: one pane has the deployment log, another has the useful SSH connection, and a third contains the half-remembered command that explains what is happening. Close the laptop, lose Wi-Fi, or get pulled into another problem and the state becomes archaeology.

Ghostty, tmux, and SSH make a good combination because they solve different problems. Ghostty renders a pleasant local terminal. SSH reaches a remote machine. tmux keeps a named session alive on the machine where work needs to continue. Once those boundaries are explicit, context switching becomes much less dramatic.

This is not an argument for a twelve-pane command center. It is a small operating model for engineers who regularly move between local code, remote environments, investigations, and normal meetings.

Give each layer one job

The model is simple:

Layer Owns Does not own
Ghostty Text rendering, local windows, keyboard input Durable project or server state
SSH Authentication and transport to a host Session persistence
tmux Long-running shells, logs, and named remote layouts Your Mac's terminal configuration
Git, scripts, and service tooling Repeatable work and system state A particular pane's scrollback

The division is more important than the particular emulator. How To Configure Ghostty For A Productive macOS Development Terminal covers the local layer: clear text, a few useful keys, and no attempt to make the emulator a personal platform. This article is about what happens after you open a terminal and the work must survive interruption.

An SSH session by itself is not durable. If the network drops, the process attached to that pseudo-terminal may stop or become inconveniently detached. A tmux server running on the remote host is durable enough for the ordinary failures that matter: a laptop sleep, a VPN reconnect, an accidental tab close, or switching from a desk setup to a travel laptop.

Make hosts and identities explicit

Start by giving real destinations clear SSH names. Put hostnames, usernames, identity files, and conservative defaults in ~/.ssh/config, rather than reconstructing them from shell history.

Host staging-app
  HostName staging.example.internal
  User deploy
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

Host prod-bastion
  HostName bastion.example.com
  User scott
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes
  ServerAliveInterval 30
  ServerAliveCountMax 3

ServerAliveInterval is not a substitute for tmux; it only helps a quiet connection notice a dead path. The durable unit is still the remote session. Keep the configuration legible enough that a future you can tell which account and key are being used. If different repositories need different identities, Use a Different SSH Identity for One Git Repository follows the same principle: make the rule explicit instead of relying on agent state or luck.

Test the host before you need it:

ssh -G staging-app | rg 'hostname|user|identityfile'
ssh staging-app 'hostname; id; tmux -V'

The first command shows SSH's effective configuration. The second confirms that the account and host are the ones you intended. It is cheap insurance before opening a production-adjacent session.

Name the remote session after the work

When you log in, attach to a session with a useful name. The session name should answer what would be expensive to lose: incident-api, release-2026-08-19, or migration-check, not main or work.

ssh -t staging-app 'tmux new-session -A -s deploy-check'

new-session -A creates the session when it does not exist and attaches when it does. That one command removes a surprising amount of friction. A normal layout can be boring:

# In the remote tmux session.
tmux rename-window deploy
tmux split-window -h
tmux select-pane -t 0

Keep one pane for the command or editor driving the work and one pane for logs, a watcher, or a second read-only view. Add panes only when they have a job. A useful tmux layout is a named reminder of the investigation, not a permanent dashboard.

Use tmux detach deliberately before changing context. Reattach with tmux attach -t deploy-check from any SSH client later. If a session is no longer useful, kill it intentionally: tmux kill-session -t deploy-check. That final act matters: durable state should be recoverable, not immortal.

Keep local work local and remote work remote

It is tempting to run a local tmux session that SSHes into several servers. That can be perfectly reasonable for a local development project, especially when you want stable local editor and test panes. But it does not replace tmux on a remote machine for work that must outlive the laptop.

Use local Ghostty tabs or a local tmux session for:

  • Editing and testing the repository on your Mac.
  • A local development server or test watcher.
  • Brief SSH sessions and normal command-line work.

Use remote tmux for:

  • A remote log tail or operational investigation.
  • A deployment or migration that must remain observable after reconnecting.
  • A long-running diagnostic command whose output you will need later.

Do not use tmux as an excuse to leave unsafe commands unattended. It preserves a terminal session; it does not add approval, rollback, observability, or judgment. For consequential operations, use the deployment tooling, change controls, and explicit checks that belong to the system.

Make reconnection a normal test

A workflow is not resilient because it contains tmux. It is resilient because you have tested the failure path before the failure matters.

Run a short exercise on a non-critical host:

ssh -t staging-app 'tmux new-session -A -s reconnect-test'
# In tmux: start a harmless watcher, then detach with Ctrl-b d.
ssh -t staging-app 'tmux attach -t reconnect-test'

Then close the local terminal and reconnect from a new Ghostty window. Confirm that the session name, working directory, and output are what you expected. If you rely on a jump host, test that too. The least glamorous host in the route is often where terminal compatibility and authentication assumptions show up.

For work that lasts beyond a shell session, prefer the system's real durability boundary. A service belongs in systemd, Kubernetes, a CI job, or the appropriate scheduler. tmux is excellent for an operator's view and an interactive investigation; it is not a production process manager.

Leave breadcrumbs outside scrollback

tmux scrollback is useful but not an incident record. When an investigation produces a decision, a command sequence worth repeating, or a risky assumption, write it down in the ticket, change record, runbook, or repository. A good handoff has enough context that someone does not need your live pane to understand the next action.

At the end of a session, capture three things:

  1. What changed or was observed.
  2. What remains uncertain.
  3. The exact safe next command or verification step.

That practice makes context switching kinder to your teammates as well as to your future self. It also limits the common failure mode where a terminal session is treated as the sole source of truth because it happened to be open during the interesting part.

Build a workflow you can replace

The terminal emulator should be easy to swap. The laptop should be able to sleep. The network should be allowed to fail. Named remote sessions, explicit SSH configuration, repeatable commands, and written breadcrumbs make those ordinary events less expensive.

Ghostty provides the local surface. SSH provides a clear route. tmux provides an interactive remote workspace that survives a disconnect. Give each layer that one job, practice reattaching before you are under pressure, and you will spend far less time reconstructing work from abandoned panes.

For more practical engineering workflow guidance, visit Slaptijack.

Slaptijack's Koding Kraken