SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-27

Dùng Claude Code từ điện thoại qua SSH và tmux

Claude Code chạy trong tmux trên VPS, còn điện thoại chỉ mở cửa sổ SSH. Bạn sẽ biết cách dùng SSH keys, mosh khi mạng chập chờn và sửa bàn phím.

Claude Code từ điện thoại: cách hoạt động thực tế

Claude Code từ điện thoại không phải là một ứng dụng mobile. Claude Code chạy trên VPS (virtual private server), bên trong một tmux session luôn mở. Điện thoại mở kết nối SSH (secure shell) đến session đó trong thời gian bạn đang xem. Khi đóng ứng dụng, agent vẫn tiếp tục làm việc vì process chưa từng chạy trên điện thoại.

Đây là toàn bộ thiết kế. Hệ điều hành trên điện thoại sẽ suspend ứng dụng vài giây sau khi bạn chuyển sang ứng dụng khác. Vì vậy, mọi job dài chạy trên điện thoại đều dừng lại. Điện thoại cũng nhận một địa chỉ mạng mới mỗi khi bạn chuyển từ wifi sang mobile data. Cả hai vấn đề đều biến mất khi process chạy trên server và điện thoại chỉ hiển thị màn hình.

Bạn cần 4 thứ trên server: tmux để giữ session, SSH keys để đăng nhập, mosh để xử lý thay đổi mạng và chính Claude Code. Phía điện thoại chỉ cần một ứng dụng terminal có hàng phím mà bạn có thể truy cập.

Những gì cần có trên VPS

Một máy Ubuntu 24.04 cấu hình nhỏ là đủ cho phần SSH và tmux. Claude Code cần nhiều hơn. Theo yêu cầu chính thức tại thời điểm tháng 7 năm 2026, máy chủ phải chạy Ubuntu 20.04 trở lên trên bộ xử lý x64 hoặc ARM64, với ít nhất 4 GB RAM. Gói 1 GB vẫn cài được, nhưng khi có tải, kernel sẽ dừng process này. Claude Code cũng cần tài khoản Claude trả phí (Pro, Max, Team hoặc Enterprise) hoặc tài khoản Console có quyền truy cập API, vì gói Claude.ai miễn phí không bao gồm tính năng này.

Thiết lập máy chủ với một user thông thường có sudo, không dùng root. Nếu máy chủ còn mới, trước tiên hãy làm theo mười phút đầu tiên trên một VPS mới, vì các thay đổi SSH ở phần sau của hướng dẫn sẽ dễ thực hiện hơn khi user và firewall đã tồn tại.

sudo apt update && sudo apt install -y tmux mosh
curl -fsSL https://claude.ai/install.sh | bash
claude --version

Installer đặt binary tại ~/.local/bin/claude, và claude --version in ra một dòng dạng 2.1.211 (Claude Code). Nếu lệnh in ra command not found, thư mục đó chưa có trong PATH của bạn: hãy đăng xuất, đăng nhập lại, rồi kiểm tra bằng command -v claude. claude doctor in ra thông tin chẩn đoán về quá trình cài đặt và settings mà không khởi động session.

Hãy đăng nhập một lần ngay bây giờ từ laptop, trước khi phụ thuộc vào điện thoại. Chạy claude trong một thư mục project và làm theo prompt đăng nhập. Quy trình này yêu cầu bạn mở một URL trong browser rồi nhập code trở lại terminal. Thực hiện việc đó trên màn hình điện thoại bằng cách chuyển qua lại giữa hai app khá chậm. Hãy làm một lần bằng bàn phím thật; credentials sẽ được giữ trên server.

Khởi động Claude Code bên trong tmux để kết nối bị ngắt không thể dừng tiến trình

tmux new -s claude
cd ~/projects/api
claude

Nhấn Ctrl-b để detach, sau đó nhấn d. tmux in [detached (from session claude)] rồi trả bạn về shell. Bây giờ bạn có thể đóng ứng dụng, mất sóng hoặc bỏ điện thoại vào túi. Pane vẫn tiếp tục chạy.

