tmux 설정 가이드

MuxPad는 서버의 tmux를 있는 그대로 SSH 위에 렌더링합니다(100% raw tmux). 그래서 prefix·키 바인딩·상태바가 그대로 유지되며, 접속하려는 원격 서버에는 반드시 tmux가 설치되어 있어야 합니다. 이 가이드에서는 tmux 설치, 선택적인 ~/.tmux.conf 설정 몇 줄, 첫 접속까지 순서대로 안내합니다.

1. 요구 사항

2. tmux 설치

서버의 패키지 매니저로 tmux를 설치한 뒤 버전을 확인하세요.

# Ubuntu / Debian
sudo apt update && sudo apt install -y tmux

# Fedora
sudo dnf install -y tmux

# RHEL / CentOS
sudo yum install -y tmux

# Arch
sudo pacman -S tmux

# Alpine
sudo apk add tmux

# openSUSE
sudo zypper install -y tmux

# macOS (Homebrew)
brew install tmux

# FreeBSD
pkg install tmux

설치 확인:

tmux -V

2-b. 또는 AI에게 맡기기 — 프롬프트 하나로

서버에서 이미 Claude Code(또는 다른 AI CLI)를 쓰고 있다면, 아래 프롬프트 하나만 붙여넣으세요. tmux 설치부터 권장 설정, MuxPad용 Claude Code 알림 훅까지 — 2~4장의 내용을 전부 대신 해줍니다:

MuxPad(iPad/iPhone tmux 터미널 클라이언트)용 서버를 설정해줘. 아래를 전부, 멱등하게, 기존 설정을 깨지 않고 수행해:

1. tmux가 없으면 이 시스템의 패키지 매니저로 설치. `tmux -V`로 확인(3.2+ 권장).
2. ~/.tmux.conf에 다음 줄들이 없으면 추가:
   set -g mouse on
   set -g set-clipboard on
   set -g allow-passthrough all
   set -g history-limit 50000
   set -g allow-rename off
   set -g automatic-rename off
   tmux 서버가 떠 있으면 `tmux source-file ~/.tmux.conf`로 적용.
3. ~/.claude/hooks/muxpad-notify.sh 생성(chmod +x), 내용은 정확히:
   #!/bin/sh
   [ -n "$TMUX_PANE" ] || exit 0
   title="${1:-Claude Code}"; body="${2:-확인이 필요합니다}"
   printf '\ePtmux;\e\e]777;notify;%s;%s\a\e\\' "$title" "$body" \
     > "$(tmux display -p -t "$TMUX_PANE" '#{pane_tty}')"
4. ~/.claude/settings.json에 병합(먼저 백업, 기존 훅·설정 전부 보존):
   - hooks.Notification += 위 스크립트를 본문 "입력을 기다리고 있어요"로 실행
   - hooks.Stop += 위 스크립트를 본문 "작업이 끝났어요"로 실행
5. (선택 — Claude 상태 배지+메시지: 사이드바에 running=프롬프트 앞부분, needs_input=요청 내용, idle=완료 문구 표시. python3 필요) ~/.claude/hooks/muxpad-status.sh 생성(chmod +x), 내용은 정확히:
   #!/bin/sh
   [ -n "$TMUX_PANE" ] || exit 0
   s="${1:-running}"; m=""
   if [ "$s" = auto ]; then
     cur=$(tmux show-options -p -t "$TMUX_PANE" -v @claude_status 2>/dev/null)
     case "$cur" in running|idle) exit 0 ;; esac
     s=running
   fi
   j(){ python3 -c 'import sys,json;print(" ".join(str(json.load(sys.stdin).get(sys.argv[1],"") or "").split())[:120])' "$1" 2>/dev/null; }
   case "$s" in
     running) m=$(j prompt) ;;
     needs_input)
       m=$(j message)
       case "$m" in *"waiting for your input"*) exit 0 ;; esac
       ;;
     idle) m="${2:-🎯 Done}" ;;
   esac
   t=$(tmux display -p -t "$TMUX_PANE" '#{pane_tty}')
   if [ "$s" = off ]; then
     tmux set-option -p -t "$TMUX_PANE" -u @claude_status 2>/dev/null
     tmux set-option -p -t "$TMUX_PANE" -u @claude_message 2>/dev/null
     printf '\ePtmux;\e\e]7777;claude;off;%s\a\e\\' "$TMUX_PANE" > "$t"
     exit 0
   fi
   tmux set-option -p -t "$TMUX_PANE" @claude_status "$s" 2>/dev/null
   if [ -n "$m" ]; then
     b=$(printf %s "$m" | base64 | tr -d '\n')
     tmux set-option -p -t "$TMUX_PANE" @claude_message "$b" 2>/dev/null
     printf '\ePtmux;\e\e]7777;claude;%s;%s;%s\a\e\\' "$s" "$TMUX_PANE" "$b" > "$t"
   else
     printf '\ePtmux;\e\e]7777;claude;%s;%s\a\e\\' "$s" "$TMUX_PANE" > "$t"
   fi
   그다음 ~/.claude/settings.json의 hooks에 이벤트별 상태 토큰으로 병합:
   - UserPromptSubmit += muxpad-status.sh running
   - SessionStart, PreToolUse += muxpad-status.sh auto (조건부 — needs_input 해제·신규 시작만 running으로, idle은 유지)
   - Stop += muxpad-status.sh idle (2번째 인자=완료 문구, 기본 "🎯 Done". SubagentStop은 매핑 금지 — 서브에이전트 종료로 idle 오전환 방지)
   - Notification += muxpad-status.sh needs_input (matcher "permission_prompt" — 권한 요청만. 유휴 리마인더가 idle을 덮지 않게)
   - SessionEnd += muxpad-status.sh off
