The best remote Claude Code w/ cmux + tmux + Tailscale + Echo

4 min read Original article ↗

Hello! This is my favorite Claude Code experience to work locally and have maximum flexibility to remote Claude Code. It uses cmux + tmux + Tailscale + Echo app.

echo app demo

I run Claude Code in cmux on my Mac Studio and control sessions from my iPad or iPhone while on the road over Tailscale using Echo. tmux keeps everything alive between connections.

What you need

All items are free for personal use except Echo app.

Setup

Tailscale

Download and install on both devices, sign in with the same Tailscale account. Note your Mac's Tailscale hostname from the menu bar app. No port forwarding, no firewall rules, no dynamic DNS. Both devices land on the same encrypted private network.

Remote Login

On your Mac, enable this: System Settings > General > Sharing > Remote Login.

Configuration

Three files need changes.

~/.zshrc

Add the following to the bottom of ~/.zshrc. (Open with open ~/.zshrc, edit, save, then run source ~/.zshrc)

# alias to quickly start claude code in cmux with correct workspace naming
ccode() {
  local name="${1:-$(basename $PWD)}"
  local cmd="claude"
  local wants_continue=false
  for arg in "${@:2}"; do
    case "$arg" in
      -c) cmd="claude --continue"; wants_continue=true ;;
      -d) cmd="claude --dangerously-skip-permissions" ;;
      -cd|-dc) cmd="claude --continue --dangerously-skip-permissions"; wants_continue=true ;;
    esac
  done
  if $wants_continue; then
    local project_dir="$HOME/.claude/projects/$(pwd | tr '/' '-')"
    local newest=$(find "$project_dir" -maxdepth 1 -name '*.jsonl' -print 2>/dev/null | head -1)
    if [ -z "$newest" ]; then
      echo "ccode: no sessions to continue in $(pwd)" >&2
      return 1
    fi
  fi

  cmux rename-workspace "$name"
  if tmux has-session -t "$name" 2>/dev/null; then
    tmux attach -t "$name"
  else
    tmux new -s "$name" -c "$PWD" "$cmd"
  fi
}

# Shift+Enter inserts newline instead of executing command
insert-newline() { LBUFFER+=$'\n' }
zle -N insert-newline
bindkey '\e\r' insert-newline

cmux rename-workspace syncs the sidebar name to the tmux session name so everything matches across local and remote. The tmux session wraps Claude Code so it persists between connections - disconnect from Echo and reattach later without losing your place.

The -c and -cd flags include a pre-flight check that verifies a prior session exists before trying to continue. Without this, you get a blank tmux window if there's nothing to continue. The check uses find instead of glob expansion because zsh's NOMATCH behavior breaks ls *.jsonl when no files match.

~/.tmux.conf

set -g status off
set -g allow-passthrough on
set -g mouse on

# Selection highlight - matrix green on black
set -g mode-style "fg=black,bg=#00ff00"

# Mouse release copies to system clipboard and exits copy mode
bind -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "pbcopy"
bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "pbcopy"

allow-passthrough on lets escape sequences pass through tmux to the terminal. This is required for cmux sidebar notifications and other terminal integrations. mouse on gives you scroll-wheel scrollback. The pbcopy bindings send selected text to the macOS clipboard on mouse release so Cmd+V works everywhere.

Ghostty config

~/.config/ghostty/config (cmux reads keybindings from Ghostty's config):

keybind = shift+enter=text:\x1b\x0d

The Ghostty keybind sends an escape sequence for Shift+Enter, and the zsh binding catches it to insert a newline instead of submitting the command.

Workflow

On your Mac in a cmux pane:

ccode                   # session named after the folder
ccode projectName -c    # continue last conversation
ccode projectName -d    # skip permissions
ccode projectName -cd   # continue + skip permissions

Open Echo on your iPhone, SSH to your Mac's Tailscale hostname, then:

tmux ls                 # list active sessions
tmux a -t projectName   # attach to an active session

You're now in Claude Code from your phone - same session, same state, same conversation.

Mosh (optional)

SSH connections can drop when you switch networks or your phone locks. Mosh handles this - it reconnects automatically without losing your session.

Install Mosh on your Mac:

No local install needed. In the Echo app, enable Mosh in your connection settings and it handles the rest.