[bug] Windows: env 注入到 shell profile 时写的是原生路径,source 静默失败而 doctor 仍报通过
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4.8k
- Forks
- 342
- Avg merge
- 13h 48m
- Merged PRs (30d)
- 211
Description
English summary — On Windows, the env block injected into
~/.bashrccontains
[ -f C:\Users\<user>\.teamai/env.sh ] && source C:\Users\<user>\.teamai/env.sh.
Because an unquoted\is an escape character in POSIX shells, the word degrades to
C:UsersCarlos.teamai/env.sh, the[ -f ]test is false,&&short-circuits and
sourcenever runs — so no env variable is ever delivered.teamai doctorstill
prints✔ Env variables injected in shell profilebecause the check only greps for the
marker comment. The only visible symptom is downstream: MCP entries using${VAR}get
skipped withunresolved variable(s).
Description
Windows 上 teamai pull(或 teamai init)注入到 shell profile 的 env 块,source 行用的是原生 Windows 路径(反斜杠):
# [teamai:env:start]
# DO NOT EDIT: This section is auto-managed by teamai
[ -f C:\Users\<user>\.teamai/env.sh ] && source C:\Users\<user>\.teamai/env.sh
# [teamai:env:end]
在没有引号的 POSIX shell 词里,\ 是转义符。上面这一行实际被解析成:
+ '[' -f C:UsersCarlos.teamai/env.sh ']'
exit=1
反斜杠被吞掉,得到一个不可能存在的路径 → [ -f ... ] 为假 → && 短路 → source 从未执行。于是 ~/.teamai/env.sh 里的变量永远进不了任何 shell。
而 .bashrc 里一个失败的 [ 测试既不报错也不中断,所以从用户视角完全静默:没有任何输出、没有非零退出影响会话。
更糟的是 teamai doctor 仍然显示通过:
✔ Env variables injected in shell profile
因为该检查只断言 profile 文本里出现过标记串 # [teamai:env:start],从不验证这个块是否真的能加载。于是失败被掩盖,唯一的可见症状跑到下游去了——MCP 定义里引用 ${VAR} 的服务被跳过,输出一句 unresolved variable(s),完全指不到 env.yaml 或 shell profile 头上。
Root cause
generateShellBlock() 把 path.join() 的结果(win32 → 反斜杠)原样插进 shell 脚本:
generateShellBlock(teamaiHome) {
const lines = [
TEAMAI_ENV_START,
"# DO NOT EDIT: This section is auto-managed by teamai",
`[ -f ${teamaiHome}/env.sh ] && source ${teamaiHome}/env.sh`,
TEAMAI_ENV_END
];
return lines.join("\n");
}
teamaiHome 来自 getDataHome() → getTeamaiHome(),即 path.join(home, ".teamai"),在 Windows 上必然是 C:\Users\<user>\.teamai。这里既没有换成分隔符、也没有加引号。
配套的 doctor 检查只做字符串包含判断:
{
name: "Env variables injected in shell profile",
check: async () => {
if (teamConfig?.sharing?.env?.injectShellProfile === false) return true;
if (!localConfig) return true;
const envYamlPath = path.join(localConfig.repo.localPath, "env", "env.yaml");
if (!await pathExists(envYamlPath)) return true;
const home = getUserHome();
// ...
return content?.includes(TEAMAI_ENV_START) ?? false;
},
fix: "Run `teamai pull` to inject env variables into shell profile"
}
整条链路里没有任何一步做「目标 shell 需要什么形式的路径」这个转换或校验。
Reproduction
- Windows 11 + Node.js +
teamai0.24.0,团队仓库含env/env.yaml且至少有一个变量。 teamai pull→ 上面的反斜杠块写入~/.bashrc。- 用
sh -x跑这个块:
$ sh -x ~/.bashrc # 或单独把该块存成文件后执行
+ '[' -f C:UsersCarlos.teamai/env.sh ']'
exit=1
- 确认变量从未到达 shell:
$ bash -lc 'echo "MY_VAR=[${MY_VAR}]"'
MY_VAR=[]
teamai doctor→ 依旧✔ Env variables injected in shell profile。
对照:同一个块用 POSIX 形式写就能工作(这是我本机临时修正后的形态):
# [teamai:env:start]
# DO NOT EDIT: This section is auto-managed by teamai
[ -f "/c/Users/Carlos/.teamai/env.sh" ] && source "/c/Users/Carlos/.teamai/env.sh"
# [teamai:env:end]
$ bash -lc 'source ~/.bashrc >/dev/null 2>&1; echo "len=${#MY_VAR}"'
len=16
Environment
- OS: Windows 11 25H2 (10.0.26200)
- Node.js:
v22.22.2(v22.17.0同样复现) - teamai:
0.24.0 - Provider: GitHub
- AI tool(s): WorkBuddy / CodeBuddy —— 注意本缺陷与具体工具无关,只要 profile 是 POSIX shell(
~/.bashrc、~/.zshrc)就会中招
Suggested fix
两处独立的小改动,建议都做:
-
输出 shell 安全的路径。 在生成块的地方做转换,而不是改
path的计算结果(同一个值还要用于真实文件系统访问)。推荐直接回避绝对路径,用$HOME并加引号:[ -f "$HOME/.teamai/env.sh" ] && source "$HOME/.teamai/env.sh"如果需要绝对路径(例如
dataHome被自定义到别的盘),则应转成目标 shell 能懂的形式(/c/Users/...这类 MSYS 风格)并始终加引号——注意Program Files这种带空格的路径只有加引号才安全。 -
让
doctor验证行为而不是验证存在。 现在只要字符串在就算通过。建议在 shell 里真正 source 一次 profile(或至少求值那个[ -f ... ]测试)并断言其中一个变量确实解析成功,否则报.bashrc 中的 env 块无法加载。
Logs
~/.bashrc 中被注入的块,以及它的求值结果
$ grep -A3 'teamai:env:start' ~/.bashrc
# [teamai:env:start]
# DO NOT EDIT: This section is auto-managed by teamai
[ -f C:\Users\Carlos\.teamai/env.sh ] && source C:\Users\Carlos\.teamai/env.sh
# [teamai:env:end]
$ sh -x <把上面的块存成文件后执行>
+ '[' -f C:UsersCarlos.teamai/env.sh ']'
exit=1
即:source 分支根本没被走到。
teamai doctor 的假通过
$ teamai doctor
✔ Env variables injected in shell profile
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at generateShellBlock(), where teamaiHome is inserted into the shell profile, and inspect the doctor check named "Env variables injected in shell profile". Reproduce the generated block on Windows with sh -x or bash, then verify that the environment variable loads and doctor does not report success for an unusable block.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, node.js, typescript
- Domain
- cli, developer-experience
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100