You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ACP chat sessions ignore the agent config's env (CLAUDE_CONFIG_DIR) and reject custom claude/codex configs #9505
ACP chat sessions ignore the agent config they were started with, so two Claude accounts (e.g. work + personal, separated via CLAUDE_CONFIG_DIR in each agent config's env) can run side by side as terminals but not as chats.
superset sessions create --local --workspace <ws> --agent <A-uuid> --prompt 'run: echo $CLAUDE_CONFIG_DIR'
→ the chat starts, but prints the default account's dir (SUPERSET_DEFAULT_CLAUDE_CONFIG_DIR), not ~/.claude-a. The chat silently runs on the wrong account.
superset sessions create ... --agent <B-uuid> ...
→ Agent <B-uuid> or its attachments cannot be used with ACP chat. No terminal was launched.
Cause
createChatSession only forwards harness to the chat runtime; the agent config id is dropped, so buildChatAgentEnv only ever applies the default-account env.
chatLaunchTarget maps presetId → ACP harness, so a custom config that runs claude/codex has no harness.
Proposed fix
Carry an optional agentConfigId on the chat session (persisted, inherited on resume/fork/rewind), layer the config's env over the default-account env when launching the ACP agent (same precedence as terminal launches), and let custom configs whose command is claude/codex chat as that preset. PR incoming.
Both problems are real, and the cause is what you described. A chat session never learns which agent config started it, so the ACP agent only gets the host-default account env. Separately, choosing a chat harness keys on the config's presetId, and a custom config only gets its command checked for omp.
I read the code only; I didn't run anything or write a test.
Summary
Terminal launches put the agent config's own env on top of the default account's env, so a config that sets CLAUDE_CONFIG_DIR stays on its own account. Chat (ACP) launches skip that. The config is used only to pick a harness name, then dropped, so the spawned claude/codex uses the host-default CLAUDE_CONFIG_DIR / CODEX_HOME. A custom config that runs claude or codex can't be used for chat at all, because no harness matches the custom preset.
Affected code
1. Config env is dropped on the chat path
packages/host-service/src/trpc/router/agents/agents.ts:666-705: chatLaunchTarget resolves the config but returns only { harness, label, attachments }. The config id and env go no further.
packages/host-service/src/trpc/router/sessions/create-chat-session.ts:22-33: chat.commands.createSession gets scopeId, cwd, harness, terminalId, modelId, modeId and resume. Nothing names the agent config.
packages/host-service/src/chat-v3/acpHarnesses.ts:50-62: the harness factory builds env from buildChatAgentEnv({ db, cwd, workspaceId, terminalId }) only. It has no config to read.
packages/host-service/src/chat-v3/agentEnv.ts:56-76: buildChatAgentEnv adds resolveDefaultAccountTerminalEnv(db) (usage/default-account.ts:243), which is always the host-default Claude and Codex accounts.
The other buildChatAgentEnv calls (chat-v3/mount.ts:87,112 and agent-tooling/agent-tooling.ts:83) have the same gap.
The terminal path does this correctly with agentLaunchEnv in packages/host-service/src/terminal-agents/agent-config.ts:101-106:
seed-agent-trust.ts:84 uses the same order. So on the chat path, per-agent env never wins.
The session's account is also read from this env (captureSessionAccount(..., env.CLAUDE_CONFIG_DIR ...) in acpHarnesses.ts:64-73). Once the env is fixed, the recorded account will be fixed too.
2. custom configs are rejected for chat
agents.ts:696-701: the harness comes from acpHarnessForPreset(resolveAgentLaunchPresetId(config.presetId, config.command)).
packages/shared/src/agent-models.ts:725-735: resolveAgentLaunchPresetId only remaps the command omp / omp.exe to "omp". Any other command keeps presetId, here "custom".
packages/host-service/src/chat-v3/acpCatalogue.ts:98-108: ACP_HARNESS_BY_PRESET has no custom entry. chatLaunchTarget returns null, and session-service.ts:110-114 throws "…cannot be used with ACP chat. No terminal was launched."
Reproduction
Manual: follow the steps in the issue. With config A, the chat prints the default account's dir. With config B, the error above appears.
As a bun:test sketch, next to the existing chatLaunchTarget tests in agents.test.ts (around line 1160):
Insert a hostAgentConfigs row with presetId: "custom", command: "claude" and surface: "chat", then call chatLaunchTarget. It returns null today.
For the env bug, insert a presetId: "claude" row whose envJson sets CLAUDE_CONFIG_DIR. Check that the env the chat launch builds contains that value. Today buildChatAgentEnv has no way to accept the config, so the test will first need a new parameter or a way to look up the config by session.
Fix direction
The proposal in the issue matches the code:
Carry the config.
Return the config id from chatLaunchTarget and pass it through createChatSession into createSession. Store it on the session so resume, fork, rewind and restart keep it.
Expose it on the factory options.
Have buildChatAgentEnv add config.env last, the same way agentLaunchEnv does: { ...hostLaunchEnv, ...defaultAccountEnv, ...config.env }.
Sessions without a stored id fall back to today's behaviour.
Accept custom configs. Extend resolveAgentLaunchPresetId to map claude and codex executables the way it maps omp. Model and mode checks (agents.ts:702-703) and agentLaunchEnv would then treat these configs as their real preset. This function is in packages/shared and other callers use it, so check their behaviour too.
Check the CLI wrapper. The issue saw SUPERSET_DEFAULT_CLAUDE_CONFIG_DIR. default-account.ts:268-270 says the agent wrapper uses that variable to re-resolve the default account. Confirm that a CLAUDE_CONFIG_DIR set by the config is kept when the wrapper in ~/.paradev/bin, which withSupersetBinFirst puts first on PATH, starts the CLI.
Compatibility. Any new optional field on a tRPC input or on stored session data should follow packages/trpc/AGENTS.md, because released clients still call these procedures.
Activity
github-actions commentedon Nov 8, 2026
Both problems are real, and the cause is what you described. A chat session never learns which agent config started it, so the ACP agent only gets the host-default account env. Separately, choosing a chat harness keys on the config's
presetId, and acustomconfig only gets its command checked foromp.I read the code only; I didn't run anything or write a test.
Summary
Terminal launches put the agent config's own
envon top of the default account's env, so a config that setsCLAUDE_CONFIG_DIRstays on its own account. Chat (ACP) launches skip that. The config is used only to pick a harness name, then dropped, so the spawnedclaude/codexuses the host-defaultCLAUDE_CONFIG_DIR/CODEX_HOME. Acustomconfig that runsclaudeorcodexcan't be used for chat at all, because no harness matches thecustompreset.Affected code
1. Config env is dropped on the chat path
packages/host-service/src/trpc/router/agents/agents.ts:666-705:chatLaunchTargetresolves the config but returns only{ harness, label, attachments }. The config id and env go no further.packages/host-service/src/trpc/router/sessions/create-chat-session.ts:22-33:chat.commands.createSessiongetsscopeId,cwd,harness,terminalId,modelId,modeIdandresume. Nothing names the agent config.packages/host-service/src/chat-v3/acpHarnesses.ts:50-62: the harness factory builds env frombuildChatAgentEnv({ db, cwd, workspaceId, terminalId })only. It has no config to read.packages/host-service/src/chat-v3/agentEnv.ts:56-76:buildChatAgentEnvaddsresolveDefaultAccountTerminalEnv(db)(usage/default-account.ts:243), which is always the host-default Claude and Codex accounts.buildChatAgentEnvcalls (chat-v3/mount.ts:87,112andagent-tooling/agent-tooling.ts:83) have the same gap.The terminal path does this correctly with
agentLaunchEnvinpackages/host-service/src/terminal-agents/agent-config.ts:101-106:seed-agent-trust.ts:84uses the same order. So on the chat path, per-agent env never wins.The session's account is also read from this env (
captureSessionAccount(..., env.CLAUDE_CONFIG_DIR ...)inacpHarnesses.ts:64-73). Once the env is fixed, the recorded account will be fixed too.2.
customconfigs are rejected for chatagents.ts:696-701: the harness comes fromacpHarnessForPreset(resolveAgentLaunchPresetId(config.presetId, config.command)).packages/shared/src/agent-models.ts:725-735:resolveAgentLaunchPresetIdonly remaps the commandomp/omp.exeto"omp". Any other command keepspresetId, here"custom".packages/host-service/src/chat-v3/acpCatalogue.ts:98-108:ACP_HARNESS_BY_PRESEThas nocustomentry.chatLaunchTargetreturnsnull, andsession-service.ts:110-114throws "…cannot be used with ACP chat. No terminal was launched."Reproduction
Manual: follow the steps in the issue. With config A, the chat prints the default account's dir. With config B, the error above appears.
As a
bun:testsketch, next to the existingchatLaunchTargettests inagents.test.ts(around line 1160):hostAgentConfigsrow withpresetId: "custom",command: "claude"andsurface: "chat", then callchatLaunchTarget. It returnsnulltoday.presetId: "claude"row whoseenvJsonsetsCLAUDE_CONFIG_DIR. Check that the env the chat launch builds contains that value. TodaybuildChatAgentEnvhas no way to accept the config, so the test will first need a new parameter or a way to look up the config by session.Fix direction
The proposal in the issue matches the code:
chatLaunchTargetand pass it throughcreateChatSessionintocreateSession. Store it on the session so resume, fork, rewind and restart keep it.options.buildChatAgentEnvaddconfig.envlast, the same wayagentLaunchEnvdoes:{ ...hostLaunchEnv, ...defaultAccountEnv, ...config.env }.customconfigs. ExtendresolveAgentLaunchPresetIdto mapclaudeandcodexexecutables the way it mapsomp. Model and mode checks (agents.ts:702-703) andagentLaunchEnvwould then treat these configs as their real preset. This function is inpackages/sharedand other callers use it, so check their behaviour too.SUPERSET_DEFAULT_CLAUDE_CONFIG_DIR.default-account.ts:268-270says the agent wrapper uses that variable to re-resolve the default account. Confirm that aCLAUDE_CONFIG_DIRset by the config is kept when the wrapper in~/.paradev/bin, whichwithSupersetBinFirstputs first on PATH, starts the CLI.packages/trpc/AGENTS.md, because released clients still call these procedures.