tanscp

用 tmux + LaunchAgent + remote-opencode 搭一套常在线 AI 开发环境


最近我一直在反复折腾自己的开发环境。原因很简单:AI 写代码这件事,已经不是“偶尔用一下”了,而是越来越像一种长期工作方式。问题也随之暴露出来——我们手上的设备越来越多,但 AI 的上下文却还是割裂的。

白天在公司电脑上开着终端,晚上回家换到自己的 Mac;出门在外,手边只有手机或 iPad。设备一切换,前面刚铺好的上下文、刚跑到一半的任务、刚调顺手的工作流,往往也跟着断掉。你会发现,真正拖慢效率的,很多时候不是模型不够强,也不是机器不够快,而是这套环境没有连续性。

所以我这段时间重点解决的,不是“再换一个更强的 AI 工具”,而是想办法把开发环境本身做成一个全天候在线、跨设备可调用的基座。我的目标很明确:不管我人在哪里,只要能发出一条指令,就能接上同一台 Mac、同一个终端会话、同一套知识库、同一份上下文。

这篇文章讲的,就是我目前跑得最顺手的一套方案:Ghostty + tmux + remote-opencode + LaunchAgent。它表面上是在解决远程开发问题,实际上解决的是另一件更重要的事:把你的记忆资产固定在一台始终在线的机器上,而不是分散在不同设备里。


1. 桌面端为什么还是主战场

先说一个很现实的判断:移动端很方便,但真正高强度的开发,主战场依然是桌面端。

原因不复杂。桌面端有更完整的终端能力、更稳定的网络环境、更强的本地性能,也更适合长时间盯着复杂上下文工作。尤其是在 AI 参与越来越深的情况下,终端已经不只是“输入命令的地方”了,它更像一个持续运行的协作现场:模型在里面读代码、改代码、跑命令、等待反馈,你在旁边观察、修正、继续推进。

既然桌面端是主战场,那这套环境首先就得满足两个要求:足够快,以及足够稳

1.1 Ghostty:把“卡顿感”从工作流里拿掉

如果你经常让 AI 一口气输出大段代码、日志或者 diff,就会很容易感受到终端性能的差异。很多终端在普通场景下没问题,但一旦输出量上来,滚动、刷新、分屏切换这些动作就开始拖后腿。它不一定会完全卡死,但就是会让你觉得“不跟手”。

我后来换到 Ghostty,最大的感受不是某个参数多强,而是它整体非常顺。它用 Zig 编写,走 GPU 渲染路线,在大段输出场景里依然能保持很好的反馈速度。这个体验放在 AI 工作流里特别重要,因为你几乎一直在和大量文本打交道:代码、日志、终端输出、补丁结果、测试回显,全部都在争夺你的注意力。

当终端本身足够流畅时,你的注意力就会放在“内容是什么”上,而不是“它怎么还没刷出来”。这件事听起来小,但每天高频发生时,差别非常明显。

1.2 tmux:让长任务真正“有地方住”

但只有快还不够。AI 工作流还有另一个典型问题:任务时长不稳定。

有时候它几秒钟就结束,有时候它会在那儿持续跑很久。可能是在改一批文件,可能是在读一堆上下文,可能是在执行一串串联命令。这个时候,如果终端窗口被你顺手关了,或者网络抖了一下,整个过程就断了。

所以我一直认为,AI 时代的终端环境必须配 tmux。它最大的价值不是“酷”,而是给进程一个稳定的落点。

我的日常用法很简单:

这样一来,Ghostty 是前台界面,tmux 才是后台生命线。就算我把窗口关了、机器短暂断开显示、甚至重新连回来,只要 tmux session 还在,整个上下文就还在。对于 AI 长任务来说,这种“会话不跟窗口同生共死”的能力,几乎是基础设施级别的存在。


2. 真正该被保护的,其实是“记忆资产”

很多人会把这类方案理解成“远程控制自己的电脑”。这当然没错,但如果只看到这里,其实还没抓住重点。

这套流程真正要保护的,不是某一个终端窗口,也不是某一个模型会话,而是你长期积累下来的记忆资产

我所谓的记忆资产,包含几层东西:

这些东西一旦固定在某一台机器上,并且不断累积,它就会越来越值钱。相反,如果你在公司一套环境、家里一套环境、手机上又临时切到另一个入口,结果就是上下文四分五裂。每次切换设备,AI 都得重新认识你一次。你看起来是在“随时可用”,实际上是在不断重建现场。

