IDE Agent ignores terminal.integrated.defaultProfile.windows -- always uses PowerShell even with Nushell/Bash configured

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

The IDE agent on Windows ignores the configured default terminal profile and always uses PowerShell for command execution. Even with terminal.integrated.defaultProfile.windows set to a custom shell (e.g., Nushell), the agent continues spawning PowerShell. The interactive terminal respects the setting – only the agent ignores it.

Settings that were tried and confirmed to have no effect on the agent:

  • terminal.integrated.defaultProfile.windows: “Nushell” (with profile defined)
  • terminal.integrated.automationProfile.windows: path to nu.exe
  • terminal.integrated.shell.windows (deprecated): path to nu.exe
  • “Legacy Terminal Tool” toggle: ON
  • Closing all agent chats + full Cursor restart

PowerShell causes multi-second cold starts (5-30s) on every agent command and post-execution hangs of several seconds, significantly slowing down agent workflows.

Steps to Reproduce

  1. Install Nushell (or any non-standard shell)
  2. Configure in settings.json:
{
  "terminal.integrated.defaultProfile.windows": "Nushell",
  "terminal.integrated.profiles.windows": {
    "Nushell": {
      "path": "C:\\Users\\...\\nu.exe"
    }
  }
}
  1. Restart Cursor completely (quit + reopen)
  2. Open a new agent chat
  3. Ask the agent to run any shell command
  4. Observe: agent writes to ps-script-*.ps1 temp files, command runs in PowerShell
  5. Meanwhile, opening a new interactive terminal correctly uses Nushell

Expected Behavior

The agent should use the shell configured in terminal.integrated.defaultProfile.windows, matching the behavior of the interactive terminal.

Operating System

Windows 10/11

Version Information

IDE: 2.4.37

Additional Information

Root cause analysis (from examining the shared shell execution library in IDE v2.4.37, same library as CLI v2026.02.13-41ac335):

The IDE correctly resolves the shell path from VS Code settings during extension host startup:

// From workbench.desktop.main.js (extensionHost init):
let shellHint;
try {
  shellHint = await this._terminalProfileResolverService.getDefaultShell({
    allowAutomationShell: false, os: platform, remoteAuthority: undefined
  });
} catch {
  try {
    const profile = this._terminalProfileService.getDefaultProfile();
    shellHint = profile?.path;
  } catch { /* Failed to get default terminal shell path */ }
}
// Passed to agent as: { userTerminalHint: shellHint }

So userTerminalHint is correctly populated (e.g., "C:\\Users\\...\\nu.exe"). But the shell type detection function (shared with the CLI agent – identical logic) ignores it:

function detectShellType(hint) {
  const shellStr = hint || process.env.SHELL || "";
  const isWindows = process.platform === "win32";

  return shellStr.includes("zsh") ? ShellType.Zsh
    : shellStr.includes("bash") && isGitBash ? ShellType.Bash
    // On Windows, the PowerShell condition includes a system-level fallback:
    : shellStr.includes("pwsh") || shellStr.includes("powershell")
      || isWindows && (commandExists("pwsh") || commandExists("powershell"))
      ? ShellType.PowerShell
    // No check for "nu", "fish", or any other shell -- UNREACHABLE on Windows
    // because the PowerShell condition above always matches when PS is installed
    : commandExists("zsh") ? ShellType.Zsh
    : commandExists("bash") && isGitBash ? ShellType.Bash
    : commandExists("pwsh") || commandExists("powershell") ? ShellType.PowerShell
    : ShellType.Naive;
}

The hint "C:\\Users\\...\\nu.exe" doesn’t match any includes() check for zsh, bash, or powershell. Critically, on Windows, the PowerShell ternary arm combines both string matching and a system-level commandExists fallback in a single || chain. Since PowerShell is always installed on Windows, this condition evaluates to true regardless of the hint string, and ShellType.PowerShell is returned. Any shell check placed after this point is dead code on Windows.

Additionally, the executor factory’s default handler (which creates a NaiveTerminalExecutor) doesn’t wire userTerminalHint into its shell resolution – it falls back to the system PowerShell on Windows even when invoked.

Proposed fix (same as CLI – shared library):

The shell library needs two changes:

  1. Add non-standard shell recognition in detectShellType(), placed before the PowerShell condition (critical – placing it after is unreachable on Windows due to the combined includes || commandExists condition):
  : shellStr.includes("bash") && isGitBash ? ShellType.Bash
  // These must come BEFORE the PowerShell check:
  : shellStr.includes("nu") ? ShellType.Naive
  : shellStr.includes("fish") ? ShellType.Naive
  : shellStr.length > 0 ? ShellType.Naive  // trust any explicit user config
  // Then the existing PowerShell check:
  : shellStr.includes("pwsh") || shellStr.includes("powershell")
    || isWindows && (commandExists("pwsh") || commandExists("powershell"))
    ? ShellType.PowerShell
  : /* existing fallback chain */
  1. Wire userTerminalHint into the executor factory’s default handler’s shell resolution, and/or add an explicit ShellType.Naive case using the existing NaiveTerminalExecutor class (which spawns shell -c "command" generically – NOT the BashStateExecutor which always requires Bash):
case ShellType.Naive:
  return new LazyExecutor(Promise.resolve(
    new NaiveTerminalExecutor(process.cwd(), {
      shell: opts.userTerminalHint || process.env.SHELL || "/bin/sh",
      ...opts
    })
  ));

No new settings are needed for the IDE – terminal.integrated.defaultProfile.windows already populates userTerminalHint correctly. It just needs to be respected by the detection function and routed to the correct executor.

Note: The CLI agent has a related but separate issue (no config mechanism for shell at all) – filed separately.

Hey, thanks for the report.

This is a known limitation in how the agent detects and picks shells. The detectShellType() function has explicit branches only for zsh, bash, and PowerShell. Everything else (nushell, fish, etc.) falls back to the system default, which on Windows always ends up being PowerShell.

I see you also created a related issue for the CLI here. It makes sense to track these separately since the input paths are different.

I’ve shared both reports with the team. The root cause analysis and the proposed fix with a general ShellType.Naive option are exactly the level of detail that helps with prioritization. No timeline yet, but your reports help raise visibility.

I’ll post an update here if there are any news.

Same underlying bug here, but in my case the agent tries WSL instead of Git Bash.

Setup: Windows, Git Bash as my default terminal (terminal.integrated.defaultProfile.windows). The integrated terminal uses Git Bash correctly; the agent does not. I only have WSL 2 for Docker Desktop’s backend — no Ubuntu or other user WSL distro. I work on Windows with Git Bash by choice.

What happens: When the agent runs a command, it doesn’t use Git Bash; it tries WSL and runs something like execvpe(/bin/bash), which fails with “No such file or directory” because I have no Ubuntu distro. So the same fix would help me: the agent should respect the default terminal profile and use Git Bash instead of falling back to PowerShell or WSL.

Please treat this as the same bug (default profile ignored) — different symptom (WSL attempted instead of Git Bash), same root cause.