排查 Codex CLI 无法启用 IDE Context
问题
vscode先连接到wsl2打开项目,ssh连接到wsl2进入项目目录启动codex:
Codex CLI 中执行:
/ide报错:
IDE context could not be enabled. Open this project in VS Code or Cursor with the Codex extension active.检查了路径没问题,防火墙没问题,实在想不到还有什么可能导致vscode插件无法连接
被迫去看源码,发现Codex CLI 对多种失败情况会返回类似的用户提示:IDE context could not be enabled. 都会引导用户“打开 VS Code 或 Cursor 并启用扩展”
所以下一步是分析 /ide 的实际处理链路。
/ide 做了什么
从 Codex 的源码可以看到,在 Unix/Linux 环境下,CLI 默认会连接这个路径下的 socket:
${TMPDIR:-/tmp}/codex-ipc/ipc-$(id -u).sock在 Windows 下则使用命名管道:
\\.\pipe\codex-ipcCLI 连接到 socket 后,会发送一个 ide-context 请求,请求参数中包含当前工作区路径 workspaceRoot。也就是说,/ide 的关键条件至少包括:
- CLI 必须能连接到对应用户的 socket
- socket 必须由当前用户拥有
- workspaceRoot 必须能被 IDE 扩展识别
- IDE 扩展必须支持并响应 ide-context 请求
源码里还可以看到,IDE context 请求有 5 秒超时,并且请求方法是 ide-context,参数包含 workspaceRoot
这个模型决定了后面的排查顺序:先排除环境隔离,再检查 socket 是否存在,再检查 workspace,再检查权限和响应。
确认 socket 是否存在
接下来检查 Codex IPC socket:
ls -la "${TMPDIR:-/tmp}/codex-ipc/ipc-$(id -u).sock"实际输出类似:
srwxrwxr-x 1 kurfuerst kurfuerst 0 May 17 21:52 /tmp/codex-ipc/ipc-1000.sock这说明 socket 文件确实存在,而且 owner 是当前用户 kurfuerst。
socket 父目录
到这里,表面条件都满足了:
同一台远程机器
同一个用户
同一个项目路径
socket 文件存在
VS Code 插件正常但 /ide 仍然失败。
没办法,又去看了看源码,突然发现Codex CLI 源码里不只是检查 socket 文件本身,还会检查 Unix socket 的父目录。它要求父目录:
必须是目录
必须归当前用户所有
不能被 group 或 other 写入源码:
// codex-rs/tui/src/ide_context/ipc.rs
fn validate_unix_socket_path(socket_path: &Path) -> std::io::Result<()> {
...
if parent_metadata.permissions().mode() & 0o022 != 0 {
return Err(permission_denied_io_error(
"IDE context socket directory is writable by other users",
));
}
...
}如果父目录权限包含 0o022,就返回 PermissionDenied,原因是 “IDE context socket directory is writable by other users”。然而这句关键的报错用户没法看到。
所以需要检查的不只是:
/tmp/codex-ipc/ipc-1000.sock还包括它的父目录:
/tmp/codex-ipc执行:
ls -ld /tmp/codex-ipc
stat -c '%U %G %a %n' /tmp/codex-ipc /tmp/codex-ipc/ipc-$(id -u).sock实际输出是:
drwxrwxr-x 2 kurfuerst kurfuerst 4096 May 18 00:26 /tmp/codex-ipc
kurfuerst kurfuerst 775 /tmp/codex-ipc
kurfuerst kurfuerst 775 /tmp/codex-ipc/ipc-1000.sock问题就在这里了
group 有写权限
而 Codex CLI 的安全检查认为这样的目录不可信,因为其他同组用户理论上可能替换、干扰或伪造 socket。
解决方案
临时方案很简单,直接修改目录权限
执行:
pkill -f codex || true
chmod 755 /tmp/codex-ipc
stat -c '%U %G %a %n' /tmp/codex-ipc期望输出:
kurfuerst kurfuerst 755 /tmp/codex-ipc然后重启 VSCode Remote SSH 后端
临时方案确实快,但是重启后所做更改就丢失了,每次重启都要手动修改目录权限太过麻烦,所以想要通过更改pam配置彻底解决问题。
当前 shell 或 Codex CLI 的 umask 是 0022,但真正创建 IPC 文件的是 VS Code 扩展里的进程:
codex app-server修复前检查进程 umask:
for p in $(pgrep -u "$USER" -f 'codex app-server|extensionHost|server/node'); do
echo "PID=$p"
tr '\0' ' ' < /proc/$p/cmdline | cut -c1-200
grep '^Umask:' /proc/$p/status
echo
done发现 VSCode Server / codex app-server 的 umask 是:
Umask: 0002导致 /tmp/codex-ipc 被创建成 775。
进一步检查系统配置:
grep -R "pam_umask\|UMASK\|USERGROUPS" \
/etc/pam.d /etc/login.defs /etc/default/login 2>/dev/null结果显示:
/etc/pam.d/common-session:session optional pam_umask.so
/etc/pam.d/common-session-noninteractive:session optional pam_umask.so
/etc/login.defs:UMASK 022
/etc/login.defs:USERGROUPS_ENAB yes虽然 UMASK 是 022,但 USERGROUPS_ENAB yes 会在“用户名和主组名相同”时把 022 转换成 002。因此 VSCode Remote 会话最终拿到的是 umask 0002。
修复方法
修改这两个 PAM 配置文件:
/etc/pam.d/common-session
/etc/pam.d/common-session-noninteractive先备份:
sudo cp -a /etc/pam.d/common-session /etc/pam.d/common-session.bak
sudo cp -a /etc/pam.d/common-session-noninteractive /etc/pam.d/common-session-noninteractive.bak随后编辑这两个文件,将这一行:
session optional pam_umask.so改成:
session optional pam_umask.so umask=0022 nousergroups确认修改:
grep -n '^[^#].*pam_umask' \
/etc/pam.d/common-session \
/etc/pam.d/common-session-noninteractive
# 输出
/etc/pam.d/common-session:session optional pam_umask.so umask=0022 nousergroups
/etc/pam.d/common-session-noninteractive:session optional pam_umask.so umask=0022 nousergroups重启 VSCode Server 和清理旧 IPC
pkill -u "$USER" -f 'codex app-server' 2>/dev/null || true
pkill -u "$USER" -f '.vscode-server' 2>/dev/null || true
rm -rf /tmp/codex-ipc然后重新连接服务器。
重新连接后检查 VSCode / Codex 相关进程:
for p in $(pgrep -u "$USER" -f 'codex app-server|extensionHost|server/node'); do
echo "PID=$p"
tr '\0' ' ' < /proc/$p/cmdline | cut -c1-200
grep '^Umask:' /proc/$p/status
echo
done修复后应看到:
Umask: 0022然后重新触发 Codex 连接或 /ide,检查 IPC 权限:
ls -ld /tmp/codex-ipc
stat -c '%U %G %a %n' /tmp/codex-ipc /tmp/codex-ipc/ipc-$(id -u).sock
# 输出
755 /tmp/codex-ipc
755 /tmp/codex-ipc/ipc-1000.sock至少 /tmp/codex-ipc 必须是 755,这样 Codex 的安全检查才能通过。