6. 테스트: 각 스크립트를 테스트 인자로 1회 실행하고, 바꾼 내용 전체 요약을 보여줘.

3. 권장 ~/.tmux.conf 설정

MuxPad는 기존 tmux 설정 그대로 바로 동작합니다. 바인딩이나 prefix를 바꾸지 않습니다. 선택적인 한 줄짜리 설정 몇 개로 기능이 더 열립니다.

set -g mouse on              # 두 손가락 스크롤·pane 선택 (터치)
set -g set-clipboard on      # OSC 52 — tmux 복사를 iOS 클립보드로
set -g allow-passthrough all  # 서버가 기기로 알림을 보낼 수 있게 (OSC 9/777)
set -g history-limit 50000   # ⌘F copy-mode 검색을 위한 스크롤백 확대
set -g allow-rename off      # 프로그램이 탭(윈도우) 이름을 덮어쓰지 못하게
set -g automatic-rename off

tmux를 재시작하지 않고 설정을 다시 불러오기:

tmux source-file ~/.tmux.conf

또는 실행 중인 tmux 안에서 prefix(기본값 Ctrl-b)를 누른 뒤 :를 입력하고 source-file ~/.tmux.conf를 실행합니다.

vim·nvim을 쓴다면 (선택)

터미널에서 vim/nvim을 주로 쓴다면 아래 몇 줄이 편집 체감을 크게 개선합니다.

setw -g mode-keys vi                              # copy-mode를 vi 키로
set -sg escape-time 10                            # Esc 지연 제거 (모드 전환 체감 개선)
set -ga terminal-overrides ",xterm-256color:Tc"  # truecolor(24비트 색)
set -g focus-events on                            # nvim autoread·gitsigns 연동

4. 서버 알림(선택)

set -g allow-passthrough all을 켜면, 서버의 어떤 스크립트든 tmux passthrough로 감싼 OSC 777 notify 시퀀스로 기기에 제목이 있는 알림을 보낼 수 있습니다. 긴 빌드나 원격 AI 작업이 끝났음을 알리기에 좋습니다. 예를 들어 Claude Code 알림 훅에서 이렇게 씁니다.

printf '\ePtmux;\e\e]777;notify;빌드 완료;모든 테스트 통과\a\e\\' \
  > "$(tmux display -p '#{pane_tty}')"

on이 아니라 all을 쓰세요 — on은 화면에 보이는 pane만 통과시키는데, 알림이 필요한 순간은 정확히 다른 화면을 보고 있을 때입니다.

Claude Code 훅 설정

Claude Code가 승인을 기다리거나 작업을 마쳤을 때 알림을 받으려면, 서버에 이 스크립트를 저장하세요(예: ~/.claude/hooks/muxpad-notify.sh, chmod +x):

#!/bin/sh
# tmux(OSC 777)를 통해 MuxPad로 제목 있는 알림을 보냅니다.
[ -n "$TMUX_PANE" ] || exit 0
title="${1:-Claude Code}"; body="${2:-확인이 필요합니다}"
printf '\ePtmux;\e\e]777;notify;%s;%s\a\e\\' "$title" "$body" \
  > "$(tmux display -p -t "$TMUX_PANE" '#{pane_tty}')"

그다음 ~/.claude/settings.json에 등록합니다:

{
  "hooks": {
    "Notification": [{ "hooks": [{ "type": "command",
      "command": "~/.claude/hooks/muxpad-notify.sh 'Claude Code' '입력을 기다리고 있어요'" }] }],
    "Stop": [{ "hooks": [{ "type": "command",
      "command": "~/.claude/hooks/muxpad-notify.sh 'Claude Code' '작업이 끝났어요'" }] }]
  }
}

MuxPad는 터미널 벨에도 알림을 띄우고, 출력이 멈추는 것을 감지해 오래 걸리는 작업이 끝난 것으로 보일 때 알려줍니다. 이 두 가지는 서버 설정 없이 동작합니다.

Claude 상태 배지(선택)

사이드바의 각 Mux 행에 Claude Code 상태를 sparkle 배지로 표시할 수 있습니다 — 작업 중(파랑, 깜빡임)·입력 대기(주황)·유휴(회색). 한 Mux 안 여러 pane에서 Claude를 돌리면 키보드 커서가 있는 활성 pane의 상태를 보여줍니다. 훅을 설치하지 않았거나 Claude를 실행하지 않으면 배지가 나타나지 않습니다(기존 사이드바 그대로). 배지와 함께 호스트 아래에 상태 메시지 한 줄도 표시됩니다 — 작업 중엔 입력한 프롬프트 앞부분, 입력 대기엔 Claude가 요청한 내용, 유휴엔 완료 문구.