tmux ls
tmux attach -t claude

tmux ls in một dòng cho mỗi session, chẳng hạn như claude: 1 windows (created Thu Jul 30 09:14:02 2026). tmux attach -t claude đưa bạn trở lại đúng vị trí trước đó, bao gồm cả phần chỉnh sửa đang làm dở.

Cách này hoạt động vì tmux chạy một server process riêng. Shell và Claude Code là các process con của server đó, không phải của sshd. Khi kết nối SSH kết thúc, kernel gửi tín hiệu hangup, SIGHUP, đến các process gắn với kết nối đó. tmux server không nằm trong số đó. Nếu không dùng tmux, việc khóa màn hình làm rớt kết nối cũng sẽ dừng Claude Code giữa chừng khi đang gọi tool. Chạy Claude Code trên VPS bên trong tmux trình bày chi tiết hơn về cách bố trí session.

Chạy tmux trên server, không chạy trên điện thoại. Gõ tmux bên trong một session mà bạn đã attach sẽ in sessions should be nested with care, unset $TMUX to force. Nếu ép chạy, bạn sẽ có hai phím prefix tranh nhau.

Tự động attach sau mỗi lần đăng nhập

Gõ lệnh attach bằng bàn phím cảm ứng nhanh chóng trở nên bất tiện. Thêm đoạn này vào cuối ~/.profile trên server:

if command -v tmux >/dev/null 2>&1 && [ -z "$TMUX" ] && [ -t 1 ]; then
  exec tmux new-session -A -s claude
fi

new-session -A -s claude attach vào session có tên claude nếu session đó tồn tại và tạo session nếu chưa có. Vì vậy, một lệnh xử lý được cả hai trường hợp. exec thay shell đăng nhập bằng tmux. Khi thoát tmux, kết nối sẽ đóng thay vì đưa bạn về một prompt trống. Khi cần shell thông thường, hãy bỏ qua file này: ssh you@server -t "bash --noprofile".

Đặt đoạn này trong ~/.profile, không đặt trong ~/.bashrc. ~/.bashrc cũng chạy với các session không tương tác, khiến việc truyền file bị lỗi: scpsftp đọc phần output không mong muốn dưới dạng dữ liệu giao thức rồi fail với Received message too long. ~/.profile chỉ chạy với login shell, đúng với session SSH tương tác.

~/.profile cũng là nơi Ubuntu thêm ~/.local/bin vào PATH. Nếu claude hoạt động ngay sau khi đăng nhập nhưng shell bên trong tmux báo command not found, thứ tự này là nguyên nhân. Khi đó, hãy khởi động tmux từ login shell như trên thay vì từ một script bỏ qua profile.

Cả hai app đều hỗ trợ SSH và mosh, đồng thời lưu key trong app. Điểm khác biệt là giao diện.

Blink Shell hoạt động bằng command. Tại prompt, bạn nhập ssh you@server hoặc mosh you@server, dùng cùng cú pháp như terminal trên desktop. Mở phần cài đặt bằng cách nhập config. Trong mục Keys, app sẽ tạo một cặp key cho bạn.

Termius hoạt động qua form. Bạn điền thông tin host, rồi chuyển host đó từ SSH sang Mosh trong phần chi tiết của host. Termius tích hợp sẵn implementation của mosh và hỗ trợ mosh 1.3.0 trở lên, nên server vẫn cần cài package mosh.

Trong cả hai trường hợp, hãy tạo key ngay trong app và không bao giờ copy private key có sẵn vào điện thoại. App sẽ hiển thị public key. Đây là một dòng duy nhất mà bạn thêm vào ~/.ssh/authorized_keys trên server. Key SSH theo từng thiết bị và cách revoke một key trình bày cách đặt tên và revoke key. Việc này quan trọng với điện thoại hơn laptop.

Hãy bật biometric lock hoặc passcode lock của terminal app. Nếu không, điện thoại đang mở khóa sẽ trở thành một shell mở vào server của bạn trong suốt thời gian màn hình còn sáng.

