Problem
On Windows, the terminal backend currently hard-codes powershell.exe:
function getShell(): string {
if (process.platform === 'win32') return 'powershell.exe';
return process.env.SHELL || '/bin/bash';
}
This always starts Windows PowerShell 5.1, even when PowerShell 7 (pwsh.exe) is installed.
Because PowerShell 5.1 and PowerShell 7 can coexist, users who have PowerShell 7 installed may reasonably expect the terminal plugin to use the newer version by default.
Expected behavior
On Windows, the plugin should automatically select a PowerShell executable using a priority similar to:
- An explicitly configured shell path or environment variable
- The highest installed stable PowerShell 7 version
pwsh.exe available through PATH
- Windows PowerShell 5.1 (
powershell.exe) as a fallback
This would preserve compatibility for users who only have Windows PowerShell while allowing PowerShell 7 users to get the newer shell automatically.
Suggested configuration override
It would also be useful to support an environment variable such as:
For example:
$env:CLOUDCLI_TERMINAL_SHELL = 'C:\Program Files\PowerShell\7\pwsh.exe'
This gives users a reliable way to select another shell, including PowerShell Preview, Git Bash, Nushell, or a custom executable.
Suggested implementation
A Windows shell resolver could:
- Check
CLOUDCLI_TERMINAL_SHELL first
- Search standard PowerShell installation directories
- Detect versioned directories under
Program Files\PowerShell
- Prefer the highest stable installed version
- Check
pwsh.exe through PATH
- Fall back to
powershell.exe
Example implementation:
import path from 'node:path';
import fs from 'node:fs';
import { execFileSync } from 'node:child_process';
function findExecutableInPath(executable: string): string | undefined {
try {
const output = execFileSync('where.exe', [executable], {
encoding: 'utf8',
windowsHide: true,
stdio: ['ignore', 'pipe', 'ignore'],
});
return output
.split(/\r?\n/)
.map((entry) => entry.trim())
.find(Boolean);
} catch {
return undefined;
}
}
function parseVersionDirectory(name: string): number[] | undefined {
if (!/^\d+(?:\.\d+)*$/.test(name)) return undefined;
return name.split('.').map((part) => Number.parseInt(part, 10));
}
function compareVersionsDescending(a: number[], b: number[]): number {
const length = Math.max(a.length, b.length);
for (let index = 0; index < length; index++) {
const difference = (b[index] ?? 0) - (a[index] ?? 0);
if (difference !== 0) return difference;
}
return 0;
}
function findHighestInstalledPowerShell(): string | undefined {
const programFiles = process.env.ProgramFiles || 'C:\\Program Files';
const powerShellRoot = path.join(programFiles, 'PowerShell');
try {
const candidates = fs.readdirSync(powerShellRoot, {
withFileTypes: true,
})
.filter((entry) => entry.isDirectory())
.map((entry) => ({
name: entry.name,
version: parseVersionDirectory(entry.name),
}))
.filter(
(
entry,
): entry is {
name: string;
version: number[];
} => Boolean(entry.version),
)
.sort((a, b) => compareVersionsDescending(a.version, b.version))
.map((entry) =>
path.join(powerShellRoot, entry.name, 'pwsh.exe'),
)
.find((candidate) => fs.existsSync(candidate));
return candidates;
} catch {
return undefined;
}
}
function getWindowsShell(): string {
const configuredShell =
process.env.CLOUDCLI_TERMINAL_SHELL?.trim();
if (configuredShell) {
return configuredShell;
}
return (
findHighestInstalledPowerShell()
|| findExecutableInPath('pwsh.exe')
|| findExecutableInPath('powershell.exe')
|| 'powershell.exe'
);
}
function getShell(): string {
if (process.platform === 'win32') {
return getWindowsShell();
}
return process.env.SHELL || '/bin/bash';
}
Additional considerations
Stable versus preview releases
PowerShell Preview is often installed in a separate directory such as:
C:\Program Files\PowerShell\7-preview\pwsh.exe
I suggest preferring stable numeric version directories by default. Preview versions could still be selected explicitly through CLOUDCLI_TERMINAL_SHELL.
Validation
The selected shell could be exposed through the existing /info endpoint, making the behavior easy to verify.
Possible Windows test cases:
- Only Windows PowerShell 5.1 installed
- PowerShell 7 installed and available through
PATH
- PowerShell 7 installed but absent from
PATH
- Multiple PowerShell 7 versions installed
- Stable and Preview versions installed together
- Explicit shell override configured
- Invalid override path
- Installation path containing spaces
Benefits
- Uses PowerShell 7 automatically when available
- Preserves support for Windows PowerShell 5.1
- Avoids a Windows-specific hard-coded shell choice
- Supports custom shells without editing and rebuilding the plugin
- Makes behavior more predictable across different Windows environments
Problem
On Windows, the terminal backend currently hard-codes
powershell.exe:This always starts Windows PowerShell 5.1, even when PowerShell 7 (
pwsh.exe) is installed.Because PowerShell 5.1 and PowerShell 7 can coexist, users who have PowerShell 7 installed may reasonably expect the terminal plugin to use the newer version by default.
Expected behavior
On Windows, the plugin should automatically select a PowerShell executable using a priority similar to:
pwsh.exeavailable throughPATHpowershell.exe) as a fallbackThis would preserve compatibility for users who only have Windows PowerShell while allowing PowerShell 7 users to get the newer shell automatically.
Suggested configuration override
It would also be useful to support an environment variable such as:
For example:
This gives users a reliable way to select another shell, including PowerShell Preview, Git Bash, Nushell, or a custom executable.
Suggested implementation
A Windows shell resolver could:
CLOUDCLI_TERMINAL_SHELLfirstProgram Files\PowerShellpwsh.exethroughPATHpowershell.exeExample implementation:
Additional considerations
Stable versus preview releases
PowerShell Preview is often installed in a separate directory such as:
I suggest preferring stable numeric version directories by default. Preview versions could still be selected explicitly through
CLOUDCLI_TERMINAL_SHELL.Validation
The selected shell could be exposed through the existing
/infoendpoint, making the behavior easy to verify.Possible Windows test cases:
PATHPATHBenefits