tmux 설정 가이드
MuxPad는 서버의 tmux를 있는 그대로 SSH 위에 렌더링합니다(100% raw tmux). 그래서 prefix·키 바인딩·상태바가 그대로 유지되며, 접속하려는 원격 서버에는 반드시 tmux가 설치되어 있어야 합니다. 이 가이드에서는 tmux 설치, 선택적인 ~/.tmux.conf 설정 몇 줄, 첫 접속까지 순서대로 안내합니다.
1. 요구 사항
- 서버에 tmux 설치. 원격 호스트에 tmux가 설치되어 있어야 합니다(3.2 이상 권장). MuxPad는 접속 시 tmux를 자동으로 감지하며, 설치되어 있지 않으면 접속이 차단되고 설치 안내가 표시됩니다. 로컬 셸 에뮬레이션은 제공하지 않습니다.
- iPadOS / iOS 17 이상의 iPad 또는 iPhone.
- 비밀번호 또는 ed25519/RSA 키로 인증할 수 있는 SSH 접속 계정.
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
set -g mouse on— iPad에서 두 손가락 스크롤과 pane 선택·크기 조절 등 터치 조작을 켭니다. MuxPad는 이 설정이 켜져 있을 때 두 손가락 스크롤을 tmux 마우스 휠로 전달합니다.set -g set-clipboard on— OSC 52를 켜서 tmux copy-mode에서 복사한 텍스트가 iPad·iPhone 클립보드로 들어갑니다.set -g allow-passthrough all— 서버의 스크립트나 훅이 기기로 제목이 있는 알림을 바로 보낼 수 있게 합니다(4번 항목 참고).set -g history-limit 50000— 스크롤백 버퍼를 크게 유지해 ⌘F copy-mode 검색이 더 많은 기록을 다룹니다.set -g allow-rename off/set -g automatic-rename off— 프로그램(Claude Code 등)이 OSC나 실행 명령으로 윈도우 이름을 덮어쓰는 것을 막아 MuxPad 윈도우 목록을 깔끔하게 유지합니다.
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 세 요소로 나눠 구성합니다.
- Host 추가 — 접속 대상(주소와 포트).
- User 추가 — 재사용 가능한 자격증명(사용자명과 비밀번호 또는 키). 하나의 User를 여러 Host·Mux에서 공유할 수 있습니다.
- Mux 생성 — 호스트와 사용자를 고르고 이름을 지정합니다. Mux 이름이 곧 tmux 세션 이름이 됩니다.
- Mux를 탭. MuxPad가 SSH로 접속해 tmux 세션을 자동으로 시작하거나 다시 연결합니다.
접속 시 MuxPad는 tmux를 자동으로 감지합니다. 설치되어 있지 않으면 접속이 차단되고 설치 안내가 표시됩니다. Mux 이름은 tmux 세션 이름과 대응하므로, 서버에 이미 있는 세션과 같은 이름의 Mux를 탭하면 그 세션에 다시 연결됩니다. 앱을 종료해도 세션이 유지되고, iPad에서 쓰던 세션을 iPhone에서 이어서 쓸 수 있는 것도 이 방식 덕분입니다.
6. 문제 해결
- "접속 차단 / tmux 필요" 안내가 나옵니다. 서버에 tmux가 설치되어 있지 않습니다. 2번 항목의 명령으로 설치한 뒤 다시 접속하세요.
- copy-mode에서 복사한 것이 클립보드로 오지 않습니다. OSC 52가 꺼져 있습니다.
~/.tmux.conf에set -g set-clipboard on을 추가하고tmux source-file ~/.tmux.conf로 다시 불러오세요. - 서버 알림이 오지 않습니다. passthrough가 꺼져 있습니다.
set -g allow-passthrough all을 추가해 다시 불러오고, notify 시퀀스가 4번 항목의 tmux passthrough 이스케이프로 감싸져 있는지 확인하세요. - Ctrl-S를 누르면 터미널이 멈춘 것처럼 보입니다. 이는 XOFF 흐름 제어가 터미널 출력을 일시 정지시킨 것이며 오류가 아닙니다.
Ctrl-Q로 재개하거나stty -ixon으로 이 단축키를 비활성화하세요. - 키가 프로그램에 전달되지 않습니다. tmux 키 바인딩과 prefix를 확인하세요. 사용자 지정 prefix나 충돌하는 바인딩이 프로그램에 도달하기 전에 키를 가로챌 수 있습니다. MuxPad는 키를 raw로 그대로 전달하므로 처리 주체는 tmux 자신입니다.