Scope user-terminal credential guard to Windows, add settings toggle, forward guard into WSL (#7652)

This commit is contained in:
Brennan Benson
2026-07-10 17:28:09 -07:00
parent 085b4e5651
commit 57e7ce2490
16 changed files with 286 additions and 48 deletions
+41
View File
@@ -218,3 +218,44 @@ describe('nonInteractiveGitEnv credential-interactivity disable (STA-1292)', ()
expect(env.GIT_SSH_COMMAND).toBe('ssh -o BatchMode=yes')
})
})
describe('guard-env WSLENV forwarding (#7652)', () => {
it('registers the guard vars in WSLENV on Windows so WSL-routed git imports them', () => {
const env = promptGuardGitEnv({ PATH: '/usr/bin' }, 'win32')
const keys = (env.WSLENV ?? '').split(':')
expect(keys).toContain('GIT_TERMINAL_PROMPT')
expect(keys).toContain('GCM_INTERACTIVE')
expect(keys).toContain('GIT_CONFIG_COUNT')
expect(keys).toContain('GIT_CONFIG_KEY_0')
expect(keys).toContain('GIT_CONFIG_VALUE_0')
expect(keys).toContain('GIT_CONFIG_KEY_1')
expect(keys).toContain('GIT_CONFIG_VALUE_1')
// Windows askpass paths are meaningless inside a distro.
expect(keys).not.toContain('GIT_ASKPASS')
expect(keys).not.toContain('SSH_ASKPASS')
})
it('preserves a caller-set WSLENV instead of clobbering it', () => {
const env = promptGuardGitEnv({ PATH: '/usr/bin', WSLENV: 'MY_VAR/p' }, 'win32')
const keys = (env.WSLENV ?? '').split(':')
expect(keys[0]).toBe('MY_VAR/p')
expect(keys).toContain('GIT_TERMINAL_PROMPT')
})
it('does not touch WSLENV on non-Windows hosts', () => {
const env = promptGuardGitEnv({ PATH: '/usr/bin' }, 'darwin')
expect(env.WSLENV).toBeUndefined()
})
it('forwards GIT_SSH_COMMAND only when nonInteractiveGitEnv set the default itself', () => {
const defaulted = nonInteractiveGitEnv({ PATH: '/usr/bin' }, 'win32')
expect((defaulted.WSLENV ?? '').split(':')).toContain('GIT_SSH_COMMAND')
// A caller's Windows-specific ssh command must not leak into the distro.
const callerSet = nonInteractiveGitEnv(
{ PATH: '/usr/bin', GIT_SSH_COMMAND: 'C:\\ssh\\ssh.exe' },
'win32'
)
expect((callerSet.WSLENV ?? '').split(':')).not.toContain('GIT_SSH_COMMAND')
})
})
+32 -4
View File
@@ -29,6 +29,7 @@ import {
notifyGhPrimaryRateLimit
} from './gh-rate-limit-breaker'
import { getDefaultWslDistro, parseWslPath, toWindowsWslPath, type WslPathInfo } from '../wsl'
import { addWslEnvKeys } from '../wsl-env'
import { getSpawnArgsForWindows, isWindowsBatchScript, resolveWindowsCommand } from '../win32-utils'
import {
buildWslLoginShellCommand,
@@ -560,8 +561,13 @@ export function appendGitConfigEnv(
return next
}
export function promptGuardGitEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
return appendGitConfigEnv(
const GIT_CONFIG_WSLENV_KEY_RE = /^GIT_CONFIG_(?:COUNT|KEY_\d+|VALUE_\d+)$/
export function promptGuardGitEnv(
env: NodeJS.ProcessEnv = process.env,
platform: NodeJS.Platform = process.platform
): NodeJS.ProcessEnv {
const next = appendGitConfigEnv(
{
...env,
GIT_TERMINAL_PROMPT: '0',
@@ -580,6 +586,19 @@ export function promptGuardGitEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.
['credential.guiPrompt', 'false']
]
)
if (platform === 'win32') {
// Why: wsl.exe only imports env vars named in WSLENV, so WSL-routed git
// would never see the guard — and WSL setups commonly use the Windows
// credential manager as git's helper, which pops the same OAuth window
// (issue #7652). Askpass vars are deliberately not forwarded: a Windows
// askpass path is meaningless inside the distro.
addWslEnvKeys(next, [
'GIT_TERMINAL_PROMPT',
'GCM_INTERACTIVE',
...Object.keys(next).filter((key) => GIT_CONFIG_WSLENV_KEY_RE.test(key))
])
}
return next
}
/**
@@ -597,10 +616,19 @@ export function promptGuardGitEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.
* (an unknown host still errors, it just won't hang). Only added when the
* caller hasn't set its own GIT_SSH_COMMAND.
*/
export function nonInteractiveGitEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
const next = promptGuardGitEnv(env)
export function nonInteractiveGitEnv(
env: NodeJS.ProcessEnv = process.env,
platform: NodeJS.Platform = process.platform
): NodeJS.ProcessEnv {
const next = promptGuardGitEnv(env, platform)
if (!next.GIT_SSH_COMMAND) {
next.GIT_SSH_COMMAND = 'ssh -o BatchMode=yes'
if (platform === 'win32') {
// Why: forward across the WSL boundary only when we set the value —
// plain `ssh` resolves inside the distro, whereas a caller's
// Windows-specific GIT_SSH_COMMAND must not leak into Linux git.
addWslEnvKeys(next, ['GIT_SSH_COMMAND'])
}
}
return next
}
+4 -3
View File
@@ -511,9 +511,10 @@ export type BuildPtyHostEnvOptions = {
isWsl?: boolean
agentStatusHooksEnabled: boolean
networkProxySettings?: NetworkProxySettings
/** When true (the default at the call sites), a user terminal's git cannot
* pop the OS credential helper's interactive OAuth window (issue #7652).
* Agent terminals are always guarded regardless of this flag. */
/** When true (the default at the call sites), a user terminal's git on a
* Windows host cannot pop Git Credential Manager's interactive OAuth window
* (issue #7652). No effect on non-Windows hosts; agent terminals are always
* guarded on every platform regardless of this flag. */
suppressUserTerminalGitCredentialPrompt?: boolean
}
@@ -7,32 +7,67 @@ function isGuarded(env: Record<string, string>): boolean {
}
describe('applyTerminalGitCredentialPromptGuard', () => {
it('guards an agent terminal even when user-terminal suppression is off', () => {
const env: Record<string, string> = { PATH: '/usr/bin' }
applyTerminalGitCredentialPromptGuard(env, {
launchCommand: 'claude',
suppressUserTerminalPrompt: false
})
expect(isGuarded(env)).toBe(true)
// Never empties the credential helper — cached auth must keep working.
expect(env.GIT_CONFIG_COUNT).toBeDefined()
expect(Object.values(env)).not.toContain('credential.helper')
it('guards an agent terminal on every platform, even when user-terminal suppression is off', () => {
for (const platform of ['win32', 'darwin', 'linux'] as const) {
const env: Record<string, string> = { PATH: '/usr/bin' }
applyTerminalGitCredentialPromptGuard(env, {
launchCommand: 'claude',
suppressUserTerminalPrompt: false,
platform
})
expect(isGuarded(env), platform).toBe(true)
// Never empties the credential helper — cached auth must keep working.
expect(env.GIT_CONFIG_COUNT).toBeDefined()
expect(Object.values(env)).not.toContain('credential.helper')
}
})
it('guards a plain user terminal by default (suppression on)', () => {
it('guards a plain user terminal by default on a Windows host', () => {
const env: Record<string, string> = { PATH: '/usr/bin' }
applyTerminalGitCredentialPromptGuard(env, {
launchCommand: undefined,
suppressUserTerminalPrompt: true
suppressUserTerminalPrompt: true,
platform: 'win32'
})
expect(isGuarded(env)).toBe(true)
})
it('leaves a plain user terminal untouched when the user opts out', () => {
it('registers the guard in WSLENV on Windows so WSL-routed git sees it too', () => {
const env: Record<string, string> = { PATH: '/usr/bin' }
applyTerminalGitCredentialPromptGuard(env, {
launchCommand: undefined,
suppressUserTerminalPrompt: true,
platform: 'win32'
})
const wslenvKeys = (env.WSLENV ?? '').split(':')
expect(wslenvKeys).toContain('GIT_TERMINAL_PROMPT')
expect(wslenvKeys).toContain('GCM_INTERACTIVE')
expect(wslenvKeys).toContain('GIT_CONFIG_COUNT')
expect(wslenvKeys).toContain('GIT_CONFIG_KEY_0')
expect(wslenvKeys).toContain('GIT_CONFIG_VALUE_0')
// Windows askpass paths are meaningless inside a distro.
expect(wslenvKeys).not.toContain('GIT_ASKPASS')
expect(wslenvKeys).not.toContain('SSH_ASKPASS')
})
it('leaves a user terminal untouched on non-Windows hosts — no popup exists there, only working tty prompts', () => {
for (const platform of ['darwin', 'linux'] as const) {
const env: Record<string, string> = { PATH: '/usr/bin' }
applyTerminalGitCredentialPromptGuard(env, {
launchCommand: '/bin/zsh',
suppressUserTerminalPrompt: true,
platform
})
expect(env, platform).toEqual({ PATH: '/usr/bin' })
}
})
it('leaves a Windows user terminal untouched when the user opts out', () => {
const env: Record<string, string> = { PATH: '/usr/bin' }
applyTerminalGitCredentialPromptGuard(env, {
launchCommand: '/bin/zsh',
suppressUserTerminalPrompt: false
suppressUserTerminalPrompt: false,
platform: 'win32'
})
expect(env.GIT_TERMINAL_PROMPT).toBeUndefined()
expect(env.GCM_INTERACTIVE).toBeUndefined()
+14 -5
View File
@@ -10,20 +10,29 @@ import { recognizeAgentProcessFromCommandLine } from '../../shared/agent-process
*
* The credential *helper* is kept, so cached-token auth still works; only the
* interactive fallback prompt is suppressed. Agent terminals are always guarded
* (they can't dismiss a GUI popup); user terminals are guarded unless the user
* opted out via settings.
* on every platform (an agent can't answer a prompt, so failing fast beats
* hanging). User terminals are only guarded on Windows terminal hosts — the
* popup is a Windows credential-manager behavior, and on other platforms the
* guard would only take working tty prompts away from an interactive user —
* and the user can opt out via settings.
*
* Mutates `env` in place to match how the PTY host assembles its environment.
*/
export function applyTerminalGitCredentialPromptGuard(
env: Record<string, string>,
opts: { launchCommand?: string | null; suppressUserTerminalPrompt: boolean }
opts: {
launchCommand?: string | null
suppressUserTerminalPrompt: boolean
/** Injectable for tests; defaults to the spawning host's platform. */
platform?: NodeJS.Platform
}
): void {
const isAgentTerminal = Boolean(recognizeAgentProcessFromCommandLine(opts.launchCommand))
if (!isAgentTerminal && !opts.suppressUserTerminalPrompt) {
const platform = opts.platform ?? process.platform
if (!isAgentTerminal && (!opts.suppressUserTerminalPrompt || platform !== 'win32')) {
return
}
for (const [key, value] of Object.entries(promptGuardGitEnv(env))) {
for (const [key, value] of Object.entries(promptGuardGitEnv(env, platform))) {
if (typeof value === 'string') {
env[key] = value
}
@@ -36,6 +36,7 @@ describe('TerminalAdvancedSection scrollback rows', () => {
setScrollbackMode={vi.fn()}
searchQuery=""
showWindowsPowerShellImplementation={false}
showWindowsGitCredentialGuard={false}
isMac={false}
/>
)
@@ -10,12 +10,16 @@ import { ToggleGroup, ToggleGroupItem } from '../ui/toggle-group'
import {
SettingsRow,
SettingsSegmentedControl,
SettingsSubsectionHeader
SettingsSubsectionHeader,
SettingsSwitchRow
} from './SettingsFormControls'
import { SCROLLBACK_PRESETS_ROWS } from './SettingsConstants'
import { SearchableSetting } from './SearchableSetting'
import { matchesSettingsSearch } from './settings-search'
import { getTerminalWindowsPowershellImplementationSearchEntry } from './terminal-windows-search'
import {
getTerminalGitCredentialPopupSearchEntry,
getTerminalWindowsPowershellImplementationSearchEntry
} from './terminal-windows-search'
import { TerminalMacKeyboardSection } from './TerminalMacKeyboardSection'
import { translate } from '@/i18n/i18n'
@@ -26,6 +30,9 @@ type TerminalAdvancedSectionProps = {
setScrollbackMode: (mode: 'preset' | 'custom') => void
searchQuery: string
showWindowsPowerShellImplementation: boolean
/** Windows terminal hosts only — the popup this guards against is a Windows
* credential-manager behavior (issue #7652). */
showWindowsGitCredentialGuard: boolean
pwshAvailable?: boolean
isMac: boolean
}
@@ -41,6 +48,7 @@ export function TerminalAdvancedSection({
setScrollbackMode,
searchQuery,
showWindowsPowerShellImplementation,
showWindowsGitCredentialGuard,
pwshAvailable,
isMac
}: TerminalAdvancedSectionProps): React.JSX.Element {
@@ -296,6 +304,40 @@ export function TerminalAdvancedSection({
</SearchableSetting>
) : null}
{showWindowsGitCredentialGuard &&
matchesSettingsSearch(searchQuery, getTerminalGitCredentialPopupSearchEntry()) ? (
<SearchableSetting
title={translate(
'auto.components.settings.terminal.windows.search.8630676830',
'Block Git Credential Popups'
)}
description={translate(
'auto.components.settings.terminal.windows.search.9d8b09bc09',
'Stop git in terminals from opening Git Credential Manager sign-in windows.'
)}
keywords={['git', 'credential', 'popup', 'oauth', 'github', 'sign in', 'gcm', 'prompt']}
>
<SettingsSwitchRow
label={translate(
'auto.components.settings.terminal.windows.search.8630676830',
'Block Git Credential Popups'
)}
description={translate(
'auto.components.settings.TerminalPane.3fab0f2239',
'Stop git in user terminals from opening Git Credential Manager sign-in windows. Saved credentials still work; git fails fast instead of prompting. Applies to new terminals.'
)}
checked={settings.terminalSuppressGitCredentialPrompt ?? true}
onChange={() =>
updateSettings({
terminalSuppressGitCredentialPrompt: !(
settings.terminalSuppressGitCredentialPrompt ?? true
)
})
}
/>
</SearchableSetting>
) : null}
{isMac ? (
<TerminalMacKeyboardSection settings={settings} updateSettings={updateSettings} />
) : null}
@@ -13,6 +13,7 @@ import {
getTerminalSetupScriptSearchEntries
} from './terminal-search'
import {
getTerminalGitCredentialPopupSearchEntry,
getTerminalRightClickToPasteSearchEntry,
getTerminalWindowsPowershellImplementationSearchEntry,
getTerminalWindowsShellSearchEntry
@@ -104,6 +105,8 @@ export function TerminalPane({
searchQuery,
getTerminalWindowsPowershellImplementationSearchEntry()
)) ||
(showWindowsHostSettings &&
matchesSettingsSearch(searchQuery, getTerminalGitCredentialPopupSearchEntry())) ||
(isMac &&
(matchesSettingsSearch(searchQuery, getTerminalMacOptionSearchEntries()) ||
matchesSettingsSearch(searchQuery, getTerminalMacYenSearchEntries()))) ? (
@@ -115,6 +118,7 @@ export function TerminalPane({
setScrollbackMode={setScrollbackMode}
searchQuery={searchQuery}
showWindowsPowerShellImplementation={showWindowsPowerShellImplementation}
showWindowsGitCredentialGuard={showWindowsHostSettings}
pwshAvailable={pwshAvailable}
isMac={isMac}
/>
@@ -140,8 +140,68 @@ export const getTerminalRightClickToPasteSearchEntry = createLocalizedCatalog(()
}
])
export const getTerminalGitCredentialPopupSearchEntry = createLocalizedCatalog(() => [
{
title: translate(
'auto.components.settings.terminal.windows.search.8630676830',
'Block Git Credential Popups'
),
description: translate(
'auto.components.settings.terminal.windows.search.9d8b09bc09',
'Stop git in terminals from opening Git Credential Manager sign-in windows.'
),
keywords: [
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.e7d2793b03',
'terminal'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.28ff08ed35',
'windows'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.ba9f11ecc3',
'git'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.7c7c74ef60',
'credential'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.8eff361700',
'popup'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.7c82e855b0',
'oauth'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.bf215181b5',
'github'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.b19a25c6a0',
'sign in'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.ef5acdb939',
'gcm'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.4ae35dbb42',
'prompt'
),
...translateSearchKeyword(
'auto.components.settings.terminal.windows.search.27e4a4878d',
'credential manager'
)
]
}
])
export const getTerminalWindowsSearchEntries = createLocalizedCatalog((): SettingsSearchEntry[] => [
...getTerminalWindowsShellSearchEntry(),
...getTerminalWindowsPowershellImplementationSearchEntry(),
...getTerminalRightClickToPasteSearchEntry()
...getTerminalRightClickToPasteSearchEntry(),
...getTerminalGitCredentialPopupSearchEntry()
])
+5 -2
View File
@@ -6678,7 +6678,8 @@
"fastDescription": "Extra multiplier while scrolling with a modifier key.",
"tui": "TUI",
"tuiDescription": "Discrete wheel reports for full-screen terminal apps."
}
},
"3fab0f2239": "Stop git in user terminals from opening Git Credential Manager sign-in windows. Saved credentials still work; git fails fast instead of prompting. Applies to new terminals."
},
"TerminalSettingsPreview": {
"a63953a48a": "Preview {{value0}} theme",
@@ -8397,7 +8398,9 @@
"6cd20b9e64": "cmd",
"7c7056940a": "shell",
"713c4a2f92": "Choose the default shell for new terminal panes on Windows.",
"13715f9d23": "Default Shell"
"13715f9d23": "Default Shell",
"8630676830": "Block Git Credential Popups",
"9d8b09bc09": "Stop git in terminals from opening Git Credential Manager sign-in windows."
}
}
},
+5 -2
View File
@@ -6641,7 +6641,8 @@
"fastDescription": "Multiplicador adicional al desplazarse con una tecla modificadora.",
"tui": "TUI",
"tuiDescription": "Eventos discretos de rueda para apps de terminal de pantalla completa."
}
},
"3fab0f2239": "Stop git in user terminals from opening Git Credential Manager sign-in windows. Saved credentials still work; git fails fast instead of prompting. Applies to new terminals."
},
"TerminalSettingsPreview": {
"a63953a48a": "Vista previa del tema {{value0}}",
@@ -8360,7 +8361,9 @@
"6cd20b9e64": "cmd",
"7c7056940a": "shell",
"713c4a2f92": "Elija el shell predeterminado para los nuevos paneles de terminal en Windows.",
"13715f9d23": "Shell predeterminado"
"13715f9d23": "Shell predeterminado",
"8630676830": "Block Git Credential Popups",
"9d8b09bc09": "Stop git in terminals from opening Git Credential Manager sign-in windows."
}
}
},
+5 -2
View File
@@ -6663,7 +6663,8 @@
"fastDescription": "修飾キーを押しながらスクロールするときの追加倍率。",
"tui": "TUI",
"tuiDescription": "全画面ターミナルアプリ向けの離散的なホイール通知。"
}
},
"3fab0f2239": "Stop git in user terminals from opening Git Credential Manager sign-in windows. Saved credentials still work; git fails fast instead of prompting. Applies to new terminals."
},
"TerminalSettingsPreview": {
"a63953a48a": "{{value0}} テーマのプレビュー",
@@ -8382,7 +8383,9 @@
"6cd20b9e64": "cmd",
"7c7056940a": "シェル",
"713c4a2f92": "Windows 上の新規 terminal ペインのデフォルト シェルを選択します。",
"13715f9d23": "デフォルトのシェル"
"13715f9d23": "デフォルトのシェル",
"8630676830": "Block Git Credential Popups",
"9d8b09bc09": "Stop git in terminals from opening Git Credential Manager sign-in windows."
}
}
},
+5 -2
View File
@@ -6626,7 +6626,8 @@
"fastDescription": "수정 키로 스크롤할 때 적용되는 추가 배율.",
"tui": "TUI",
"tuiDescription": "전체 화면 터미널 앱을 위한 개별 휠 보고."
}
},
"3fab0f2239": "Stop git in user terminals from opening Git Credential Manager sign-in windows. Saved credentials still work; git fails fast instead of prompting. Applies to new terminals."
},
"TerminalSettingsPreview": {
"a63953a48a": "{{value0}} 테마 미리보기",
@@ -8345,7 +8346,9 @@
"6cd20b9e64": "cmd",
"7c7056940a": "셸",
"713c4a2f92": "Windows의 새 terminal 패널에 대한 기본 셸을 선택합니다.",
"13715f9d23": "기본 쉘"
"13715f9d23": "기본 쉘",
"8630676830": "Block Git Credential Popups",
"9d8b09bc09": "Stop git in terminals from opening Git Credential Manager sign-in windows."
}
}
},
+5 -2
View File
@@ -6626,7 +6626,8 @@
"fastDescription": "按住修饰键滚动时的额外倍数。",
"tui": "TUI",
"tuiDescription": "面向全屏终端应用的离散滚轮报告。"
}
},
"3fab0f2239": "Stop git in user terminals from opening Git Credential Manager sign-in windows. Saved credentials still work; git fails fast instead of prompting. Applies to new terminals."
},
"TerminalSettingsPreview": {
"a63953a48a": "预览 {{value0}} 主题",
@@ -8345,7 +8346,9 @@
"6cd20b9e64": "指令",
"7c7056940a": "shell",
"713c4a2f92": "为 Windows 上的新终端窗格选择默认 Shell。",
"13715f9d23": "默认 Shell"
"13715f9d23": "默认 Shell",
"8630676830": "Block Git Credential Popups",
"9d8b09bc09": "Stop git in terminals from opening Git Credential Manager sign-in windows."
}
}
},
+3 -3
View File
@@ -252,9 +252,9 @@ export function getDefaultSettings(homedir: string): GlobalSettings {
// is installed, with a safe fallback to the inbox Windows PowerShell.
terminalWindowsPowerShellImplementation: 'auto',
terminalMouseHideWhileTyping: false,
// Default on: suppress the OS credential helper's interactive OAuth popup
// for git in user terminals (issue #7652). Agent/automated contexts are
// guarded regardless of this setting.
// Default on: suppress Git Credential Manager's interactive OAuth popup
// for git in user terminals on Windows hosts (issue #7652). No effect on
// other platforms; agent/automated contexts are guarded regardless.
terminalSuppressGitCredentialPrompt: true,
terminalQuickCommands: getDefaultTerminalQuickCommands(),
// Default false: opt-in only (matches Ghostty's default). Existing users
+8 -6
View File
@@ -2554,12 +2554,14 @@ export type GlobalSettings = {
terminalPaddingX?: number
terminalPaddingY?: number
terminalMouseHideWhileTyping?: boolean
/** When on (default), git run in a user terminal cannot pop the OS credential
* helper's interactive OAuth window (e.g. Git Credential Manager's "Connect
* to GitHub" popup) — it uses cached credentials or fails fast instead of
* looping in network-restricted environments (issue #7652). Agent terminals
* and Orca-run setup scripts are always guarded regardless of this setting.
* Turn off to let your interactive terminal prompt via the OS helper. */
/** When on (default), git run in a user terminal on a Windows terminal host
* cannot pop Git Credential Manager's interactive OAuth window ("Connect to
* GitHub") — it uses cached credentials or fails fast instead of looping in
* network-restricted environments (issue #7652). Only applies on Windows
* hosts: the popup is a Windows credential-manager behavior, and elsewhere
* the guard would only remove working tty prompts. Agent terminals and
* Orca-run setup scripts are always guarded on every platform regardless of
* this setting. Turn off to let your terminal prompt via the OS helper. */
terminalSuppressGitCredentialPrompt?: boolean
terminalWordSeparator?: string
terminalCursorOpacity?: number