这也是我开始认真看待 remote-opencode 的原因。

它最有意思的地方,不只是把本地 OpenCode CLI 暴露到了远程,而是把“统一入口”这件事做得很顺。你不需要在每台设备上都重新维护一套开发环境,也不需要为了移动端临时换一个完全不同的工作方式。你只要把核心环境放在那台最稳定、性能最强、资料最完整的 Mac 上,然后通过 Discord 这样的入口去调用它就行。

换句话说,手机、iPad、甚至别的临时设备,在这个体系里都不再是“新的工作环境”,而只是“同一套环境的远程入口”。这个思路一旦建立起来,整个工作流会一下子清晰很多。


3. remote-opencode 的价值,不只是“远程”

第一次接触 remote-opencode,很多人都会先被它的形式吸引:原来可以直接在 Discord 里给本地 OpenCode 发指令。

这当然很直观。但我自己真正用下来之后,觉得它最有价值的地方,不是“能发指令”,而是它帮我把不同设备之间那条断裂带给补上了。

以前的情况是这样的:

而现在,Discord 这个聊天窗口本身,就变成了一个轻量控制台。它背后接的不是一个全新的云端环境,而是我自己那套已经养熟了的本地环境。这里的区别非常大。

因为这意味着:

这才是我最看重的地方:不是跨设备都能做事,而是跨设备做的还是同一件事。


4. 一个非常实用的副产物:Obsidian 移动端快速记录

这套流程还有一个我非常喜欢的副产物——它几乎顺手解决了 Obsidian 移动端快速记录 的问题。

只要长期用 Obsidian,你大概率都遇到过类似情况:人在外面,突然冒出一个想法,想赶紧记下来;你掏出手机,点开 Obsidian,等它加载、同步、进入目标笔记,整个过程并不算慢到不能接受,但就是足够打断思路。

问题不在于它不能记,而在于它不够“即刻”。

而有了这套远程流程之后,记录方式会变得非常自然:

  1. 打开手机上的 Discord;
  2. 直接发一句自然语言,比如:

    • “帮我把这条想法存到收件箱:……”
    • “把这件事记到今日日记里:……”
    • “帮我新建一条关于 xxx 的笔记草稿。”
  3. 远端的 OpenCode 接收到消息之后,直接调用本地的 obsidian CLI;
  4. 内容被写入你 Mac 上那份真正的 Vault;
  5. 等你回到电脑前,一切已经在原来的体系里了。

这件事的妙处在于,它没有要求你在移动端重新搭一个“轻量 Obsidian 工作流”,也没有让你去适应另一套工具。你只是换了一个更快的入口,但背后还是同一个知识库。

我现在很喜欢把它理解成一种“闪念胶囊”:你不需要完整进入系统,只需要把想法扔进去,系统会替你准确落到该落的地方。对于高频记录的人来说,这个体验提升非常明显。


5. 落地配置:让这套服务开机就在线

如果这套方案只是“偶尔手动启动一下”,那它的价值会大打折扣。真正好用的状态,应该是你几乎不用去想它,它自己就在那儿稳定运行。

所以接下来这一步很关键:把 remote-opencode 放进 tmux,再交给 macOS 的 LaunchAgent 处理,让它在登录后自动拉起。

5.1 启动脚本:先保证 session 的存在

我习惯先写一个很小的启动脚本,专门干一件事:检查 tmux session 是否已经存在,如果没有,就创建并启动 remote-opencode

路径~/scripts/auto_opencode.sh

#!/bin/bash

# launchd 环境下 PATH 很干净,必须手动补全,不然找不到 node 和全局包
export PATH="/Users/用户名/.npm-global/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"

TMUX_BIN="/opt/homebrew/bin/tmux"
OPENCODE_BIN="/Users/用户名/.npm-global/bin/remote-opencode"

# 检查 session 在不在,不在才启动
$TMUX_BIN has-session -t remote-opencode 2>/dev/null
if [ $? != 0 ]; then
  # 先建一个空 session,再发送启动命令
  # 这样即使启动时报错,也能直接 attach 进去看现场
  $TMUX_BIN new-session -d -s remote-opencode
  sleep 1
  $TMUX_BIN send-keys -t remote-opencode "$OPENCODE_BIN start" C-m
fi

这里有两个细节值得注意。

第一,launchd 运行出来的环境变量非常干净,很多你在交互式 shell 里默认有的 PATH,它其实都不知道,所以这里一定要手动把常用路径补全。

