Cursor Cloud Agent 环境折腾记

发布于

最近在折腾 Cursor Cloud Agent 的环境配置,想实现“新开会话就能直接本地访问 admin-web”。没想到前前后后花了两天,踩了好几个完全不在文档里的坑。记录下来,主要是为了以后自己查。

本文撰文环境

  1. 物理机:Windows 11 Pro
  2. 本地 Node 版本管理工具:fnm
  3. 仓库:pnpm monorepo,包含 admin-web(React Router 8 + Cloudflare Workers)
  4. Cloud Agent:2026 年 8 月

第一个坑:面板 Environment 和 .cursor/environment.json 是什么关系?

第一次使用 Cloud Agent,自然先去 Dashboard 的 Environment 面板设置。面板里能填的东西只有:

看起来很完整——但实际用起来,dev 服务从来没有自动起来过。面板里根本没有“如何启动预览”的配置项,也没有 terminals 字段,更没有 ports

后来才知道:.cursor/environment.json 里的 terminals 是在面板里完全看不到的字段,但它才是控制“新会话开机后自动跑哪些 dev 进程”的关键。

两者的优先级关系

Cursor 的环境配置有一套优先级:

  1. 仓库里的 .cursor/environment.json(本仓库当前使用这个)
  2. 面板里个人保存的 Environment 设置
  3. 团队共享的 Environment 设置

只要仓库里有 .cursor/environment.json,面板里的 install/start 设置就会被忽略,完全以文件为准。

这一点文档没有显著说明,导致花了很长时间在面板里调来调去,发现调了没有任何效果。

面板 Environment 实际的使用场景

面板设置的作用是:在没有 .cursor/environment.json 的仓库里,提供一个图形化的安装和启动配置。也就是说,面板是给“不想在仓库里维护 .cursor/environment.json“的用户用的。

如果你的项目是 monorepo、有复杂的 terminal 启动需求、需要 ports 声明,那几乎一定要维护 .cursor/environment.json,面板设置对你来说基本没有存在感——但它并没有消失,只是被文件覆盖了。

面板里唯一不被覆盖的东西:Secrets

面板里配置的 Secrets(环境变量)是独立的注入机制,不受文件优先级影响,无论你是否有 .cursor/environment.json,Secrets 都会注入到 VM 的进程环境变量里。

这也是为什么建议把敏感配置(数据库连接串、API Key)放在面板的 Secrets,而不是写进 .cursor/environment.json——后者会进仓库。


第二个坑:Secrets 注入完全失效(官方 bug)

回到我自己的经历。当时面板里 Secrets 都配置好了,状态是 Active,仓库关联也正确,但新开 Cloud Agent 之后,dev 服务就是起不来。AI 查了一圈,最后通过调用 Supabase MCP 绕过了问题,但根本原因一直没查清楚。

直到后来在社区看到这个帖子才恍然大悟:

Cloud Agent environment secrets exist but are never injected into the VM

这是一个官方确认的 bug(2026 年 7 月):Environment 作用域的 Secrets 使用了和 Personal 作用域不同的注入路径,而那条路径有 bug,导致 Secrets 根本没有被注入到 VM——即使 UI 显示一切正常。

这个 bug 最坑的地方在于:

当时的临时 Workaround:把 Secrets 从 Environment 作用域改到 Personal 作用域重建一遍,重新开会话。Personal 作用域走的是另一条注入路径,没有这个 bug。

官方修复时间:2026-07-22 部署修复,社区验证有效。

所以如果你在 2026 年 7 月之前就遇到这个问题,不是你配置有问题,是 Cursor 的 bug。


第三个坑:Node 版本错导致 dev 服务起不来

在 Secrets 问题解决之后,dev 服务还是跑不起来,这次是另一个报错:

Node v22.14.0 detected. react-router requires a Node version greater than 22.22.0.
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"

Cloud Agent 的镜像默认 Node 是 v22.14.0,但项目要求 >=26.0.0。这个问题倒是比较直观,修起来也有路可循。


折腾 Node 版本管理的过程

