Compare commits

...
Author SHA1 Message Date
Arafatkatze 5cf04506d2 feat(terminal): add shell path matching for terminal reuse
- Add getShellPath() method to determine correct shell based on terminal profile
- Match shell path when finding available terminals for reuse
- Pass shell path when creating new terminals
- Improve shell argument detection to handle cross-platform shells
  (PowerShell, bash, zsh) regardless of platform

This ensures terminals are reused only when they have the same shell
configuration, preventing issues when switching between different
shell profiles.
2025-12-28 19:47:18 -08:00
2 changed files with 46 additions and 10 deletions
@@ -12,6 +12,7 @@
* - Provides summary for environment details
*/
import { getShell, getShellForProfile } from "@utils/shell"
import * as fs from "fs"
import * as os from "os"
import * as path from "path"
@@ -135,6 +136,18 @@ export class StandaloneTerminalManager implements ITerminalManager {
return mergePromise(process, promise)
}
/**
* Get the shell path to use for new terminals.
* Uses the configured terminal profile or falls back to the default shell.
* @returns The shell path to use
*/
private getShellPath(): string {
if (this.defaultTerminalProfile !== "default") {
return getShellForProfile(this.defaultTerminalProfile)
}
return getShell()
}
/**
* Get or create a terminal for the specified working directory.
* @param cwd The working directory for the terminal
@@ -142,12 +155,17 @@ export class StandaloneTerminalManager implements ITerminalManager {
*/
async getOrCreateTerminal(cwd: string): Promise<TerminalInfo> {
const terminals = this.registry.getAllTerminals()
const expectedShellPath = this.getShellPath()
// Find available terminal with matching CWD
// Find available terminal with matching CWD and shell path
const matchingTerminal = terminals.find((t) => {
if (t.busy) {
return false
}
// Also check shell path matches to ensure we use the correct shell
if (t.shellPath !== expectedShellPath) {
return false
}
return (t.terminal as any)._cwd === cwd
})
@@ -158,7 +176,7 @@ export class StandaloneTerminalManager implements ITerminalManager {
// Find any available terminal if reuse is enabled
if (this.terminalReuseEnabled) {
const availableTerminal = terminals.find((t) => !t.busy)
const availableTerminal = terminals.find((t) => !t.busy && t.shellPath === expectedShellPath)
if (availableTerminal) {
// Change directory
await this.runCommand(availableTerminal, `cd "${cwd}"`)
@@ -171,10 +189,11 @@ export class StandaloneTerminalManager implements ITerminalManager {
}
}
// Create new terminal
// Create new terminal with the correct shell path
const newTerminalInfo = this.registry.createTerminal({
cwd: cwd,
name: `Cline Terminal ${this.registry.size + 1}`,
shellPath: expectedShellPath,
})
this.terminalIds.add(newTerminalInfo.id)
return newTerminalInfo
@@ -310,16 +310,33 @@ export class StandaloneTerminalProcess extends EventEmitter<TerminalProcessEvent
* @returns Array of shell arguments
*/
private getShellArgs(shell: string, command: string): string[] {
if (process.platform === "win32") {
if (shell.toLowerCase().includes("powershell") || shell.toLowerCase().includes("pwsh")) {
return ["-Command", command]
} else {
return ["/c", command]
}
} else {
const shellLower = shell.toLowerCase()
// Check for PowerShell (works on all platforms)
if (shellLower.includes("powershell") || shellLower.includes("pwsh")) {
return ["-Command", command]
}
// Check for bash-like shells (Git Bash, WSL Bash, Cygwin, etc.)
// These use Unix-style arguments even on Windows
if (shellLower.includes("bash") || shellLower.includes("sh")) {
// Use -l for login shell, -c for command
return ["-l", "-c", command]
}
// Check for zsh
if (shellLower.includes("zsh")) {
return ["-l", "-c", command]
}
// Platform-specific defaults
if (process.platform === "win32") {
// Default to cmd.exe style on Windows
return ["/c", command]
} else {
// Default to Unix shell style
return ["-l", "-c", command]
}
}
/**