第二,我不建议直接一条命令粗暴启动,而是先建空 session,再 send-keys。因为这样出问题时更容易排查。你只要 tmux attach -t remote-opencode,就能直接看到它到底卡在了哪一步。

脚本写完之后,记得加执行权限:

chmod +x ~/scripts/auto_opencode.sh

5.2 LaunchAgent:交给系统接管启动流程

接下来,用 LaunchAgent 让 macOS 在登录时自动执行这个脚本。

路径~/Library/LaunchAgents/com.用户名.remote-opencode.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.用户名.remote-opencode</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/用户名/scripts/auto_opencode.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <false/>
</dict>
</plist>

配好之后,执行:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.用户名.remote-opencode.plist

以后机器一登录,这套流程就会自动起来。你想确认它是不是正常运行,也很简单,直接:

tmux attach -t remote-opencode

如果看到 session 已经在,说明整个启动链路是通的。


6. 最后一公里:让 Mac 合盖也别睡

到这里,其实整套系统已经差不多成型了。但如果你真想把这台 Mac 当成一台长期在线的“个人开发服务器”,还有最后一个现实问题:合盖休眠

只要系统睡过去了,远程入口再漂亮也没用。所以这一层保障不能省。

6.1 图形化方案:KeepingYouAwake

如果你更喜欢简单稳定的方式,KeepingYouAwake 基本就是最省心的选择。它是个很轻的小工具,放在菜单栏里,点一下就能阻止系统休眠。

比较实用的设置思路是:

这样做的好处是,屏幕可以黑掉,不影响日常放置和省电,但系统本身仍然在线,后台服务也不会中断。

6.2 命令行方案:caffeinate

如果你不想额外装工具,也可以直接用 macOS 自带的 caffeinate

# 在 tmux 里跑这个,系统就不会进入休眠
caffeinate -i remote-opencode start

再激进一点,也可以直接改电源设置:

sudo pmset -a disablesleep 1

不过这个方案更适合你非常清楚自己在做什么的时候再用。毕竟机器长期不睡,散热、电源、摆放环境这些现实问题都要一起考虑。我的建议很简单:如果你是把它当长期在线节点来跑,最好接着电,并放在一个散热条件稳定的位置。


7. 这套方案改变的,不只是“能不能远程”

我后来越来越确定,这套流程真正改变的,不只是我能不能在外面远程给家里的电脑发命令。

它改变的是我对开发环境的理解。

以前我们总把开发环境理解成“我现在手上这台设备上的一堆工具”。但在 AI 时代,这种理解其实已经有点落后了。因为真正持续积累价值的,不再只是编辑器、终端和命令本身,而是那套不断被喂养、不断长上下文、不断沉淀知识的工作现场。

一旦你把这件事想清楚,就会发现最合理的做法不是“每台设备都尽量配齐”,而是固定一台核心机器,让所有设备都去连接它。

这样一来:

这就是我现在最喜欢的部分:设备边界还在,但工作流边界被抹平了。

你在地铁上想到一个点子,掏出手机发出去;回到桌前,打开 Ghostty,attach 回 tmux,刚才那条思路已经接进了原来的任务链。整个过程没有重启上下文,也没有“我刚才到底记到哪儿了”的额外心智负担。

这种感觉一旦用顺,真的很难再回到过去那种每切一次设备就重新来过的状态。


总结

如果只看表面,这篇文章讲的是 tmux + remote-opencode + LaunchAgent 怎么配。

但如果往里看一层,它其实是在回答一个更现实的问题:在 AI 深度参与开发之后,我们该怎么保住自己的上下文连续性。

我的答案就是,把最完整的环境固定在一台长期在线的 Mac 上,用 Ghostty 提供顺滑体验,用 tmux 保住会话,用 remote-opencode 打通远程入口,再用 LaunchAgent 和防休眠方案把它变成真正稳定的底座。

这样做之后,你获得的不是一个花哨的远程控制玩法,而是一套真正能每天使用、能持续积累、能把不同设备重新串成一条线的工作流。

如果你也在折腾多设备协同、远程开发、或者 Obsidian 移动端快速记录,这套思路值得你自己跑一遍。很多体验,光看文字很难完全感受到,真把它搭起来之后,你会更容易理解什么叫“同一套记忆资产,在不同设备上被持续调用”。

当前页面是本站的「Baidu MIP」版。查看和发表评论请点击:完整版 »