Skip to content

[Bug] 自定义配置目录(CLAUDE_CONFIG_DIR 等)下历史会话点开「当前会话暂无消息」——parser 不读 agent 设置的 env_json(影响全部 agent) #948

Closed

Description

@lfabay

现象

给 agent 配了自定义配置目录(agent 设置里的 env_json,如 Claude 的 CLAUDE_CONFIG_DIR、Codex 的 CODEX_HOME)后:

  • 侧栏能列出会话标题;
  • 但点开会话显示「当前会话暂无消息」(messageList.emptyConversation);
  • 在会话里继续发消息,上下文完全对得上。

数据没丢(会话 jsonl 都在磁盘上),只是界面读不出来,也无报错日志 —— parser 找不到文件后静默返回空 turn 列表。

复现

  1. 给 claude_code 配 env_json = {"CLAUDE_CONFIG_DIR": "C:\\Users\\<用户>\\.claude-ocx"}(agent 设置里的环境变量);
  2. 用 codeg 起一个 Claude 会话、聊几句 → 会话文件写到 ~\.claude-ocx\projects\<项目>\<sessionId>.jsonl;
  3. 重启 codeg;
  4. 点开该会话 → 「当前会话暂无消息」;
  5. 在该会话里继续发消息 → 上下文正常(说明是"界面读不到",不是数据丢)。

对照实验:把 ~\.claude\projects 做成指向 ~\.claude-ocx\projects 的 junction 后,同一批会话立刻能显示 —— 坐实了"parser 去错目录"。

根因

codeg 读 CLAUDE_CONFIG_DIR 有两条路,只通了一条:

用途 读哪里 结果
启动 agent 子进程 agent_setting.env_json(runtime_env) ✅ 用了自定义目录
读历史会话(parser) std::env::var_os("CLAUDE_CONFIG_DIR")(进程环境变量) ❌ 主进程没有 → fallback 到 ~\.claude

src-tauri/src/parsers/claude.rs:1563:

pub(crate) fn resolve_claude_config_dir() -> PathBuf {
    resolve_claude_config_dir_from(std::env::var_os("CLAUDE_CONFIG_DIR"), dirs::home_dir())
}

而 build_agent_parser(src-tauri/src/parsers/mod.rs:376)只接收 agent_type,拿不到该 agent 的 env_json:

pub fn build_agent_parser(agent_type: AgentType) -> Box<dyn AgentParser> {
    let inner: Box<dyn AgentParser> = match agent_type {
        AgentType::ClaudeCode => Box::new(claude::ClaudeParser::new()),   // new() 无 env 参数
        AgentType::Codex      => Box::new(codex::CodexParser::new()),
        // …
        AgentType::Custom(_)  => Box::new(acp_native::AcpNativeParser::new(agent_type)),
    };
    Box::new(RouteSanitized(inner))
}

且 codeg 并不会在启动时把 env_json 注入主进程环境:全仓 std::env::set_var 只用于 CODEG_DATA_DIR、WEBVIEW2_ARGS_ENV、CODEG_ACP_* 测试开关等,从不写 CLAUDE_CONFIG_DIR / CODEX_HOME 之类。这些变量通常也不是用户级/系统级环境变量 ⇒ 主进程侧永远读不到 ⇒ parser 恒定去默认目录。

影响面:全部 agent,不止 Claude

build_agent_parser 是所有 agent 的统一入口,而每个 parser 的目录解析都直接读进程环境变量:

parser 读的变量
claude.rs CLAUDE_CONFIG_DIR
codex.rs CODEX_HOME
codebuddy.rs CODEBUDDY_CONFIG_DIR
cursor.rs CURSOR_CONFIG_DIR / XDG_CONFIG_HOME
grok.rs GROK_HOME
gemini.rs GEMINI_CLI_HOME
antigravity.rs GEMINI_HOME
deepseek.rs DSH_HOME / DSH_AGENTS_HOME

⇒ 只要用户在 agent 设置里配了自定义目录,该 agent 的历史会话就都读不出来。

建议修复方向

codeg 已经有正确做法,只是 parser 层没接上:

  • src-tauri/src/acp/file_system_runtime.rs:273 的 agent_data_roots(agent_type, runtime_env) —— 注释写着「env_json moves the agent's state, so it must move the allowed root too」,并有测试 agent_data_roots_honor_runtime_env_relocation() 佐证 codeg 明确知道 runtime_env 会搬移状态目录;
  • 同一文件里的 raw_env_value(runtime_env, key) / env_value(runtime_env, key) 就是「先读该 agent 的 runtime_env,再退回 codeg 进程 env」的标准解析;FileSystemPolicy::from_env(workspace_root, agent_type, runtime_env) 是已采用该模式的样例。

方向:让 build_agent_parser 接收该 agent 的 runtime_env(或复用 agent_data_roots),各 parser 的 new() 用 raw_env_value(runtime_env, "CLAUDE_CONFIG_DIR") 之类的解析结果,替代裸 std::env::var_os。

临时规避(用户侧,不改 codeg)

把默认目录做成指向自定义目录的 junction,让 parser 找得到:

New-Item -ItemType Junction -Path "$env:USERPROFILE\.claude\projects" -Target "$env:USERPROFILE\.claude-ocx\projects"

(先把两边数据合并。注意别用 cmd 的 mklink —— 在 git-bash 下 /J 会被当成路径参数吃掉。)

相关 issue

环境

  • codeg v0.35.1(Windows 安装版)
  • OS:Windows 10 Pro 19045
  • agent:claude_code(内置 ACP)
  • 自定义目录:CLAUDE_CONFIG_DIR=%USERPROFILE%\.claude-ocx(agent 设置 env_json 内)

Activity

  1. xintaofei commented on Oct 14, 2026

    @xintaofei
    Collaborator

    codeg work task 344 is done — merged locally into main as 8131bc1 (25 files, +1259/-178).

  2. added a commit that references this issue on Oct 14, 2026
    8131bc1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions