11 posts 44 tags 7 domains

tmux na codzień — Claude Code z /remote-control w tle i kilka sprytnych trików

Praktyczny przewodnik po tmux: jak utrzymać sesję Claude Code z /remote-control żywą po wylogowaniu z SSH, plus przydatne wzorce pracy.

Problem

Otwierasz SSH do serwera, odpalasz claude w katalogu projektu, wpisujesz /remote-control i dostajesz URL — od teraz możesz sterować tą sesją z claude.ai/code albo z telefonu. Problem: w momencie kiedy zamkniesz okno terminala albo padnie ci wifi, proces claude ginie razem z SSH, a /remote-control przestaje odpowiadać. Cała pointa się rozsypuje.

tmux rozwiązuje to w jednym ruchu: trzyma proces claude jako swoje child process, niezależnie od tego czy ktoś jest podpięty terminalem. SSH umiera — tmux żyje dalej — /remote-control dalej rejestruje się u Anthropica i odpowiada na komendy z telefonu.

Instalacja i podstawy

bash
$sudo apt install tmux # Debian/Ubuntu/RPi
$sudo dnf install tmux # Fedora

Domyślny prefix to Ctrl+b. W tekście zapisuję go jako C-b. Każdy skrót zaczyna się od prefixu, potem klawisz akcji.

Sesje — najważniejsze

bash
$tmux new -s praca # nowa sesja o nazwie "praca"
$tmux ls # lista sesji
$tmux attach -t praca # wpięcie się w sesję
$tmux kill-session -t praca # ubicie sesji

Skróty w sesji:

  • C-b d — detach (wyjście z sesji, ale sesja działa dalej)
  • C-b s — lista sesji do przełączenia
  • C-b $ — zmiana nazwy sesji

Okna i panele

  • C-b c — nowe okno
  • C-b n / C-b p — następne / poprzednie okno
  • C-b , — zmiana nazwy okna
  • C-b % — podział panelu w pionie
  • C-b " — podział panelu w poziomie
  • C-b ←↑↓→ — przeskok między panelami
  • C-b z — zoom panelu (toggle, fullscreen na jeden panel)
  • C-b x — zamknięcie panelu

Use case: Claude Code z /remote-control chodzący w tle

/remote-control (alias /rc) to mechanizm Claude Code, który zamienia lokalną sesję w endpoint sterowalny z claude.ai/code, aplikacji webowej i mobilnej. Sesja dalej działa lokalnie — pliki, MCP, CLAUDE.md, skille, wszystko zostaje na twojej maszynie. Anthropic to tylko przekaźnik. Wymaga to jednak żeby proces claude żył — a SSH + terminal to słabe gwarancje.

Tmux jest naturalnym kontenerem dla tego workflow.

Flow krok po kroku

bash
$ssh pawel@serwer
$tmux new -s claude
$cd ~/projekty/sklep
$claude

W sesji Claude Code:

text
> /remote-control

Claude wypisuje URL sesji i pokazuje QR. Otwierasz na telefonie albo w przeglądarce na claude.ai/code. Od tego momentu sesja chodzi i nasłuchuje na komendy z dowolnego urządzenia.

Teraz kluczowy ruch — C-b d. Detach. Wracasz do shella SSH, exit, SSH się zamyka. Tmux dalej żyje na serwerze, claude dalej żyje w tmux, /remote-control dalej jest aktywne. Z telefonu wpisujesz prompt i wszystko działa.

Sprawdzenie czy sesja żyje po fakcie

Po pewnym czasie wracasz, chcesz zerknąć w terminal:

bash
$ssh pawel@serwer
$tmux ls
claude: 1 windows (created Mon May 11 14:32:01 2026)
$tmux attach -t claude

Widzisz pełną historię — co Claude napisał, jakie tool calle wykonał, jakie pliki edytował. Możesz pisać dalej z terminala albo zostawić i wrócić do telefonu.

Ograniczenia o których trzeba pamiętać

Kilka rzeczy które wynikają z tego jak działa /remote-control, nie z tmux:

  • Jedna sesja na maszynę. Claude Code nie pozwala na dwa równoczesne /remote-control z tej samej instancji. Jeśli chcesz dwa równolegle (np. backend i frontend), potrzebujesz dwóch oddzielnych okien tmux i każda sesja musi być odpalona z innego katalogu/instancji.
  • Maszyna musi być włączona i online. Tmux nie czyni cudów — jeśli serwer się wyłączy albo straci internet, polling do API zdychzy. Po powrocie połączenia Claude Code próbuje się reconnektować, ale jeśli przerwa była długa, sesja może wymagać restartu.
  • Niektóre komendy są local-only. /mcp, /plugin, /resume — to interaktywne pickery i działają tylko z terminala. Z mobilki/webu działają komendy tekstowe (/compact, /clear, /context itp.).
  • Long-lived tokeny nie działają. Jeśli logujesz się przez CLAUDE_CODE_OAUTH_TOKEN albo claude setup-token, /remote-control odmówi — potrzebujesz pełnego loginu przez claude auth login z kontem claude.ai (Pro/Max).

Auto-enable dla każdej nowej sesji

Jeśli chcesz żeby każda sesja claude startowała od razu jako remote-controllable, bez wpisywania /rc:

text
> /config

Ustaw Enable Remote Control for all sessions na true. Od teraz każde claude w tmux od razu wystawia URL.

Wariant z auto-startem przez systemd

Jeśli serwer ma się resetować (np. po update kernela) i chcesz żeby sesja tmux + Claude Code wstała sama, jednostka user-level systemd:

ini
# ~/.config/systemd/user/claude-tmux.service
[Unit]
Description=Persistent tmux session with Claude Code
After=network-online.target
 
[Service]
Type=forking
ExecStart=/usr/bin/tmux new-session -d -s claude -c %h/projekty/sklep 'claude'
ExecStop=/usr/bin/tmux kill-session -t claude
Restart=on-failure
 
[Install]
WantedBy=default.target

Aktywacja i włączenie linger (żeby user-services chodziły bez zalogowania):

bash
$loginctl enable-linger pawel
$systemctl --user daemon-reload
$systemctl --user enable --now claude-tmux.service

Reboot → tmux wstaje sam → Claude w nim startuje → jeśli masz auto-enable Remote Control, sesja od razu jest dostępna z telefonu. Pierwszy attach: tmux attach -t claude, wpisujesz /rc jeśli auto-enable nie jest włączone i kopiujesz URL.

Konfiguracja .tmux.conf

Minimum, które warto mieć:

ini
# Prefix C-a zamiast C-b (bliżej, mniej kolizji z Vim/Emacs)
unbind C-b
set -g prefix C-a
bind C-a send-prefix
 
# Mysz
set -g mouse on
 
# Większa historia scrollback
set -g history-limit 50000
 
# Numerowanie okien od 1 (klawiatura ma 1 obok 2, nie obok 0)
set -g base-index 1
setw -g pane-base-index 1
 
# Szybki reload configu
bind r source-file ~/.tmux.conf \; display "tmux.conf reloaded"
 
# Intuicyjne podziały — | i -
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
 
# Nawigacja Vim-style
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
 
# 256 kolorów + true color
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",*256col*:Tc"

Po edycji: tmux source-file ~/.tmux.conf albo C-a r (po pierwszym reloadzie).

Inne sprytne use case

Persystentny monitoring serwera

Jedna sesja monitor, w niej cztery panele: htop, tail -f /var/log/nginx/access.log, journalctl -fu mariadb, watch -n 2 'df -h /'. Detach, sesja chodzi w tle. Kiedy klient pisze "coś nie działa", tmux attach -t monitor i widzisz wszystko w 2 sekundy.

Synchronizowane wpisywanie na kilku serwerach

Otwierasz SSH do trzech maszyn, każda w osobnym panelu. Potem:

text
C-a :setw synchronize-panes on

Każdy znak który piszesz idzie do wszystkich paneli jednocześnie. apt update && apt upgrade na trzech serwerach jednym wpisaniem. Wyłączenie: ta sama komenda z off.

Sesja "scratchpad" zawsze dostępna

W ~/.bashrc:

bash
alias t='tmux attach -t scratch 2>/dev/null || tmux new -s scratch'

Komenda t zawsze ląduje cię w tej samej sesji — pusta jeśli nie istniała, z poprzednim stanem jeśli była. Idealne na "muszę szybko coś sprawdzić, ale nie chcę tracić tego co robię".

Logowanie sesji do pliku

C-a : (komenda tmux), potem:

text
pipe-pane -o 'cat >> ~/tmux-#S-#W.log'

Wszystko co leci w panelu jest dopisywane do pliku. Przydatne kiedy robisz coś co potem trzeba udokumentować — albo kiedy podejrzewasz że Claude zrobił coś, co warto zachować poza historią sesji.

Auto-attach przy logowaniu SSH

Dodaj na końcu ~/.bashrc:

bash
if [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" ]]; then
    tmux attach -t main 2>/dev/null || tmux new -s main
fi

Każde SSH ląduje od razu w tmux. Detach przez C-a d zamiast wylogowania — sesja zostaje.

Szybkie kopiowanie do schowka systemowego

Z set -g mouse on zaznaczasz myszką w trybie copy-mode (C-a [). Żeby to wpadało do schowka X11 / Wayland:

ini
# w .tmux.conf, Linux z xclip
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'

Na macOS zamień xclip na pbcopy. Na WSL — clip.exe.

Co się dzieje pod spodem

tmux to klient–serwer. Kiedy odpalasz pierwszą sesję, w tle startuje proces serwera (tmux: server) który trzyma wszystkie sesje, okna i panele jako swoje child procesy. Klient (tmux attach) to tylko UI rysujące to co serwer wysyła przez gniazdo unixowe w /tmp/tmux-$UID/default.

Dlatego detach + exit z SSH nie zabijają niczego po stronie serwera — klient terminala znika, ale claude dalej żyje jako dziecko serwera tmux, który jest dzieckiem systemd --user (po włączeniu lingera) albo po prostu długo żyjącym procesem w sesji użytkownika. Polling do API Anthropica leci dalej, /remote-control dalej odpowiada.

Zabicie serwera tmux (tmux kill-server) albo reboot bez systemd-jednostki ubije wszystko. Lingera + jednostka user-level załatwiają to ostatnie ograniczenie i czynią tmux+Claude+/rc realnie "always-on".