import { detectPlatform, type Platform } from "./platform.ts"; import { NotifyProtocol } from "./notify-protocol.ts"; import { isInsideTmux, isInsideZellij } from "./mux.ts"; export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "warp" | "base" | "trueColor" | "windowsTerminal" | "conhost" | "unknown"; export interface TerminalCapabilities { id: TerminalId; protocol: NotifyProtocol; insideTmux: boolean; insideZellij: boolean; cmuxSurface?: string; isWsl: boolean; } function lower(value: string | undefined): string { return value?.trim().toLowerCase() ?? ""; } export function detectTerminal( env: Readonly> = process.env, platform?: Platform, readProcVersion?: () => string, ): TerminalCapabilities { const detectedPlatform = platform ?? detectPlatform(process.platform, env, readProcVersion); const program = lower(env.TERM_PROGRAM); const term = lower(env.TERM); let id: TerminalId = "base"; let protocol: NotifyProtocol = NotifyProtocol.Bell; if (program === "kitty" || term === "xterm-kitty" || env.KITTY_WINDOW_ID) { id = "kitty"; protocol = NotifyProtocol.Osc99; } else if (program === "ghostty" || env.GHOSTTY_RESOURCES_DIR) { id = "ghostty"; protocol = NotifyProtocol.Osc9; } else if (program === "wezterm" || env.WEZTERM_PANE) { id = "wezterm"; protocol = NotifyProtocol.Osc9; } else if (program === "iterm.app" || program === "iterm2" || env.ITERM_SESSION_ID || lower(env.LC_TERMINAL) === "iterm2") { id = "iterm2"; protocol = NotifyProtocol.Osc9; } else if (program === "warpterminal" || program === "warp") { id = "warp"; protocol = NotifyProtocol.Osc9; } else if (program === "vscode" || env.VSCODE_PID) { id = "vscode"; } else if (program === "alacritty" || env.ALACRITTY_WINDOW_ID) { id = "alacritty"; } else if (program === "base") { id = "base"; } else if (term.includes("ghostty")) { id = "ghostty"; protocol = NotifyProtocol.Osc9; } else if (env.WT_SESSION) { id = "windowsTerminal"; } else if (env.ConEmuANSI || program === "conhost") { id = "conhost"; } else if (lower(env.COLORTERM) === "truecolor" || lower(env.COLORTERM) === "24bit") { id = "trueColor"; } else if (detectedPlatform === "windows") { id = "conhost"; } return { id, protocol, insideTmux: isInsideTmux(env), insideZellij: isInsideZellij(env), cmuxSurface: env.CMUX_SURFACE_ID?.trim() || undefined, isWsl: detectedPlatform === "wsl", }; }