“AI Agent编写代码+人工审阅批准”的Vibe Coding流程,已经逐渐成为了我日常工作流中极其重要的一部分,然而吃饭、睡觉、外出活动的间隙,仍然不可避免地要离开电脑屏幕前。俗话说打工人得休息,但AI Agent却是可以在后台替我们完成工作、推进进度的。如何填补这一空缺,让我们不在屏幕前时也能监控、审阅本地电脑的Agent的工作结果,并进一步发出指令?

在学界业界,为解决这一问题,Claude Code、Codex等都纷纷拥抱命令行(Cli)化,也出现了happy等开源项目为其提供手机端和Web端。但就我的日常工作流而言,审阅代码、文件仍然占一大部分,因此仍然依赖Cursor这样的IDE内置AI Agent。Cursor Cli推出后,通过手机端操控本地PC的Cursor AI Agent成为了可能,本篇文章记录实现这一思路的探索历程。

实现方式(总体架构)

总体架构设计如下:

Windows PC(作为服务器,常开)
  ├─ Tailscale(组网层)
  ├─ OpenSSH Server(接入层)
  └─ WSL → Ubuntu(运行环境层)
       ├─ tmux(会话层)
       └─ Cursor CLI agent(任务执行层)
手机(外出端)
  ├─ Tailscale
  └─ SSH 客户端(Termius)

其中的关键点:

整体数据流如下:

手机)
  └─ 在 Termius 输入命令/问题
      ↓
手机 Tailscale
  └─ 把请求通过私网发回我的电脑
      ↓
电脑 Tailscale
  └─ 收到请求并交给 SSH 服务
      ↓
Windows SSHD
  └─ 建立远程终端会话
      ↓
WSL Ubuntu
  └─ 进入 Linux 运行环境
      ↓
tmux 会话(agent)
  ├─ 接收我在手机输入的内容
  ├─ 在电脑本地执行任务
      ↓
执行结果
  └─ 原路返回手机终端显示

部署流程

