fix Claude managed runtime routing and pane environment

This commit is contained in:
Merge Sim
2026-08-31 19:44:37 -07:00
parent 49b484a8f0
commit afcc06cb3d
7 changed files with 70 additions and 5 deletions
+4
View File
@@ -7,6 +7,7 @@ export const CLAUDE_AUTH_ENV_VARS = [
export type ClaudeEnvPatch = {
CLAUDE_CONFIG_DIR?: string
ORCA_CLAUDE_CONFIG_DIR?: string
ANTHROPIC_CUSTOM_HEADERS?: string
}
@@ -27,6 +28,9 @@ export function applyClaudeEnvPatch(
if (patch.CLAUDE_CONFIG_DIR && !baseEnv.CLAUDE_CONFIG_DIR) {
baseEnv.CLAUDE_CONFIG_DIR = patch.CLAUDE_CONFIG_DIR
}
if (patch.ORCA_CLAUDE_CONFIG_DIR && !baseEnv.ORCA_CLAUDE_CONFIG_DIR) {
baseEnv.ORCA_CLAUDE_CONFIG_DIR = patch.ORCA_CLAUDE_CONFIG_DIR
}
if (patch.ANTHROPIC_CUSTOM_HEADERS !== undefined) {
baseEnv.ANTHROPIC_CUSTOM_HEADERS = patch.ANTHROPIC_CUSTOM_HEADERS
}
@@ -1,3 +1,4 @@
import { readFileSync } from 'node:fs'
import type { Store } from '../persistence'
import {
getSelectedClaudeAccountIdForTarget,
@@ -124,6 +125,17 @@ export class ClaudeRuntimeAuthService extends ClaudeRuntimeAuthSync {
process.platform === 'darwin'
? () => readActiveClaudeKeychainCredentialsStrict()
: undefined,
readLegacyOauthAccount: () => {
try {
const parsed = JSON.parse(readFileSync(paths.configPath, 'utf-8')) as Record<
string,
unknown
>
return parsed.oauthAccount ?? null
} catch {
return null
}
},
readManagedCredentials: (account) => this.readManagedCredentials(account),
writeManagedCredentials: (account, contents) =>
this.writeManagedCredentials(account, contents)
@@ -1,3 +1,4 @@
import { existsSync, lstatSync, mkdirSync, symlinkSync } from 'node:fs'
import { join } from 'node:path'
import type { ClaudeManagedAccount } from '../../../shared/managed-account-types'
import { resolveLocalAccountRuntimeTarget } from '../../../shared/local-account-runtime'
@@ -44,7 +45,10 @@ export class ClaudeRuntimeAuthPreparationService extends ClaudeRuntimeAuthSnapsh
runtime: 'wsl',
wslDistro: activeAccount.wslDistro ?? null,
wslLinuxConfigDir: activeAccount.wslLinuxAuthPath,
envPatch: { CLAUDE_CONFIG_DIR: activeAccount.wslLinuxAuthPath },
envPatch: {
CLAUDE_CONFIG_DIR: activeAccount.wslLinuxAuthPath,
ORCA_CLAUDE_CONFIG_DIR: activeAccount.wslLinuxAuthPath
},
stripAuthEnv: true,
provenance: `managed:${activeAccount.id}:wsl:${activeAccount.wslDistro ?? ''}`
}
@@ -84,12 +88,16 @@ export class ClaudeRuntimeAuthPreparationService extends ClaudeRuntimeAuthSnapsh
{ adoptLegacyMarker: true }
)
if (managedPath) {
provisionClaudeManagedHome(paths.configDir, managedPath)
return {
configDir: managedPath,
runtime: 'host',
wslDistro: null,
wslLinuxConfigDir: null,
envPatch: { CLAUDE_CONFIG_DIR: managedPath },
envPatch: {
CLAUDE_CONFIG_DIR: managedPath,
ORCA_CLAUDE_CONFIG_DIR: managedPath
},
stripAuthEnv: true,
provenance: `managed:${activeAccount.id}`
}
@@ -145,3 +153,26 @@ export class ClaudeRuntimeAuthPreparationService extends ClaudeRuntimeAuthSnapsh
return defaultDistro ? { runtime: 'wsl', wslDistro: defaultDistro } : target
}
}
// Keep account homes useful without copying credential-bearing runtime state.
// Missing user resources are linked once; existing files remain user-owned.
function provisionClaudeManagedHome(systemConfigDir: string, managedPath: string): void {
if (systemConfigDir === managedPath) {
return
}
const resources = ['settings.json', 'CLAUDE.md', 'projects', 'plugins'] as const
for (const name of resources) {
const source = join(systemConfigDir, name)
const target = join(managedPath, name)
if (!existsSync(source) || existsSync(target)) {
continue
}
try {
const sourceIsDirectory = lstatSync(source).isDirectory()
mkdirSync(managedPath, { recursive: true, mode: 0o700 })
symlinkSync(source, target, sourceIsDirectory ? 'dir' : 'file')
} catch {
// Best effort: auth routing remains safe if an optional resource cannot link.
}
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ export class ClaudeRuntimePathResolver {
configDir,
credentialsPath: join(configDir, '.credentials.json'),
configPath: this.resolveConfigPath(configDir, inheritedConfigDir),
envPatch: inheritedConfigDir ? { CLAUDE_CONFIG_DIR: configDir } : {}
envPatch: { CLAUDE_CONFIG_DIR: configDir, ORCA_CLAUDE_CONFIG_DIR: configDir }
}
}
+4 -1
View File
@@ -223,7 +223,10 @@ export async function preparePtyIpcSpawnPreflight(ctx: PtyIpcSpawnState): Promis
)
try {
ctx.claudeAuth =
ctx.isClaudeLaunch && ctx.deps.prepareClaudeAuth
!ctx.preAdoptedStablePane &&
!args.connectionId &&
(ctx.isClaudeLaunch || !ctx.launchCommand) &&
ctx.deps.prepareClaudeAuth
? await ctx.deps.prepareClaudeAuth(initialSelectionTarget)
: null
} catch (error) {
+4 -1
View File
@@ -131,7 +131,10 @@ export async function prepareRuntimePtySpawn(
ctx.launchCommand = codexResumeLaunch.command
try {
ctx.claudeAuth =
ctx.isClaudeLaunch && ctx.deps.prepareClaudeAuth
!ctx.preAdoptedStablePane &&
!args.connectionId &&
(ctx.isClaudeLaunch || !ctx.launchCommand) &&
ctx.deps.prepareClaudeAuth
? await ctx.deps.prepareClaudeAuth(ctx.codexSelectionTarget)
: null
} catch (error) {
@@ -12,6 +12,7 @@ import { readLegacySidekickFlag } from '../applying-settings/onboarding-normaliz
import type { PersistedState } from '../../../shared/persisted-state-types'
import type { PreparedLoadedTerminalSettings } from './prepare-loaded-terminal-settings'
import type { PreparedLoadedProfileSettings } from './prepare-loaded-profile-settings'
import type { ClaudeManagedAccount } from '../../../shared/managed-account-types'
export function normalizeLoadedGlobalSettings(
parsed: PersistedState,
@@ -58,6 +59,9 @@ export function normalizeLoadedGlobalSettings(
// old default indistinguishable from a real opt-in. Preserve stored `true`; only
// the default changed.
...stripRetiredGlobalSettings(parsed.settings),
claudeManagedAccounts: normalizeClaudeManagedAccountRuntimes(
parsed.settings?.claudeManagedAccounts ?? defaults.settings.claudeManagedAccounts
),
worktreeVisibilityDefaults: migratedExternalVisibility.defaults,
prBotAuthorOverrides: normalizePRBotAuthorOverrides(parsed.settings?.prBotAuthorOverrides),
// Why: v1.3.42 renamed the sidekick setting to pet; carry the old flag forward once so enabled users don't lose it.
@@ -136,3 +140,11 @@ export function normalizeLoadedGlobalSettings(
}
}
}
export function normalizeClaudeManagedAccountRuntimes(
accounts: readonly ClaudeManagedAccount[]
): ClaudeManagedAccount[] {
return accounts.map((account) =>
account.managedAuthRuntime === undefined ? { ...account, managedAuthRuntime: 'host' } : account
)
}