Private/Resolve-ContainerPaths.ps1
|
function Resolve-ContainerPaths { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet('windows', 'linux')] [string]$ContainerOS, [Parameter(Mandatory)] [string]$ResolvedPath, [Parameter(Mandatory)] [string]$ClaudeConfigPath ) $errors = @() $dockerArgs = @() # Translate the host workspace path for the container's OS (e.g. Windows -> Linux) # On same-platform, this is a no-op. On Windows->Linux, converts C:\... to /c/... $workspace = ConvertTo-ContainerPath -HostPath $ResolvedPath -ContainerOS $ContainerOS # Mount ~/.claude directly at the container's ~/.claude so all reads/writes # go straight to the host filesystem. No staging path or symlinks needed. if ($ContainerOS -eq 'windows') { $claudeHome = 'C:/Users/ContainerAdministrator/.claude' } else { $claudeHome = '/home/claude/.claude' } if (Test-Path $ClaudeConfigPath) { $dockerArgs += '-v' $dockerArgs += "${ClaudeConfigPath}:${claudeHome}:rw" } else { Write-Warning "Claude config path '$ClaudeConfigPath' not found. Container will start without Claude configuration." } # Mount .claude.json (lives in home dir, separate from .claude/ directory). # Windows: Initialize-DClaudeWindowsContainers symlinks it into ~/.claude/ # so it travels with the directory mount above. # Linux: mount it inside the directory mount as a nested read-only bind. $claudeJsonPath = Join-Path (Split-Path $ClaudeConfigPath) '.claude.json' if (Test-Path $claudeJsonPath) { if ($ContainerOS -eq 'windows') { if (-not (Get-Item $claudeJsonPath).Target) { $errors += ".claude.json is not symlinked into '$ClaudeConfigPath'. Run Initialize-DClaudeWindowsContainers to fix this." } } else { $dockerArgs += '-v' $dockerArgs += "${claudeJsonPath}:${claudeHome}/.claude.json:ro" } } # Mask cross-platform directories in Linux containers (host has Windows-specific content). if ($ContainerOS -ne 'windows') { $dockerArgs += '--mount' $dockerArgs += "type=tmpfs,destination=${claudeHome}/plugins" $dockerArgs += '--mount' $dockerArgs += "type=tmpfs,destination=${claudeHome}/session-env" } # Mount the host project directory directly at the container's project path. # This must be a bind mount (not a symlink) because Claude Code's multi-worktree # resume uses readdir with {withFileTypes: true}, which returns isDirectory()=false # for symlinks -- causing symlinked project dirs to be silently skipped. $hostKey = $ResolvedPath -replace '[/\\:]', '-' $hostProjectDir = Join-Path $ClaudeConfigPath 'projects' $hostKey if (Test-Path $hostProjectDir) { # The container project key is derived from the container-side workspace path $containerKey = $workspace -replace '[/\\:]', '-' if ($ContainerOS -eq 'windows') { $containerProjectDir = "C:/Users/ContainerAdministrator/.claude/projects/$containerKey" } else { $containerProjectDir = "/home/claude/.claude/projects/$containerKey" } $dockerArgs += '-v' $dockerArgs += "${hostProjectDir}:${containerProjectDir}" } return [PSCustomObject]@{ Workspace = $workspace DockerArgs = $dockerArgs Errors = $errors } } |