最近在折腾 Cursor Cloud Agent 的环境配置,想实现“新开会话就能直接本地访问 admin-web”。没想到前前后后花了两天,踩了好几个完全不在文档里的坑。记录下来,主要是为了以后自己查。
本文撰文环境
- 物理机:Windows 11 Pro
- 本地 Node 版本管理工具:fnm
- 仓库:pnpm monorepo,包含
admin-web(React Router 8 + Cloudflare Workers) - Cloud Agent:2026 年 8 月
第一个坑:面板 Environment 和 .cursor/environment.json 是什么关系?
第一次使用 Cloud Agent,自然先去 Dashboard 的 Environment 面板设置。面板里能填的东西只有:
install命令start命令- Secrets(环境变量)
看起来很完整——但实际用起来,dev 服务从来没有自动起来过。面板里根本没有“如何启动预览”的配置项,也没有 terminals 字段,更没有 ports。
后来才知道:.cursor/environment.json 里的 terminals 是在面板里完全看不到的字段,但它才是控制“新会话开机后自动跑哪些 dev 进程”的关键。
两者的优先级关系
Cursor 的环境配置有一套优先级:
- 仓库里的
.cursor/environment.json(本仓库当前使用这个) - 面板里个人保存的 Environment 设置
- 团队共享的 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 最坑的地方在于:
- UI 显示“Active”、“Secrets 已配置”
- 仓库关联正确
- 重建 Agent 无效
- 所有配置看起来都是对的,就是不生效
- 报错是 dev 服务起不来,让人以为是自己的启动脚本有问题
当时的临时 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 里。
正确方向:版本只在一个地方声明
- Node 版本 →
.node-version文件,fnm 自动读取 - pnpm 版本 →
package.json的packageManager,corepack 自动读取
{
"packageManager": "pnpm@11.21.0+sha512.xxx"
}
这两个字段都是 Node 生态的标准,工具会自动识别,不需要在任何脚本里硬编码版本号。
PATH 传递问题的推导
然后遇到了更本质的问题:install 阶段设置的 PATH,terminals 能不能用到?
结论是:不能直接用。原因是 start 和 terminals 是独立启动的进程,install 阶段的环境变量不会自动传递过去。
一度想把初始化挪到 start 脚本——但 start 的环境变量只对 start 进程的子进程有效,同样不会传给独立启动的 terminals。
正确解法是:在 install.sh 里把 fnm 初始化写入 ~/.bashrc。这样快照里就包含了配置好的 ~/.bashrc,terminals 启动的 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 阶段执行一次):
- 安装 fnm
- 写入
~/.bashrc(fnm 初始化) fnm install && fnm use(读.node-version)corepack enable(pnpm 版本由packageManager决定)pnpm install --frozen-lockfile
升级规则:
- 升级 Node → 只改
.node-version - 升级 pnpm → 只改
packageManager install.sh和environment.json不需要动
没搞清楚的问题
折腾完之后,有一些问题我还没有完全搞清楚,写在这里:
面板 Environment 的 install/start 在什么情况下会真正生效?
理论上是“仓库里没有 .cursor/environment.json“时生效。但如果团队里有人没有维护 .cursor/environment.json,直接用面板配置,那 Secrets 的坑(已修复)他们是否也踩过?不确定。
面板 Environment 的配置和文件的配置能不能“互补”?
例如:.cursor/environment.json 里只写 terminals 和 ports,install 和 start 留空,面板里配 install——这能生效吗?
从实际观察来看,似乎是“文件存在就全覆盖面板”,而不是“字段级别的 merge”。但这一点 Cursor 文档没有明确说明,我也没有系统验证过。
几个结论
- 有
.cursor/environment.json就用文件,面板的install/start会被忽略,但 Secrets 不受影响。 terminals只能在.cursor/environment.json里配置,面板看不到这个字段,也控制不了。- Secrets 注入有过官方 bug(已修复),如果你在 2026 年 7 月前遇到 Secrets 不生效,是 Cursor 的问题。
- install 阶段写
~/.bashrc是让 terminals 继承工具链初始化的正确姿势。 - 版本管理单一来源:Node 用
.node-version,pnpm 用packageManager,不要在多处重复声明。 - Secrets 只在 VM 启动时注入一次,对话中途新增需要开新会话。