我的远程开发组合技:Ghostty + SSH + tmux
- 先说结论
- 这几个工具分别解决什么问题
- 为什么不能只靠 SSH
- tmux 的核心价值:会话和连接解耦
- 我的推荐会话规划
- tmux 里面怎么分屏
- 推荐组合一:Ghostty + SSH + tmux + Codex
- 推荐组合二:tmux + code-server
- 推荐组合三:手机临时接管远程开发机
- 我会这样配置 alias
- 一个更完整的 tmux 配置
- 什么时候用 systemd,什么时候用 tmux
- 常见坑
- 我的最终工作流
最近一直在折腾远程开发机、SSH、Codex、code-server,还有手机上怎么接回开发现场。折腾了一圈之后,我发现真正稳定好用的方案不是某一个工具,而是一套组合技:
Ghostty 负责本地终端体验
SSH 负责连到远程开发机
tmux 负责会话保活和分屏
Codex / code-server / vim / 脚本 跑在 tmux 里面
这套组合的核心目标很简单:网络断了没事,电脑休眠没事,手机切后台也没事,任务继续在服务器上跑,回来还能接着干。
先说结论
如果你只想直接抄作业,我建议这样用:
# 1. 本地 Ghostty 里 SSH 到远程开发机
ssh n37
# 2. 在远程机器上创建一个 tmux 会话
tmux new -s codex
# 3. 在 tmux 里面跑长期任务
codex
临时退出但不结束任务:
Ctrl+b,然后按 d
下次回来:
ssh n37
tmux a -t codex
这就是 80% 的用法。
这几个工具分别解决什么问题
很多人会把终端、Shell、SSH、tmux 混在一起理解,其实它们不是一类东西。
| 工具 | 负责什么 | 一句话理解 |
|---|---|---|
| Ghostty | 本地终端 App | 替代 Terminal / iTerm2,负责显示终端窗口 |
| SSH | 远程连接协议 | 从本地连到远程开发机 |
| Shell | 命令解释器 | bash / zsh / fish,负责执行命令 |
| tmux | 终端会话管理器 | 让远程任务断线不丢,还能分屏和多窗口 |
| Codex / code-server | 具体工作负载 | 真正干活的 AI 编程工具或 Web IDE |
所以它们的关系是:
你的电脑
└── Ghostty
└── ssh n37
└── tmux session
├── pane 1: codex
├── pane 2: git / vim
└── pane 3: server / logs
Ghostty 让本地体验舒服,tmux 让远程现场不丢。
为什么不能只靠 SSH
普通 SSH 有一个问题:它和当前网络连接强绑定。
你直接这样跑:
ssh n37
codex
如果本地网络断了、电脑睡眠了、手机切后台了,这个 SSH 连接就可能断掉。连接一断,里面前台跑的任务也可能一起没了。
这对 AI 编程尤其难受:
- Codex 正在分析代码,突然断了;
- 一个长脚本刚跑到一半,断了;
- 服务日志正在排查,断了;
- 手机上刚连回去,App 被系统杀后台,断了。
所以只靠 SSH 不够。SSH 负责「连上去」,但不负责「现场保活」。
这个活要交给 tmux。
tmux 的核心价值:会话和连接解耦
tmux 最关键的能力是:把终端会话放在服务器上,而不是放在你的 SSH 连接里。
也就是说:
没有 tmux:
本地终端断了 = 远程任务也可能断
有 tmux:
本地终端断了 = 只是你暂时看不见,任务还在远程继续跑
这就是为什么远程开发机上一定要用 tmux。
我的推荐会话规划
我不建议所有东西都塞进一个 tmux session。最好按用途拆开。
tmux new -s codex # AI 编程主会话
tmux new -s dev # 普通开发会话
tmux new -s server # 服务运行和日志
tmux new -s blog # 博客写作/预览
查看当前有哪些会话:
tmux ls
进入某个会话:
tmux a -t codex
杀掉一个会话:
tmux kill-session -t codex
如果只记一条,我建议记这个命名习惯:
tmux new -s <项目名或任务名>
比如:
tmux new -s money-eval
tmux new -s cody
tmux new -s blog
tmux 里面怎么分屏
tmux 的默认前缀键是:
Ctrl+b
先按 Ctrl+b,松开,再按后面的键。
| 操作 | 快捷键 |
|---|---|
| 退出但保留会话 | Ctrl+b 然后 d |
| 新建窗口 | Ctrl+b 然后 c |
| 下一个窗口 | Ctrl+b 然后 n |
| 上一个窗口 | Ctrl+b 然后 p |
| 左右分屏 | Ctrl+b 然后 % |
| 上下分屏 | Ctrl+b 然后 " |
| 切换 pane | Ctrl+b 然后方向键 |
| 关闭当前 pane | 输入 exit |
我比较常用的布局是:
window: codex
左边:codex 主对话
右上:git diff / git status
右下:测试命令 / 日志
这样 AI 改代码、我看 diff、跑测试,三个动作在一个窗口里完成。
推荐组合一:Ghostty + SSH + tmux + Codex
这是我现在最推荐的 AI 编程组合。
ssh n37
tmux new -s codex
codex
如果已经有会话:
tmux a -t codex
退出时不要直接关窗口,先 detach:
Ctrl+b,然后 d
这样 Codex 还在远程机器里。
适合的场景:
- 让 Codex 长时间读代码;
- 让 Codex 改一批文件;
- 本地网络不稳定;
- 在手机上临时接回任务;
- 一边跑测试,一边让 Codex 继续分析。
推荐组合二:tmux + code-server
如果远程机器上跑 code-server,也建议放到 tmux 里:
tmux new -s code-server
code-server --host 0.0.0.0 --port 8080
或者更保守一点,只监听本地地址,然后通过 SSH tunnel 访问:
code-server --host 127.0.0.1 --port 8080
本地开隧道:
ssh -L 8080:127.0.0.1:8080 n37
然后浏览器访问:
http://127.0.0.1:8080
这套方式的好处是:code-server 进程不容易因为 SSH 断开而挂掉。
推荐组合三:手机临时接管远程开发机
手机上操作远程开发机,最怕的不是屏幕小,而是后台被杀、网络切换、连接不稳定。
所以手机端更应该依赖 tmux。
流程是:
手机 SSH App
-> ssh n37
-> tmux a -t codex
手机只是一个临时显示器。真正的工作现场在远程 tmux 里。
这样哪怕手机切后台,回来重新 attach 就行。
我会这样配置 alias
每次敲完整命令有点麻烦,可以在远程机器的 ~/.zshrc 里加几个 alias:
alias t='tmux'
alias tls='tmux ls'
alias ta='tmux a -t'
alias tn='tmux new -s'
alias tk='tmux kill-session -t'
之后就可以这样用:
tn codex
ta codex
tls
如果你经常只用一个主会话,也可以加:
alias tcodex='tmux new -A -s codex'
new -A -s 的意思是:
- 如果
codex会话不存在,就新建; - 如果已经存在,就直接 attach。
以后只要:
tcodex
一个更完整的 tmux 配置
可以在远程机器上创建 ~/.tmux.conf:
# 鼠标支持
set -g mouse on
# 历史滚动行数
set -g history-limit 50000
# 从 1 开始编号,更符合直觉
set -g base-index 1
setw -g pane-base-index 1
# 重新加载配置
bind r source-file ~/.tmux.conf \; display-message "tmux config reloaded"
# 更快的快捷键响应
set -sg escape-time 10
改完之后,在 tmux 里按:
Ctrl+b,然后 r
或者执行:
tmux source-file ~/.tmux.conf
什么时候用 systemd,什么时候用 tmux
有些长期服务,比如正式的后台服务,我不建议只放 tmux 里。
可以这样区分:
| 场景 | 推荐方式 |
|---|---|
| 临时跑 Codex | tmux |
| 临时跑测试脚本 | tmux |
| 临时看日志 | tmux |
| 开发态 code-server | tmux 或 systemd user service |
| 长期稳定服务 | systemd |
| 机器重启后要自动拉起 | systemd |
一句话:
tmux 管开发现场,systemd 管正式服务。
常见坑
1. 直接关终端,不知道任务还在不在
如果你在 tmux 里面,直接关本地终端,远程任务通常还在。
重新连上后:
tmux ls
tmux a -t codex
2. 忘了自己在哪个 session
执行:
echo $TMUX
如果有输出,说明你在 tmux 里面。
也可以:
tmux display-message -p '#S'
查看当前 session 名。
3. 嵌套 tmux
有时候你已经在 tmux 里,又 attach 另一个 tmux,会变得很绕。
可以先看:
echo $TMUX
如果已经在 tmux 里,不要再随便 tmux a,可以新建 window 或 pane。
4. 误把 session 退出了
如果你在 tmux 里面一直输入 exit,直到最后一个 shell 也退出,这个 session 就结束了。
如果只是临时离开,要用:
Ctrl+b,然后 d
不是 exit。
我的最终工作流
现在我的远程开发基本会收敛成这样:
# 本地 Ghostty
ssh n37
# 远程机器
tmux new -A -s codex
# tmux 里面
codex
旁边再开一个 pane:
git status
git diff
再开一个 pane 跑测试或服务:
make test
# 或者
npm run dev
# 或者
go test ./...
然后离开时:
Ctrl+b,然后 d
回来时:
ssh n37
tmux a -t codex
这套组合的好处不是炫技,而是非常朴素:远程开发现场稳定、可恢复、可接管。
对于 AI 编程尤其重要。因为 AI 工具经常需要长时间读项目、改文件、跑命令,不能因为一次网络抖动就前功尽弃。
所以我的建议是:
本地终端体验交给 Ghostty
远程连接交给 SSH
会话保活交给 tmux
长期服务交给 systemd
AI 编程交给 Codex
把每个工具放在它最擅长的位置,这套远程开发流就会稳定很多。