1. 本地PC端:配置

  1. 安装Tailscale桌面应用并登录
  2. 安装sshd——OpenSSH服务端(参见教程:开始使用 Windows 版 OpenSSH。若安装太慢,推荐直接下载OpenSSH的Github Releases
  3. 运行OpenSSH服务端:以管理员模式打开powershell运行下列指令:

    Start-Service sshd # 启动服务
    Set-Service -Name sshd -StartupType Automatic # 设置开机自启动
  4. 开放防火墙22端口(Tailscale服务端口):powershell运行下列指令:

    New-NetFirewallRule -Name sshd -DisplayName "OpenSSH Server (sshd)" -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
  5. 安装并配置tmux环境(前置条件:安装wsl、Ubuntu):powershell运行下列指令:

    # 首先需要安装wsl(通过docker)
    wsl --install -d Ubuntu-22.04 # wsl中安装Ubuntu发行版
    wsl -d Ubuntu-22.04 # 运行Ubuntu,并进行注册登录
    sudo apt update # 更新包索引,为安装tmux做准备
    sudo apt install -y tmux # 安装 tmux
    curl https://cursor.com/install -fsS | bash # 在wsl中安装cursor agent
    # 完成上述安装后,开始配置
    tmux new -s agent # 创建长期会话并跑 agent
    agent # 在此会话运行agent,按提示登录cursor账号

2. 手机端:配置

  1. 安装TailscaleApp并登录。此时,两台设备登陆了同一账号,已经能识别到。Tailscale会显示两台设备的ip,需记下【电脑端 Tailscale IP】
  2. 安装TermiusApp并登录。然后在New host中创建新的服务器,填写IP为【电脑端 Tailscale IP】、Username为Windows用户名、Password为Windows登陆密码(若无法登录,换为使用公钥私钥认证的方法)
  3. 完成配置,在Termius可访问终端

实际使用流程

  1. 电脑cursor ide执行某个项目时需要离开电脑、使用手机,则打开Tailscale、powershell,在powershell中执行cd "【项目地址】",然后执行agent打开agent。完成后,可离开电脑。
  2. 打开手机Tailscale确认连接,然后打开Termius连接之前配置好的Host,进入终端执行cd /d "【项目地址】",然后执行agent ls打开agent列表,找到刚刚的agent,然后回车进入
  3. 在终端中使用Agent。如下图:左为手机端界面,右侧为PC powershell界面。

PixPin_2026-04-16_16-45-32.png

体验优化

可见上述流程中,记录【项目地址】、重复输入还是很麻烦。为进一步优化,我们首先在电脑端wsl中新增两个脚本,编辑流程如下:

  1. powershell打开wsl:wsl -d Ubuntu-22.04(其中Ubuntu-22.04为你实际安装的wsl版本)
  2. wsl中创建脚本目录:mkdir -p ~/bin ~/.agent
  3. 使用wsl的nano编辑器,依次写入两个脚本:nano ~/bin/agent-open.shnano ~/bin/agent-attach-last.sh后分别粘贴本文文末附件的附件A和B内容(注意粘贴后需要Ctrl+O保存、回车确定文件名、Ctrl+X退出),然后分别执行chmod +x ~/bin/agent-open.shchmod +x ~/bin/agent-attach-last.sh赋予权限
  4. 修改本地powershell启动脚本,执行:notepad $PROFILE打开启动脚本文件,编辑其内容,在其末尾粘贴本文文末附件的附件C内容

然后,修改手机端Termius设置,在Host的Snippet中添加指令wsl -d Ubuntu-22.04 -- bash -lc "~/bin/agent-attach-last.sh"(只有开通了pro才能使用该功能)

这样一来,使用流程转变为了:

  1. 电脑某个目录启动agent
  2. 手机打开Termius,直接进入对话(开通了pro的前提下);若使用免费版,则输入wsl -d Ubuntu-22.04 -- bash -lc "~/bin/agent-attach-last.sh恢复到上一个agent

Limitation

当前项目架构下,依赖的是本地cursor cli,无法与cursor ide内部的agent相连接。因此:

Cursor社区讨论:Cursor CLI and Editor should sync所言,我们急切希望官方能实现这一功能!

Discussion:从IDE到Cli,谁是AI Agent的未来?

引言中我们提到:近年来,Claude Code、Codex等都纷纷拥抱命令行(Cli),Cursor也顺应此大势推出了Cursor Cli,传统的IDE内置AI Agent似乎不再是主流路径了。究其根本原因:
(1)对于开发者而言,Cli终端交互是比较习惯的模式,且更利于脚本化、自动化
(2)AI Agent的远程操控,确实只有cli能做到

但我们仍看到,作为学生和科研者,在日常学习生活中的AI需求中,与不同类型文件、不同任务交互的需求庞大。我们既需要AI能对Word、Latex、PPT等不同类型的文件进行编辑,还需要其帮助我们展开Vibe Coding。也就是说,在我们这里AI Agent不仅是编码工具,还更多承担Agent助理的功能。

从这一需求出发,目前的IDE内置AI Agent,相比于老式的Web AI交互,确实能更好地满足与文件交互这一功能。对于我们来说,Cli AI Agent则更多用于需要长时间监控的工作(如大模型训练等)和本文所述的“远程操控”场景。

附件

脚本A:agent-open.sh供电脑端调用记录工作目录和会话

#!/usr/bin/env bash
set -euo pipefail
# 严格模式:出错即停,避免写入错误状态

ws="${1:-$PWD}"
# 第1参数是工作目录;没传就用当前目录

if [ ! -d "$ws" ]; then
  echo "Workspace not found: $ws" >&2
  exit 1
fi
# 目录存在性校验,避免记录失效路径

make_session_name() {
  local p="$1"
  local base hash
  base="$(basename "$p" | tr -cs '[:alnum:]' '_' | sed 's/^_*\|_*$//g')"
  [ -z "$base" ] && base="ws"
  if command -v sha1sum >/dev/null 2>&1; then
    hash="$(printf '%s' "$p" | sha1sum | cut -c1-8)"
  else
    hash="$(printf '%s' "$p" | shasum | cut -c1-8)"
  fi
  printf '%s_%s' "$base" "$hash"
}
# 会话名生成规则:
# 1) basename 清洗(避免非法字符)
# 2) 空名回退到 ws(兼容中文目录)
# 3) 追加路径哈希(避免同名目录冲突)

name="${2:-$(make_session_name "$ws")}"
# 第2参数是会话名;没传则自动生成稳定会话名

mkdir -p ~/.agent
echo "$ws" > ~/.agent/last_workspace
echo "$name" > ~/.agent/last_session
# 记录最近工作目录/会话(给手机自动恢复)

cmd="agent --workspace $(printf '%q' "$ws") --continue"
# 显式绑定 workspace,避免在错误目录续会话

if ! tmux has-session -t "$name" 2>/dev/null; then
  tmux new-session -d -s "$name" -c "$ws" "$cmd"
fi
# 会话不存在时:后台创建并在该目录启动 agent

exec tmux attach -t "$name"
# 最后附着到该会话

脚本B:agent-attach-last.sh供手机端调用连接后自动恢复工作目录

#!/usr/bin/env bash
set -euo pipefail
# 严格模式

make_session_name() {
  local p="$1"
  local base hash
  base="$(basename "$p" | tr -cs '[:alnum:]' '_' | sed 's/^_*\|_*$//g')"
  [ -z "$base" ] && base="ws"
  if command -v sha1sum >/dev/null 2>&1; then
    hash="$(printf '%s' "$p" | sha1sum | cut -c1-8)"
  else
    hash="$(printf '%s' "$p" | shasum | cut -c1-8)"
  fi
  printf '%s_%s' "$base" "$hash"
}

sess="$(cat ~/.agent/last_session 2>/dev/null || true)"
ws="$(cat ~/.agent/last_workspace 2>/dev/null || true)"
# 最近会话名、最近目录(没有就为空)

if [ -n "$sess" ] && tmux has-session -t "$sess" 2>/dev/null; then
  exec tmux attach -t "$sess"
fi
# 会话还在:直接附着

if [ -n "$ws" ]; then
  if [ ! -d "$ws" ]; then
    echo "Workspace not found: $ws"
    exit 1
  fi
  # 目录不存在时直接提示,避免静默失败

  [ -n "$sess" ] || sess="$(make_session_name "$ws")"
  echo "$ws" > ~/.agent/last_workspace
  echo "$sess" > ~/.agent/last_session
  # 补全/刷新状态文件

  cmd="agent --workspace $(printf '%q' "$ws") --continue"
  exec tmux new-session -A -s "$sess" -c "$ws" "$cmd"
fi
# 会话不在但目录记录还在:重建并恢复

echo "No previous agent session found."

附件C:powershell启动文件覆写agent函数

function agent {
    param(
        [Parameter(ValueFromRemainingArguments = $true)]
        [string[]]$Args
    )

    $Distro = "Ubuntu-22.04"

    # 有参数时,走原生 agent.exe(例如 agent ls / agent status)
    if ($Args.Count -gt 0) {
        & (Get-Command agent.exe).Source @Args
        return
    }

    # 无参数时,走 WSL + tmux 自动恢复流程
    $winPath = (Get-Location).Path
    $wslPath = (wsl -d $Distro -- wslpath -a "$winPath").Trim()

    # 直接调用已落盘脚本,避免内嵌bash字符串解析问题
    wsl -d $Distro -- bash -lc '~/bin/agent-open.sh "$1"' _ "$wslPath"
}
AI创作申明:三个附件代码由GPT-5.4编写和测试