最初的想法:在 terminals 里写初始化

"command": "bash -lc 'nvm use 22.22.2 && pnpm --filter admin-web dev'"

这能工作,但每条命令都写一遍,且版本写死在 JSON 里,和 package.json 的版本声明脱节。

换 volta,再发现版本还是写死了

换成 Volta 之后,terminals 里写:

"command": "bash -lc 'export VOLTA_HOME=... && volta install node@26.7.0 pnpm@11.21.0 && pnpm --filter admin-web dev'"

写完发现这和“写死版本”没有本质区别,只是换了个工具——node@26.7.0 pnpm@11.21.0 还是直接硬编码在 JSON 里。

正确方向:版本只在一个地方声明

{
  "packageManager": "pnpm@11.21.0+sha512.xxx"
}

这两个字段都是 Node 生态的标准,工具会自动识别,不需要在任何脚本里硬编码版本号。

PATH 传递问题的推导

然后遇到了更本质的问题:install 阶段设置的 PATH,terminals 能不能用到?

结论是:不能直接用。原因是 startterminals 是独立启动的进程,install 阶段的环境变量不会自动传递过去。

一度想把初始化挪到 start 脚本——但 start 的环境变量只对 start 进程的子进程有效,同样不会传给独立启动的 terminals

正确解法是:install.sh 里把 fnm 初始化写入 ~/.bashrc。这样快照里就包含了配置好的 ~/.bashrcterminals 启动的 login shell 会自动读取它,不需要任何额外初始化。

# install.sh 里的关键部分
if ! grep -q 'fnm env' "$HOME/.bashrc" 2>/dev/null; then
  cat >> "$HOME/.bashrc" <<'EOF'

# fnm – Node version manager
export PATH="$HOME/.local/share/fnm:$PATH"
eval "$(fnm env --shell bash --use-on-cd)"
EOF
fi

这样 environment.json 就能写成最干净的形式:

{
  "install": "bash .cursor/install.sh",
  "terminals": [
    { "command": "pnpm --filter admin-web dev" }
  ]
}

和本地开发者直接跑的命令完全一样。


最终方案

.node-version(根目录):

26.7.0

package.json(片段):

{
  "engines": { "node": ">=26.0.0" },
  "packageManager": "pnpm@11.21.0+sha512.xxx"
}

.cursor/install.sh(build 阶段执行一次):

  1. 安装 fnm
  2. 写入 ~/.bashrc(fnm 初始化)
  3. fnm install && fnm use(读 .node-version
  4. corepack enable(pnpm 版本由 packageManager 决定)
  5. pnpm install --frozen-lockfile

升级规则


没搞清楚的问题

折腾完之后,有一些问题我还没有完全搞清楚,写在这里:

面板 Environment 的 install/start 在什么情况下会真正生效?

理论上是“仓库里没有 .cursor/environment.json“时生效。但如果团队里有人没有维护 .cursor/environment.json,直接用面板配置,那 Secrets 的坑(已修复)他们是否也踩过?不确定。

面板 Environment 的配置和文件的配置能不能“互补”?

例如:.cursor/environment.json 里只写 terminalsportsinstallstart 留空,面板里配 install——这能生效吗?

从实际观察来看,似乎是“文件存在就全覆盖面板”,而不是“字段级别的 merge”。但这一点 Cursor 文档没有明确说明,我也没有系统验证过。


几个结论

  1. .cursor/environment.json 就用文件,面板的 install/start 会被忽略,但 Secrets 不受影响。
  2. terminals 只能在 .cursor/environment.json 里配置,面板看不到这个字段,也控制不了。
  3. Secrets 注入有过官方 bug(已修复),如果你在 2026 年 7 月前遇到 Secrets 不生效,是 Cursor 的问题。
  4. install 阶段写 ~/.bashrc 是让 terminals 继承工具链初始化的正确姿势。
  5. 版本管理单一来源:Node 用 .node-version,pnpm 用 packageManager,不要在多处重复声明。
  6. Secrets 只在 VM 启动时注入一次,对话中途新增需要开新会话。

参考资料