Khi Claude Code chạy trên server từ xa, hook notify-send hay osascript sẽ chạy trên server, nơi không có desktop nào để hiển thị. Có hai cách hoạt động được. Cách thứ nhất là terminal escape sequence: thông báo có sẵn của Claude Code, hoặc một hook trả về terminalSequence, sẽ truyền ngược qua kết nối SSH và terminal trên máy bạn (Ghostty, Kitty hoặc iTerm2) sẽ hiển thị nó, nhưng chỉ khi bạn đang kết nối và terminal đang mở. Cách thứ hai là push qua mạng từ server tới điện thoại, thông qua ntfy, webhook hoặc Claude Code Notifier, vẫn hoạt động cả khi laptop đã gập lại.
01Vì sao các lệnh thông báo cục bộ không có tác dụng qua SSH
Hook là lệnh mà Claude Code chạy trên chính máy đang chạy Claude Code. Với server truy cập qua SSH, đó là server. notify-send ở đó cần desktop notification daemon, thứ mà hướng dẫn hook của Anthropic lưu ý là server headless và phiên SSH không có. Còn osascript và toast PowerShell thì hoàn toàn không tồn tại.
Vậy câu hỏi không phải là "dùng lệnh thông báo nào", mà là "làm sao để tín hiệu đi từ server tới tôi". Có ba cách:
02Cách 1: thông báo qua terminal SSH
Thông báo có sẵn của Claude Code là một escape sequence được ghi ra terminal. Hướng dẫn terminal của Anthropic cho biết nó truyền về máy bạn qua SSH, nên phiên từ xa vẫn báo được cho bạn. Ghostty và Kitty chuyển nó vào trung tâm thông báo của desktop mà không cần cài đặt gì. iTerm2 cũng vậy sau khi bạn bật: vào Settings > Profiles > Terminal, tick Notification Center Alerts, rồi trong Filter Alerts bật Send escape sequence-generated alerts.
Nếu terminal của bạn không nằm trong số đó, hoặc bạn muốn tự đặt nội dung, một hook có thể trả về escape sequence để Claude Code ghi ra. Hook không có terminal riêng, nên bạn trả nó về trong trường terminalSequence. Lưu đoạn này trên server thành ~/.claude/hooks/notify-ssh.sh:
#!/bin/bash
body=$(jq -r '.message // "Claude Code needs your attention"')
# OSC 9 for iTerm2, WezTerm and ConEmu; use '\033]777;notify;%s;%s\007' for Ghostty
seq=$(printf '\033]9;%s\007' "$body")
jq -nc --arg seq "$seq" '{terminalSequence: $seq}'
Sau đó thêm nó vào ~/.claude/settings.json trên server:
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/notify-ssh.sh" }
]
}
]
}
}
Chạy chmod +x ~/.claude/hooks/notify-ssh.sh và cài jq trên server. Tài liệu tham khảo của Anthropic liệt kê các sequence được chấp nhận: OSC 9 (iTerm2, ConEmu, Windows Terminal, WezTerm), OSC 99 (Kitty), OSC 777 (urxvt, Ghostty, Warp) và bell đơn thuần. Claude Code chỉ ghi sequence trong phiên tương tác khi giao diện của nó đang hiển thị trên màn hình.
Cách này có giới hạn cố hữu. Nếu kết nối SSH bị ngắt, laptop ngủ, hoặc bạn đóng tab, sẽ không có thông báo nào. Nếu bạn chạy Claude Code trong tmux, hãy thêm set -g allow-passthrough on vào ~/.tmux.conf trên server; hướng dẫn tmux có nói về điều này và về các phiên detached.
03Cách 2: push từ server
Push không phụ thuộc vào terminal, nên rất phù hợp với các tác vụ chạy lâu. Hook gửi một request HTTPS từ server, và một dịch vụ chuyển nó tới điện thoại hoặc ứng dụng chat của bạn. Hướng dẫn ntfy và hướng dẫn Telegram, Slack và Discord có sẵn hook chạy được. Chúng báo cho bạn biết có chuyện xảy ra, nhưng không thể duyệt lệnh hay trả lời câu hỏi, nên Claude vẫn phải đợi bạn kết nối lại.
04Cách 3: Claude Code Notifier trên server
Claude Code Notifier là công cụ độc lập (do TouchTap làm, không phải Anthropic). Công cụ dòng lệnh miễn phí của nó, ccn, chạy trên Mac, Windows và Linux, nên bạn cài nó trên server, nơi Claude Code đang chạy:
curl -fsSL https://claudecodenotifier.com/install.sh | sh
Nó thêm các hook của mình vào ~/.claude/settings.json trên server, giữ nguyên phần còn lại và tạo bản sao lưu. Thông báo desktop của ccn hiện trên máy mà ccn đang chạy, mà với server headless thì chẳng hiện ở đâu hữu ích cả. Điện thoại mới là cách hữu ích: thông báo điện thoại đi qua relay server mã hóa của TouchTap, không qua kết nối SSH, nên hoạt động từ bất kỳ máy nào chạy ccn, miễn là máy đó kết nối được internet.
Ghép nối qua SSH
Ghép nối không cần trình duyệt trên server. Bạn có thể chạy ccn pair trong phiên SSH; lệnh này in ra mã QR ngay trong terminal để bạn quét bằng camera điện thoại, kèm một đường link có hiệu lực 24 giờ. Hoặc mở app trên điện thoại, vào Computers > Add a computer, rồi chạy dòng lệnh app hiển thị, vừa cài đặt vừa ghép nối trong một bước:
curl -fsSL https://claudecodenotifier.com/install.sh | sh -s 482913
(Mã sáu chữ số chỉ là ví dụ; hãy dùng mã app của bạn hiển thị.) Một điện thoại có thể có nhiều máy tính, nên cả laptop lẫn server đều có thể gửi thông báo tới nó. Xem hướng dẫn ghép nối để biết chi tiết.
Những gì bạn có thể làm từ điện thoại
Sau khi ghép nối, bạn sẽ nhận push khi Claude làm xong, cần cấp quyền hoặc đặt câu hỏi. Bạn có thể cho phép một lần, cho phép trong cả phiên hoặc từ chối quyền, chọn câu trả lời cho câu hỏi của Claude, và gửi chỉ dẫn tiếp theo khi Claude làm xong. Nếu bạn vắng mặt, terminal sẽ chờ câu trả lời từ điện thoại, tối đa đến mức thời gian bạn chọn, và dừng chờ ngay khi bạn gõ phím. Chạy ccn doctor trên server để kiểm tra hook, thông tin xác thực và kết nối tới relay. Xem bảng giá cho ứng dụng điện thoại; công cụ dòng lệnh thì miễn phí.
05Giữ Claude Code chạy tiếp khi mất kết nối SSH
Cả ba cách đều cần bản thân Claude Code tiếp tục chạy. Nếu bạn chạy claude trực tiếp từ shell SSH và kết nối bị ngắt, phiên làm việc cũng kết thúc theo. Hãy chạy nó bên trong tmux hoặc GNU screen để nó sống sót qua lần mất kết nối, rồi attach lại sau. Hook vẫn tiếp tục chạy trong phiên đã detach, và đây chính là lúc push về điện thoại phát huy tác dụng. Hướng dẫn tmux và rời máy khi chạy tác vụ dài trình bày chi tiết quy trình này.
06Câu hỏi thường gặp
Tại sao notify-send không có tác dụng gì khi tôi dùng Claude Code qua SSH?
Hook chạy trên server, mà server không có daemon thông báo desktop. Hãy dùng escape sequence mà terminal trên máy bạn hiểu được, hoặc dùng một dịch vụ push.
Thông báo có sẵn của Claude Code có hoạt động qua SSH không?
Có, với các terminal hỗ trợ. Tài liệu của Anthropic cho biết thông báo desktop sẽ đến được máy local của bạn qua SSH; Ghostty và Kitty hiển thị mà không cần thiết lập, còn iTerm2 thì cần bật cảnh báo qua escape sequence. Kết nối phải đang mở.
Tôi cài ccn trên laptop hay trên server?
Trên server, vì đó là nơi Claude Code và các hook của nó chạy. Nếu bạn cũng chạy Claude Code trên laptop thì cài thêm ở đó; một điện thoại có thể ghép nối với cả hai.
Tôi có còn nhận được thông báo nếu phiên SSH bị ngắt không?
Chỉ khi có push từ server, và chỉ khi Claude Code vẫn đang chạy, ví dụ bên trong tmux. Escape sequence ngừng hoạt động ngay khi kết nối đóng.
Server có cần mở cổng nào để nhận thông báo trên điện thoại không?
ccn không cần kết nối inbound. Nó chỉ cần truy cập internet outbound để kết nối tới relay server.