Chạy Claude Code trong terminal tương tác thì ai cũng làm được. Nhưng khi bạn muốn giao agent một task 2 tiếng rồi đi ngủ, hay chạy 3 agent song song trên cùng một VPS, hay tự động hoá nó trong script - lúc đó bạn cần headless mode, tmux và một chút kỷ luật về SSH. Bài này đi từ A tới Z, toàn lệnh thật, copy chạy được.
Headless mode là gì và khi nào dùng
Headless (chế độ không tương tác) là khi bạn chạy Claude Code mà không mở giao diện chat, không ngồi gõ qua lại. Bạn đưa một prompt, agent xử lý, in kết quả ra stdout rồi thoát. Đây là cửa ngõ để tự động hoá: chạy trong cron, trong CI/CD, hoặc pipe dữ liệu vào.
Flag chính là `-p` (alias `--print`):
claude -p "Tìm và sửa bug trong auth.py" --allowedTools "Read,Edit,Bash"
Process chạy một prompt, trả lời, rồi tự thoát với exit code 0 nếu thành công. Vì nó đọc stdin và ghi stdout như mọi lệnh Unix khác, bạn pipe được tự nhiên:
cat build-error.txt | claude -p "giải thích ngắn gọn nguyên nhân gốc của lỗi build này" > ket-qua.txt
Headless với tmux khác gì nhau?
Đây là chỗ nhiều người nhầm. Headless (`-p`) là về việc agent không cần bạn tương tác. tmux là về việc giữ session sống khi SSH đứt. Hai thứ này bù trừ cho nhau:
- Task tự chạy hết, một phát ăn ngay: dùng `claude -p ... > log.txt &` hoặc `nohup`. Không cần tmux nếu bạn không muốn xem live.
- Task dài cần theo dõi/can thiệp giữa chừng: chạy agent tương tác bên trong tmux, detach khi cần rời đi.
- Pattern mạnh nhất: chạy headless bên trong một window tmux. Vừa tự chạy, vừa giữ được session để attach vào xem tiến độ bất cứ lúc nào.
tmux cơ bản: new, attach, detach
tmux (terminal multiplexer) tạo các session terminal chạy trên server, độc lập với kết nối SSH. Cài và nắm 4 lệnh là đủ xài 90% trường hợp:
sudo apt install -y tmux
tmux new -s agent # tạo session tên "agent"
tmux ls # liệt kê các session đang chạy
tmux attach -t agent # gắn lại vào session "agent"
tmux kill-session -t agent # xoá session khi xong
Bên trong tmux, mọi thao tác bắt đầu bằng prefix mặc định là Ctrl+B, nhả ra, rồi nhấn phím lệnh:
| Phím (sau Ctrl+B) | Tác dụng |
|---|---|
| d | Detach - rời session, nó vẫn chạy ngầm |
| c | Tạo window mới (như tab) |
| n / p | Chuyển window kế / trước |
| 0-9 | Nhảy thẳng tới window số đó |
| % | Chia màn hình dọc (pane mới) |
| " | Chia màn hình ngang |
| [ | Bật scroll mode (cuộn xem log cũ, q để thoát) |
Chạy task agent dài bên trong tmux
Quy trình chuẩn cho một task qua đêm:
# 1. SSH vào VPS
ssh coder@IP_VPS
# 2. Tạo session riêng cho task này
tmux new -s refactor
# 3. Vào dự án, giao task
cd ~/du-an
claude
Trong agent, ra task cụ thể: "Refactor toàn bộ service payment sang dùng async, viết test cho từng hàm, chạy test lại, sửa lỗi cho tới khi pass, rồi commit từng phần với message rõ ràng". Khi nó bắt đầu cày, nhấn Ctrl+B rồi D để detach. Thoát SSH, đóng laptop.
Sáng mai attach lại để xem:
ssh coder@IP_VPS
tmux attach -t refactor
Chạy nhiều agent song song
Đây là lúc tmux toả sáng. Một con VPS, nhiều agent làm việc cùng lúc, mỗi cái một window. Trong tmux, nhấn Ctrl+B rồi `c` để tạo window mới cho mỗi agent:
# Window 0: agent refactor backend
cd ~/du-an/backend && claude
# Ctrl+B c -> Window 1: agent viết test frontend
cd ~/du-an/frontend && claude
# Ctrl+B c -> Window 2: agent audit dependency
cd ~/du-an && claude
Chuyển qua lại bằng Ctrl+B rồi số window (0, 1, 2). Mỗi agent có context riêng, làm việc trên thư mục riêng, không giẫm chân nhau. Detach cả session, cả ba vẫn chạy song song.
Về tài nguyên: mỗi agent là một process Node nhẹ vì model chạy trên cloud. Nhưng nếu agent chạy build/test nặng (compile, chạy hàng nghìn test) thì RAM mới là thứ tốn. Hai ba agent build song song nên có ít nhất 4GB RAM. Đây cũng là lý do nhiều người chọn gói vừa thay vì gói thấp nhất khi chạy multi-agent.
Log output ra file để xem lại
Xem trên màn hình tmux là một chuyện, nhưng lưu lại log để soi sau hoặc grep tìm lỗi thì cần ghi ra file. Cách đơn giản nhất với headless:
claude -p "chạy full test suite và tóm tắt các test fail" \
--allowedTools "Bash,Read" 2>&1 | tee ~/logs/test-run-$(date +%F-%H%M).log
`tee` vừa in ra màn hình vừa ghi vào file. `2>&1` gộp cả stderr vào để không sót lỗi. Tên file kèm timestamp để mỗi lần chạy là một log riêng.
Nếu muốn chạy hoàn toàn nền không cần tmux, dùng `nohup`:
nohup claude -p "task của bạn" --allowedTools "Read,Edit,Bash" \
> ~/logs/agent.log 2>&1 &
tail -f ~/logs/agent.log # theo dõi live, Ctrl+C để thoát theo dõi
Cấu hình SSH keep-alive cho ổn định
Dù tmux đã giữ session, bạn vẫn nên cấu hình SSH keep-alive để kết nối tương tác không bị server ngắt khi bạn để yên vài phút. Trên máy laptop của bạn, sửa file `~/.ssh/config`:
Host vps-agent
HostName IP_VPS_CUA_BAN
User coder
Port 22
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
ServerAliveCountMax 3
`ServerAliveInterval 60` gửi gói giữ-kết-nối mỗi 60 giây. Giờ bạn chỉ cần `ssh vps-agent` là vào, không phải gõ IP/user mỗi lần. Đây là khác biệt nhỏ nhưng dùng hằng ngày thì sướng.
tmux hay screen?
| Tiêu chí | tmux | screen |
|---|---|---|
| Chia pane (nhiều ô cùng màn hình) | Linh hoạt, dễ | Có nhưng vụng |
| Cấu hình, scripting | Mạnh, nhiều plugin | Cơ bản |
| Phổ biến trong cộng đồng dev mới | Đang là chuẩn | Cũ, ít người mới dùng |
| Có sẵn trên server cũ | Đôi khi phải cài | Thường có sẵn |
Kết luận thực dụng: dùng tmux. Nó là chuẩn de-facto hiện nay, tài liệu nhiều, và việc chia pane để vừa chạy agent vừa xem log realtime là thứ bạn sẽ làm liên tục. screen chỉ nên dùng khi bạn vào một server cũ chưa có tmux và không tiện cài.
Bảo mật: đừng để lộ API key
Khi chạy agent trên VPS công khai, vài thứ về bảo mật không được bỏ qua. Đây là phần dân vibe coder hay quên nhất.
API key qua biến môi trường, không hardcode
Nếu dùng API key thay vì OAuth, đừng bao giờ viết key thẳng vào script hay file commit. Đặt nó trong file môi trường của user và set quyền chặt:
echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.bashrc
chmod 600 ~/.bashrc
source ~/.bashrc
Firewall và SSH key
Bật ufw, chỉ mở cổng SSH, chặn còn lại:
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status
Và dùng SSH key thay vì mật khẩu để đăng nhập. Tạo key trên laptop (`ssh-keygen -t ed25519`), copy lên VPS (`ssh-copy-id coder@IP`), rồi tắt đăng nhập bằng password trong `/etc/ssh/sshd_config` (`PasswordAuthentication no`). Bước này chặn brute-force vào SSH - thứ xảy ra liên tục với mọi VPS có IP công khai.
Nếu bạn mới bắt đầu và muốn checklist setup VPS bài bản hơn cho việc chạy agent, bên mình có gom lại trong bài tổng VPS cho vibe coder.
Tóm tắt quy trình chuẩn
- SSH vào VPS bằng SSH key (đã cấu hình keep-alive).
- `tmux new -s ten-task` tạo session riêng.
- Chạy agent - tương tác hoặc headless `-p` tuỳ task.
- Ctrl+B rồi D để detach, thoát SSH, đóng máy.
- Quay lại `tmux attach -t ten-task` xem kết quả.
- Log quan trọng ghi ra file bằng `tee` để soi sau.
Có ngần đó là bạn đã có một "agent box" chạy 24/7, ổn định, an toàn, và quản được nhiều agent cùng lúc.
Dựng agent box của riêng bạn trong 60 giây
VPS TND chạy Ubuntu sạch, SSD NVMe Enterprise, RAM ECC, có sẵn IPv4 + IPv6 để bạn SSH vào dựng tmux + Claude Code ngay. Gói 4 vCPU/4GB chạy multi-agent thoải mái chỉ 639k/tháng.