Android: Termux

pkg upgrade
pkg install openssh mosh
ssh-keygen -t ed25519 -C "pixel"
cat ~/.ssh/id_ed25519.pub

Termux cung cấp OpenSSH và mosh trong repository riêng, nên ssh, ssh-keygenmosh hoạt động giống trên máy tính desktop. Thêm dòng public key đã in vào ~/.ssh/authorized_keys trên server, rồi kết nối bằng mosh you@server.

Bàn phím trên màn hình Android không có phím Esc và Ctrl, trong khi Claude Code cần cả hai. Termux có thể hiển thị một hàng phím riêng. Thêm một dòng vào ~/.termux/termux.properties:

extra-keys = [['ESC','|','/','HOME','UP','END','PGUP'],['TAB','CTRL','ALT','LEFT','DOWN','RIGHT','PGDN']]

Sau đó chạy termux-reload-settings, hàng phím sẽ xuất hiện phía trên bàn phím. Lần reload này cũng nhận font TrueType monospace được đặt tại ~/.termux/font.ttf.

Android có thể dừng Termux khi ứng dụng chạy nền. Trong trường hợp này, bạn chỉ cần kết nối lại. Session và agent vẫn chạy trên server.

Vì sao terminal bị treo khi tôi rời khỏi Wi-Fi, và mosh khắc phục điều gì?

Kết nối SSH là kết nối TCP (transmission control protocol), và một kết nối TCP được xác định bởi cả hai địa chỉ và cả hai cổng. Khi bạn đi ra khỏi vùng phủ Wi-Fi, điện thoại nhận một địa chỉ mới từ mạng di động, nên kết nối cũ không còn khớp ở bất kỳ đầu nào. Không có thông báo nào cho biết điều này. Terminal chỉ ngừng phản hồi cho đến khi TCP timeout, sau đó ssh in ra client_loop: send disconnect: Broken pipe. Để đóng ngay một session bị treo, nhấn Enter, rồi ~, rồi ..

mosh (mobile shell) loại bỏ kiểu lỗi này. Nó dùng SSH một lần để đăng nhập và khởi động tiến trình mosh-server, đọc cổng UDP (user datagram protocol) mà server đã chọn, rồi đóng kết nối SSH. Sau đó, hai đầu trao đổi các UDP datagram được xác thực bằng một session key dùng chung, nên session được xác định bằng key đó thay vì địa chỉ của bạn. Khi địa chỉ thay đổi, session vẫn tiếp tục. mosh cũng echo nội dung bạn gõ ngay trên máy cục bộ và render lại màn hình khi server trả về trạng thái khác, nên terminal vẫn sử dụng được trên kết nối di động chậm.

mosh dùng một cổng UDP trong khoảng từ 60000 đến 61000, vì vậy hãy mở dải cổng này:

sudo ufw allow 60000:61000/udp
sudo ufw status

Mở cổng bằng ufw trình bày phần còn lại của cấu hình firewall. Nếu provider có network firewall riêng trong control panel, hãy thêm cùng dải cổng ở đó, vì rule ufw không thể tác động đến một bộ lọc nằm phía trước máy chủ.

Có 2 lỗi mosh thường gặp. Nếu đăng nhập thành công rồi bị treo và hiển thị Nothing received from server on UDP port 60001., nghĩa là dải UDP bị chặn ở đâu đó giữa điện thoại và server. Nếu kết nối báo không tìm thấy mosh-server, package này bị thiếu trên server hoặc không có trong PATH dùng để đăng nhập. Hãy cài package đó hoặc chỉ định trực tiếp bằng mosh --server=/usr/bin/mosh-server you@server.

mosh cũng từ chối chạy khi locale của phiên đăng nhập không phải UTF-8 và sẽ báo: mosh-server needs a UTF-8 native locale to run. Hãy sửa locale trên server, không phải trên điện thoại.

locale
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=en_US.UTF-8

