Swadhin Biswas feat: implement mervelas cli engine, built-in tools, and reactive UI · 4/3/2026
0358986
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import {
getSessionIngressToken,
setSessionIngressToken,
} from '../bootstrap/state.js'
import {
CCR_SESSION_INGRESS_TOKEN_PATH,
maybePersistTokenForSubprocesses,
readTokenFromWellKnownFile,
} from './authFileDescriptor.js'
import { logForDebugging } from './debug.js'
import { errorMessage } from './errors.js'
import { getFsImplementation } from './fsOperations.js'
/**
* Read token via file descriptor, falling back to well-known file.
* Uses global state to cache the result since file descriptors can only be read once.
*/
function getTokenFromFileDescriptor(): string | null {
// Check if we've already attempted to read the token
const cachedToken = getSessionIngressToken()
if (cachedToken !== undefined) {
return cachedToken
}
const fdEnv = process.env.CLAUDE_CODE_WEBSOCKET_AUTH_FILE_DESCRIPTOR
if (!fdEnv) {
// No FD env var — either we're not in CCR, or we're a subprocess whose
// parent stripped the (useless) FD env var. Try the well-known file.
const path =
process.env.CLAUDE_SESSION_INGRESS_TOKEN_FILE ??
CCR_SESSION_INGRESS_TOKEN_PATH
const fromFile = readTokenFromWellKnownFile(path, 'session ingress token')
setSessionIngressToken(fromFile)
return fromFile
}
const fd = parseInt(fdEnv, 10)
if (Number.isNaN(fd)) {
logForDebugging(
`CLAUDE_CODE_WEBSOCKET_AUTH_FILE_DESCRIPTOR must be a valid file descriptor number, got: ${fdEnv}`,
{ level: 'error' },
)
setSessionIngressToken(null)
return null
}
try {
// Read from the file descriptor
// Use /dev/fd on macOS/BSD, /proc/self/fd on Linux
const fsOps = getFsImplementation()
const fdPath =
process.platform === 'darwin' || process.platform === 'freebsd'
? `/dev/fd/${fd}`
: `/proc/self/fd/${fd}`
const token = fsOps.readFileSync(fdPath, { encoding: 'utf8' }).trim()
if (!token) {
logForDebugging('File descriptor contained empty token', {
level: 'error',
})
setSessionIngressToken(null)
return null
}
logForDebugging(`Successfully read token from file descriptor ${fd}`)
setSessionIngressToken(token)
maybePersistTokenForSubprocesses(
CCR_SESSION_INGRESS_TOKEN_PATH,
token,
'session ingress token',
)
return token
} catch (error) {
logForDebugging(
`Failed to read token from file descriptor ${fd}: ${errorMessage(error)}`,
{ level: 'error' },
)
// FD env var was set but read failed — typically a subprocess that
// inherited the env var but not the FD (ENXIO). Try the well-known file.
const path =
process.env.CLAUDE_SESSION_INGRESS_TOKEN_FILE ??
CCR_SESSION_INGRESS_TOKEN_PATH
const fromFile = readTokenFromWellKnownFile(path, 'session ingress token')
setSessionIngressToken(fromFile)
return fromFile
}
}
/**
* Get session ingress authentication token.
*
* Priority order:
* 1. Environment variable (CLAUDE_CODE_SESSION_ACCESS_TOKEN) — set at spawn time,
* updated in-process via updateSessionIngressAuthToken or
* update_environment_variables stdin message from the parent bridge process.
* 2. File descriptor (legacy path) — CLAUDE_CODE_WEBSOCKET_AUTH_FILE_DESCRIPTOR,
* read once and cached.
* 3. Well-known file — CLAUDE_SESSION_INGRESS_TOKEN_FILE env var path, or
* /home/claude/.mervelas/remote/.session_ingress_token. Covers subprocesses
* that can't inherit the FD.
*/
export function getSessionIngressAuthToken(): string | null {
// 1. Check environment variable
const envToken = process.env.CLAUDE_CODE_SESSION_ACCESS_TOKEN
if (envToken) {
return envToken
}
// 2. Check file descriptor (legacy path), with file fallback
return getTokenFromFileDescriptor()
}
/**
* Build auth headers for the current session token.
* Session keys (sk-ant-sid) use Cookie auth + X-Organization-Uuid;
* JWTs use Bearer auth.
*/
export function getSessionIngressAuthHeaders(): Record<string, string> {
const token = getSessionIngressAuthToken()
if (!token) return {}
if (token.startsWith('sk-ant-sid')) {
const headers: Record<string, string> = {
Cookie: `sessionKey=${token}`,
}
const orgUuid = process.env.CLAUDE_CODE_ORGANIZATION_UUID
if (orgUuid) {
headers['X-Organization-Uuid'] = orgUuid
}
return headers
}
return { Authorization: `Bearer ${token}` }
}
/**
* Update the session ingress auth token in-process by setting the env var.
* Used by the REPL bridge to inject a fresh token after reconnection
* without restarting the process.
*/
export function updateSessionIngressAuthToken(token: string): void {
process.env.CLAUDE_CODE_SESSION_ACCESS_TOKEN = token
}