88 formatClaudeOauthTokenFile
99} from "@prover-coder-ai/docker-git-auth-oauth/claude-oauth-token"
1010import { renderClaudeDockerOauthDockerfile } from "@prover-coder-ai/docker-git-auth-oauth/claude-docker-oauth"
11- import { Effect } from "effect"
11+ import { Effect , Match } from "effect"
1212
1313import type { AuthClaudeLoginCommand , AuthClaudeLogoutCommand , AuthClaudeStatusCommand } from "../core/domain.js"
1414import { defaultTemplateConfig } from "../core/domain.js"
@@ -27,6 +27,9 @@ import { readFileStringIfPresent, writeFileStringEnsuringParent } from "./volati
2727
2828type ClaudeRuntime = FileSystem . FileSystem | Path . Path | CommandExecutor . CommandExecutor
2929type ClaudeAuthMethod = "none" | "oauth-token" | "claude-ai-session"
30+ type ClaudeProbeAuth =
31+ | { readonly _tag : "ClaudeProbeAccountConfig" }
32+ | { readonly _tag : "ClaudeProbeOauthToken" ; readonly token : string }
3033
3134type ClaudeAccountContext = {
3235 readonly accountLabel : string
@@ -41,6 +44,7 @@ export const claudeAuthRoot = ".docker-git/.orch/auth/claude"
4144const claudeImageName = "docker-git-auth-claude:latest"
4245const claudeImageDir = ".docker-git/.orch/auth/claude/.image"
4346const claudeContainerHomeDir = "/claude-home"
47+ const claudeProbeConfigDir = "/tmp/docker-git-claude-probe"
4448const claudeConfigFileName = ".claude.json"
4549const claudeCredentialsFileName = ".credentials.json"
4650const claudeCredentialsDirName = ".claude"
@@ -178,6 +182,26 @@ const buildClaudeAuthEnv = (
178182 ...( oauthToken === null ? [ ] : [ `CLAUDE_CODE_OAUTH_TOKEN=${ oauthToken } ` ] )
179183]
180184
185+ // CHANGE: isolate non-interactive Claude OAuth probes from account settings
186+ // WHY: account settings may intentionally use bypassPermissions for real sessions, but Claude rejects that mode under root/sudo probe contexts
187+ // QUOTE(ТЗ): "почему не работает команда bun run docker-git auth claude login"
188+ // REF: user-report-2026-07-01-claude-auth-login
189+ // SOURCE: n/a
190+ // FORMAT THEOREM: forall token: probe(token) reads token env and not account(settings.json)
191+ // PURITY: CORE
192+ // INVARIANT: probe uses the persisted OAuth token without inheriting account permission settings
193+ // COMPLEXITY: O(1)
194+ const buildClaudeProbeEnv = ( auth : ClaudeProbeAuth ) : ReadonlyArray < string > =>
195+ Match . value ( auth ) . pipe (
196+ Match . when ( { _tag : "ClaudeProbeAccountConfig" } , ( ) => buildClaudeAuthEnv ( false ) ) ,
197+ Match . when ( { _tag : "ClaudeProbeOauthToken" } , ( { token } ) => [
198+ `HOME=${ claudeProbeConfigDir } ` ,
199+ `CLAUDE_CONFIG_DIR=${ claudeProbeConfigDir } ` ,
200+ `CLAUDE_CODE_OAUTH_TOKEN=${ token } `
201+ ] ) ,
202+ Match . exhaustive
203+ )
204+
181205const ensureClaudeOrchLayout = (
182206 cwd : string
183207) : Effect . Effect < void , PlatformError , FileSystem . FileSystem | Path . Path > =>
@@ -252,15 +276,15 @@ const runClaudeLogout = (
252276const runClaudePingProbeExitCode = (
253277 cwd : string ,
254278 accountPath : string ,
255- oauthToken : string | null
279+ auth : ClaudeProbeAuth
256280) : Effect . Effect < number , PlatformError , CommandExecutor . CommandExecutor > =>
257281 runDockerAuthExitCode (
258282 buildDockerAuthSpec ( {
259283 cwd,
260284 image : claudeImageName ,
261285 hostPath : accountPath ,
262286 containerPath : claudeContainerHomeDir ,
263- env : buildClaudeAuthEnv ( false , oauthToken ) ,
287+ env : buildClaudeProbeEnv ( auth ) ,
264288 args : [ "-p" , "ping" ] ,
265289 interactive : false
266290 } )
@@ -288,7 +312,10 @@ export const authClaudeLogin = (
288312 } ) ,
289313 persistToken : ( token ) => persistClaudeOauthToken ( fs , path , accountPath , token ) ,
290314 normalizeStoredCredentials : resolveClaudeAuthMethod ( fs , path , accountPath ) . pipe ( Effect . asVoid ) ,
291- probeToken : ( token ) => runClaudePingProbeExitCode ( cwd , accountPath , token ) ,
315+ probeToken : ( token ) => runClaudePingProbeExitCode ( cwd , accountPath , {
316+ _tag : "ClaudeProbeOauthToken" ,
317+ token
318+ } ) ,
292319 syncState : autoSyncState ( `chore(state): auth claude ${ accountLabel } ` )
293320 } ) . pipe ( Effect . asVoid ) )
294321
@@ -314,7 +341,10 @@ export const authClaudeStatus = (
314341 }
315342
316343 const oauthToken = method === "oauth-token" ? yield * _ ( readOauthToken ( fs , accountPath ) ) : null
317- const probeExitCode = yield * _ ( runClaudePingProbeExitCode ( cwd , accountPath , oauthToken ) )
344+ const probeAuth : ClaudeProbeAuth = method === "oauth-token" && oauthToken !== null
345+ ? { _tag : "ClaudeProbeOauthToken" , token : oauthToken }
346+ : { _tag : "ClaudeProbeAccountConfig" }
347+ const probeExitCode = yield * _ ( runClaudePingProbeExitCode ( cwd , accountPath , probeAuth ) )
318348 if ( probeExitCode === 0 ) {
319349 yield * _ ( Effect . log ( `Claude connected (${ accountLabel } , ${ method } ).` ) )
320350 return
0 commit comments