mosh không thực hiện được 2 việc. README của mosh nêu rõ rằng mosh không hỗ trợ X forwarding hoặc các cách dùng SSH không tương tác, bao gồm port forwarding. Vì vậy, để preview một web app mà Claude Code vừa khởi động, bạn vẫn cần dùng plain ssh -L 8080:127.0.0.1:8080 you@server. mosh cũng chỉ đồng bộ phần màn hình đang hiển thị, nên không có scrollback riêng. Giới hạn thứ hai không gây vấn đề ở đây vì tmux giữ scrollback: Ctrl-b rồi [ để vào copy mode, dùng thao tác kéo hoặc phím mũi tên để cuộn, và q để thoát.

Dùng được màn hình điện thoại

Bốn dòng trong ~/.tmux.conf trên server xử lý hầu hết việc:

set -g mouse on
set -g status-position top
set -g default-terminal "tmux-256color"
set -g history-limit 20000

mouse on biến thao tác kéo bằng cảm ứng thành cuộn và thao tác chạm thành chọn pane hoặc window. Nhờ đó, bạn không phải gõ hầu hết các prefix key vốn khó nhập trên điện thoại. status-position top chuyển dòng trạng thái của tmux khỏi cạnh dưới, nơi bàn phím trên màn hình và thanh gợi ý che mất nó. default-terminal quan trọng vì nếu không, tmux sẽ báo cho Claude Code rằng đây là terminal screen, khiến màu sắc và ký tự vẽ khung hiển thị kém hơn cần thiết. Nếu tmux sau đó không khởi động với missing or unsuitable terminal: tmux-256color, hệ thống đang thiếu mục terminfo: sudo apt install ncurses-term.

Chỉ cần nhớ 4 phím là bạn có thể sử dụng thoải mái.

  • Esc ngắt Claude giữa chừng và giữ lại phần công việc đã hoàn thành. Đây là phím bạn nên đặt gần ngón cái nhất.
  • Ctrl+C cũng ngắt operation đang chạy. Tại prompt đang chờ, lần nhấn đầu tiên xóa nội dung nhập và lần nhấn thứ hai thoát Claude Code, nên đây là công cụ mạnh tay hơn.
  • Nhấn Esc 2 lần để xóa prompt đang soạn. Tại prompt trống, tổ hợp này mở menu rewind.
  • Với prompt nhiều dòng, nhập \ rồi nhấn Enter. Cách này hoạt động trong mọi terminal. Shift+Enter chỉ là chức năng native trong một danh sách ngắn các terminal desktop, và các mobile client không nằm trong danh sách đó.

Tránh dùng split pane. Điện thoại ở chế độ dọc thường rộng khoảng 40 cột, nên một vertical split chỉ còn 20 cột cho mỗi pane và mọi diff đều bị wrap thành nội dung khó đọc. Thay vào đó, hãy dùng window của tmux: Ctrl-b c tạo một window và Ctrl-b n chuyển sang window tiếp theo. Nếu một window thứ hai có session Claude Code riêng, hai session có thể trực tiếp bàn giao công việc cho nhau thay vì bạn phải sao chép văn bản giữa các window trên màn hình cảm ứng. Khi cần đọc diff cho đúng, hãy xoay ngang điện thoại.

Lượng văn bản hiển thị trên màn hình nên được cân nhắc và đặt chủ động, vì style output sẽ chỉnh sửa system prompt phía sau mỗi câu trả lời, còn style ngắn gọn hơn sẽ giúp giảm số màn hình phải cuộn qua trên điện thoại.

Một session dài trên màn hình nhỏ chủ yếu gây khó khăn vì context. Vì vậy, bạn nên đọc cách quản lý context window của Claude Code trước khi thử làm việc cả ngày trên tàu.

Khóa chặt: chỉ dùng key, không dùng password

Điện thoại hiện giữ một key để truy cập vào máy chủ có thể chỉnh sửa code và chạy command của bạn. Hãy tắt xác thực bằng password. Dùng file drop-in an toàn hơn sửa trực tiếp sshd_config, vì sshd_config của Ubuntu include /etc/ssh/sshd_config.d/*.conf ở đầu file và hệ thống dùng giá trị đầu tiên tìm thấy cho một thiết lập.

sudo tee /etc/ssh/sshd_config.d/99-phone.conf >/dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
EOF
sudo sshd -t && sudo systemctl reload ssh

sshd -t phân tích config và không in gì nếu config hợp lệ. Nếu bỏ qua bước này, chỉ một lỗi gõ cũng khiến sshd fail khi reload. Giữ nguyên session đang hoạt động và test từ một kết nối thứ hai trước khi đóng bất cứ thứ gì, vì key sai sẽ khiến bạn nhận Permission denied (publickey).; khi đã tắt password thì không còn phương án dự phòng. Khi đó, cách khôi phục là dùng console của nhà cung cấp. Nếu kết nối test bị fail, hãy kết nối lại bằng ssh -v và xử lý khi session đầu tiên vẫn còn mở, vì một thông báo lỗi đó có thể chỉ ra năm lỗi riêng biệt và output verbose cho biết bạn đang gặp lỗi nào.

Cấp cho mỗi thiết bị một key riêng. Nếu mất điện thoại, bạn chỉ cần xóa một dòng trong ~/.ssh/authorized_keys, còn laptop vẫn hoạt động. Nếu dùng chung một key, bạn phải đổi key trên mọi thiết bị đang sở hữu.

Nếu chuyển SSH sang cổng khác trên Ubuntu 24.04, lưu ý listener thuộc về ssh.socket, nên chỉ thêm một dòng Port sẽ không thay đổi gì. Chạy sudo systemctl edit ssh.socket, xóa giá trị mặc định bằng một ListenStream= rỗng, rồi đặt cổng của bạn ở dòng tiếp theo. Hardening SSH trên VPS trình bày phần này và các bước hardening khác.

fail2ban cho SSH không tăng nhiều mức bảo mật khi đã tắt password, vì password bị đoán không thể được chấp nhận. Tác dụng chính của nó là làm log yên tĩnh hơn, nhờ đó dễ phát hiện một lần đăng nhập thực sự hơn.

Phương án mạnh hơn là không để SSH trên Internet công khai. Đặt máy chủ phía sau WireGuard VPN do bạn tự host, bật tunnel trên điện thoại khi cần, rồi chỉ cấp cho sshd một ListenAddress trên tunnel. mosh hoạt động qua tunnel vì cả hai phía đều dùng UDP. Có một điểm cần lưu ý: tunnel làm tăng overhead của packet, nên nếu các lần truyền dữ liệu lớn bị treo, hãy giảm MTU (maximum transmission unit) trong config WireGuard trên điện thoại.

Một điểm cuối cùng khi làm việc theo cách này. Trên điện thoại, bạn phê duyệt các prompt xin quyền trên màn hình chỉ hiển thị vài dòng diff mỗi lần. Đây là lý do để giữ các guardrail, không phải tắt chúng. Đồng thời, hãy kiểm tra session của bạn khởi động với permission mode nào, vì auto mode sẽ trở thành mặc định của Claude Code vào ngày 14 August 2026 và nó sẽ thực hiện chỉnh sửa file mà không dừng lại để hỏi bạn. Chạy Claude Code an toàn trên VPS trình bày các giới hạn về user và directory nên đặt trước khi touchscreen trở thành cách chính để bạn truy cập hệ thống.

Khi kết nối lại nhưng có vấn đề

tmux attach in ra no server running on /tmp/tmux-1000/default nghĩa là tmux server đã biến mất. Gần như luôn là do máy đã reboot. Kiểm tra bằng uptime. Các bản cập nhật kernel từ cập nhật bảo mật tự động có thể reboot máy. Máy đã reboot sẽ không còn tmux session, vì vậy hãy coi mọi lần chạy Claude Code là một tác vụ có thể khởi động lại.

can't find session: claude khác với trường hợp trên. tmux server vẫn đang chạy nhưng không có session mang tên đó. tmux ls hiển thị các session hiện có.

Nếu bạn attach và thấy một shell prompt thông thường tại vị trí trước đó Claude Code đang chạy, tiến trình đã kết thúc nhưng session vẫn còn. Xem dmesg -T | tail để tìm dòng như Out of memory: Killed process 4821 (claude). Đây là thông báo xuất hiện khi máy có ít hơn 4 GB RAM thực hiện một lần chỉnh sửa lớn. Nếu không có dòng đó, Claude Code đã tự thoát và scrollback của shell phía trên prompt chứa nguyên nhân.

Nếu một window hiển thị lại với kích thước rất nhỏ và có khoảng trống xung quanh, nghĩa là có hai client đang attach với kích thước khác nhau. tmux điều chỉnh kích thước window theo client nhỏ nhất đang attach. Laptop của bạn vẫn giữ session ở độ rộng 200 cột, trong khi điện thoại chỉ yêu cầu 40 cột. Hãy detach các client khác khi attach: tmux attach -d -t claude.

FAQ

Tôi có thể chạy Claude Code ngay trên điện thoại thay vì trên VPS không?

Không. Tính đến July 2026, các nền tảng được hỗ trợ là macOS, Windows, Ubuntu 20.04 trở lên, Debian 10 trở lên và Alpine 3.19 trở lên, với RAM từ 4 GB. Android và iOS không nằm trong danh sách này. Điện thoại cũng đưa ứng dụng vào trạng thái ngủ và liên tục thay đổi địa chỉ mạng, trong khi một agent chạy lâu không chịu được các điều đó. Hãy chạy trên server và dùng điện thoại làm màn hình.

Phiên có tiếp tục chạy nếu tôi đóng app hoặc mất tín hiệu không?

Có. Hai thành phần riêng biệt đảm nhiệm việc này. tmux giữ process chạy trên server, nên process không dừng khi connection kết thúc. mosh giữ chính connection hoạt động khi địa chỉ mạng thay đổi, nên chuyển từ wifi sang mobile data thậm chí không cần reconnect. Nếu dùng SSH thông thường mà không có tmux, connection bị ngắt sẽ gửi SIGHUP và Claude Code dừng giữa chừng.

Vì sao mosh kết nối được rồi không hiển thị gì?

Nếu đăng nhập thành công rồi bị treo với Nothing received from server on UDP port 60001., nghĩa là UDP 60000 đến 61000 chưa được mở. Hãy thêm range này vào ufw, rồi thêm lại trong network firewall của nhà cung cấp. Trên hầu hết panel, đây là một control riêng. Nếu mosh báo không tìm thấy mosh-server, server đang thiếu package: sudo apt install mosh.

Làm cách nào để ngắt Claude Code bằng bàn phím không có phím Esc?

Hãy thêm một hàng phím. Termux cấu hình hàng phím này bằng extra-keys trong ~/.termux/termux.properties. Termius và Blink đều có sẵn một hàng phím mà bạn có thể chỉnh sửa trong settings. Esc ngắt response đang chạy và giữ lại phần công việc đã hoàn thành. Ctrl+C cũng ngắt response, nhưng nếu nhấn 2 lần tại prompt đang idle thì sẽ thoát Claude Code. Vì vậy, trước tiên hãy dùng Esc.

Mở SSH ra Internet có đủ an toàn cho trường hợp này không?

Khi tắt password authentication, credential duy nhất có thể đăng nhập thành công là key không bao giờ rời khỏi các thiết bị của bạn. Đây là mức rủi ro hợp lý đối với một máy có thể rebuild. Hãy cấp cho mỗi thiết bị một key riêng, để khi mất điện thoại, bạn chỉ cần xóa một dòng trong authorized_keys. Nếu không muốn trả lời connection trên một public port, hãy đặt máy phía sau WireGuard và cho sshd listen trên địa chỉ của tunnel.