설치 방법은 두 가지입니다. ① 가장 쉬운 길은 위 2-b의 설치 프롬프트(또는 앱 첫 화면의 "설치 프롬프트 복사")를 붙여넣는 것입니다 — 이 상태 훅까지 한 번에 설치·등록됩니다. ② 직접 설치하려면 아래를 따르세요.

알림 훅과 별개인 상태 훅 스크립트를 저장하세요(예: ~/.claude/hooks/muxpad-status.sh, chmod +x). 이 스크립트는 알림을 발생시키지 않고, 전용 시퀀스(OSC 7777)와 tmux pane 옵션에만 상태를 기록합니다.

#!/bin/sh
# MuxPad로 Claude 상태·메시지를 방출합니다(전용 OSC 7777 + tmux pane 옵션 — 알림 아님).
# 메시지: running=프롬프트 앞부분, needs_input=요청 내용, idle=완료 문구($2, 기본 "🎯 Done"). python3 필요.
[ -n "$TMUX_PANE" ] || exit 0
s="${1:-running}"; m=""
if [ "$s" = auto ]; then
  cur=$(tmux show-options -p -t "$TMUX_PANE" -v @claude_status 2>/dev/null)
  case "$cur" in running|idle) exit 0 ;; esac
  s=running
fi
j(){ python3 -c 'import sys,json;print(" ".join(str(json.load(sys.stdin).get(sys.argv[1],"") or "").split())[:120])' "$1" 2>/dev/null; }
case "$s" in
  running) m=$(j prompt) ;;
  needs_input)
    m=$(j message)
    case "$m" in *"waiting for your input"*) exit 0 ;; esac
    ;;
  idle) m="${2:-🎯 Done}" ;;
esac
t=$(tmux display -p -t "$TMUX_PANE" '#{pane_tty}')
if [ "$s" = off ]; then
  tmux set-option -p -t "$TMUX_PANE" -u @claude_status 2>/dev/null
  tmux set-option -p -t "$TMUX_PANE" -u @claude_message 2>/dev/null
  printf '\ePtmux;\e\e]7777;claude;off;%s\a\e\\' "$TMUX_PANE" > "$t"
  exit 0
fi
tmux set-option -p -t "$TMUX_PANE" @claude_status "$s" 2>/dev/null
if [ -n "$m" ]; then
  b=$(printf %s "$m" | base64 | tr -d '\n')
  tmux set-option -p -t "$TMUX_PANE" @claude_message "$b" 2>/dev/null
  printf '\ePtmux;\e\e]7777;claude;%s;%s;%s\a\e\\' "$s" "$TMUX_PANE" "$b" > "$t"
else
  printf '\ePtmux;\e\e]7777;claude;%s;%s\a\e\\' "$s" "$TMUX_PANE" > "$t"
fi

그다음 ~/.claude/settings.json의 훅에 이벤트별 상태 토큰으로 등록합니다:

{
  "hooks": {
    "SessionStart":     [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/muxpad-status.sh auto" }] }],
    "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/muxpad-status.sh running" }] }],
    "PreToolUse":       [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/muxpad-status.sh auto" }] }],
    "Stop":             [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/muxpad-status.sh idle" }] }],
    "Notification":     [{ "matcher": "permission_prompt", "hooks": [{ "type": "command", "command": "~/.claude/hooks/muxpad-status.sh needs_input" }] }],
    "SessionEnd":       [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/muxpad-status.sh off" }] }]
  }
}

OSC로 즉시 반영되고, @claude_status pane 옵션 덕분에 재접속하거나 앱을 다시 켜도 몇 초 안에 배지가 복원됩니다. allow-passthrough가 꺼져 있어도 폴링(약 5초)만으로 동작합니다.

5. MuxPad에서 접속하기

MuxPad는 하나의 접속을 Host·User·Mux 세 요소로 나눠 구성합니다.

  1. Host 추가 — 접속 대상(주소와 포트).
  2. User 추가 — 재사용 가능한 자격증명(사용자명과 비밀번호 또는 키). 하나의 User를 여러 Host·Mux에서 공유할 수 있습니다.
  3. Mux 생성 — 호스트와 사용자를 고르고 이름을 지정합니다. Mux 이름이 곧 tmux 세션 이름이 됩니다.
  4. Mux를 탭. MuxPad가 SSH로 접속해 tmux 세션을 자동으로 시작하거나 다시 연결합니다.

접속 시 MuxPad는 tmux를 자동으로 감지합니다. 설치되어 있지 않으면 접속이 차단되고 설치 안내가 표시됩니다. Mux 이름은 tmux 세션 이름과 대응하므로, 서버에 이미 있는 세션과 같은 이름의 Mux를 탭하면 그 세션에 다시 연결됩니다. 앱을 종료해도 세션이 유지되고, iPad에서 쓰던 세션을 iPhone에서 이어서 쓸 수 있는 것도 이 방식 덕분입니다.

6. 문제 해결