π― Use case
This file lives under βutils/β, which covers cross-cutting helpers (shell, tempfiles, settings, messages, process input, β¦). On the API surface it exposes MTLSConfig, TLSConfig, getMTLSConfig, getMTLSAgent, and getWebSocketTLSOptions (and more) β mainly functions, hooks, or classes. Dependencies touch Node HTTPS, lodash-es, tls, and undici. It composes internal code from caCerts, debug, and fsOperations (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import type * as https from 'https' import { Agent as HttpsAgent } from 'https' import memoize from 'lodash-es/memoize.js' import type * as tls from 'tls' import type * as undici from 'undici'
π€ Exports (heuristic)
MTLSConfigTLSConfiggetMTLSConfiggetMTLSAgentgetWebSocketTLSOptionsgetTLSFetchOptionsclearMTLSCacheconfigureGlobalMTLS
π External import roots
Package roots from from "β¦" (relative paths omitted).
httpslodash-estlsundici
π₯οΈ Source preview
import type * as https from 'https'
import { Agent as HttpsAgent } from 'https'
import memoize from 'lodash-es/memoize.js'
import type * as tls from 'tls'
import type * as undici from 'undici'
import { getCACertificates } from './caCerts.js'
import { logForDebugging } from './debug.js'
import { getFsImplementation } from './fsOperations.js'
export type MTLSConfig = {
cert?: string
key?: string
passphrase?: string
}
export type TLSConfig = MTLSConfig & {
ca?: string | string[] | Buffer
}
/**
* Get mTLS configuration from environment variables
*/
export const getMTLSConfig = memoize((): MTLSConfig | undefined => {
const config: MTLSConfig = {}
// Note: NODE_EXTRA_CA_CERTS is automatically handled by Node.js at runtime
// We don't need to manually load it - Node.js appends it to the built-in CAs automatically
// Client certificate
if (process.env.CLAUDE_CODE_CLIENT_CERT) {
try {
config.cert = getFsImplementation().readFileSync(
process.env.CLAUDE_CODE_CLIENT_CERT,
{ encoding: 'utf8' },
)
logForDebugging(
'mTLS: Loaded client certificate from CLAUDE_CODE_CLIENT_CERT',
)
} catch (error) {
logForDebugging(`mTLS: Failed to load client certificate: ${error}`, {
level: 'error',
})
}
}
// Client key
if (process.env.CLAUDE_CODE_CLIENT_KEY) {
try {
config.key = getFsImplementation().readFileSync(
process.env.CLAUDE_CODE_CLIENT_KEY,
{ encoding: 'utf8' },
)
logForDebugging('mTLS: Loaded client key from CLAUDE_CODE_CLIENT_KEY')
} catch (error) {
logForDebugging(`mTLS: Failed to load client key: ${error}`, {
level: 'error',
})
}
}
// Key passphrase
if (process.env.CLAUDE_CODE_CLIENT_KEY_PASSPHRASE) {
config.passphrase = process.env.CLAUDE_CODE_CLIENT_KEY_PASSPHRASE
logForDebugging('mTLS: Using client key passphrase')
}
// Only return config if at least one option is set
if (Object.keys(config).length === 0) {
return undefined
}
return config
})
/**
* Create an HTTPS agent with mTLS configuration
*/
export const getMTLSAgent = memoize((): HttpsAgent | undefined => {
const mtlsConfig = getMTLSConfig()
const caCerts = getCACertificates()
if (!mtlsConfig && !caCerts) {
return undefined
}
const agentOptions: https.AgentOptions = {
...mtlsConfig,
...(caCerts && { ca: caCerts }),
// Enable keep-alive for better performance
keepAlive: true,
}
logForDebugging('mTLS: Creating HTTPS agent with custom certificates')
return new HttpsAgent(agentOptions)
})
/**
* Get TLS options for WebSocket connections
*/
export function getWebSocketTLSOptions(): tls.ConnectionOptions | undefined {
const mtlsConfig = getMTLSConfig()
const caCerts = getCACertificates()
if (!mtlsConfig && !caCerts) {
return undefined
}
return {
...mtlsConfig,
...(caCerts && { ca: caCerts }),
}
}
/**
* Get fetch options with TLS configuration (mTLS + CA certs) for undici
*/
export function getTLSFetchOptions(): {
tls?: TLSConfig
dispatcher?: undici.Dispatcher
} {
const mtlsConfig = getMTLSConfig()
const caCerts = getCACertificates()
if (!mtlsConfig && !caCerts) {
return {}
}
const tlsConfig: TLSConfig = {
...mtlsConfig,
...(caCerts && { ca: caCerts }),
}
if (typeof Bun !== 'undefined') {
return { tls: tlsConfig }
}
logForDebugging('TLS: Created undici agent with custom certificates')
// Create a custom undici Agent with TLS options. Lazy-required so that
// the ~1.5MB undici package is only loaded when mTLS/CA certs are configured.
// eslint-disable-next-line @typescript-eslint/no-require-imports
const undiciMod = require('undici') as typeof undici
const agent = new undiciMod.Agent({
connect: {
cert: tlsConfig.cert,
key: tlsConfig.key,
passphrase: tlsConfig.passphrase,
...(tlsConfig.ca && { ca: tlsConfig.ca }),
},
pipelining: 1,
})
return { dispatcher: agent }
}
/**
* Clear the mTLS configuration cache.
*/
export function clearMTLSCache(): void {
getMTLSConfig.cache.clear?.()
getMTLSAgent.cache.clear?.()
logForDebugging('Cleared mTLS configuration cache')
}
/**
* Configure global Node.js TLS settings
*/
export function configureGlobalMTLS(): void {
const mtlsConfig = getMTLSConfig()
if (!mtlsConfig) {
return
}
// NODE_EXTRA_CA_CERTS is automatically handled by Node.js at runtime
if (process.env.NODE_EXTRA_CA_CERTS) {
logForDebugging(
'NODE_EXTRA_CA_CERTS detected - Node.js will automatically append to built-in CAs',
)
}
}