@victor-software-house/pi-terminal-env
Tiny zero-dep helpers to detect the terminal emulator pi is running in (iTerm2, tmux, etc.). Pure env-var probes, no I/O.
Package details
Install @victor-software-house/pi-terminal-env from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@victor-software-house/pi-terminal-env- Package
@victor-software-house/pi-terminal-env- Version
0.1.3- Published
- May 13, 2026
- Downloads
- 65/mo · 8/wk
- Author
- victor-founder
- License
- MIT
- Types
- package
- Size
- 22.3 KB
- Dependencies
- 0 dependencies · 0 peers
Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@victor-software-house/pi-terminal-env
Tiny zero-dependency probes for detecting the terminal emulator pi is running in. Pure synchronous env-var checks — no I/O, no binary probing, no side effects. Safe to call at module load time from pi extensions, CLIs, postinstall scripts, anywhere.
Every detector cites the env var(s) it relies on and (where available) the vendor source for that signal. When a terminal exposes multiple signals, the detector OR-checks them so it works across:
- direct GUI launches (every var present),
- SSH sessions where the GUI emulator's vars may be stripped,
- tmux / screen passthrough where
TERMis rewritten.
Install
pnpm add @victor-software-house/pi-terminal-env
Usage
import {
isIterm2,
isCmux,
isTmux,
isSsh,
terminalProgram,
} from "@victor-software-house/pi-terminal-env";
if (isIterm2()) {
// safe to send iTerm2-specific OSC sequences, call it2api, etc.
}
if (isCmux()) {
// open the cmux Unix socket, send surface-rename or trigger-flash commands
}
if (!isTmux()) {
// register /tmux-promote, etc.
}
console.log(terminalProgram()); // "iTerm2" | "cmux" | "Ghostty" | ...
API
GUI emulators
| Export | Signals checked |
|---|---|
isIterm2() |
TERM_PROGRAM=iTerm.app · LC_TERMINAL=iTerm2 · ITERM_SESSION_ID |
isAppleTerminal() |
TERM_PROGRAM=Apple_Terminal |
isCmux() |
CMUX_BUNDLE_ID=com.cmuxterm.app · CMUX_SOCKET_PATH · CMUX_WORKSPACE_ID · CMUX_SURFACE_ID |
isGhostty() |
TERM_PROGRAM=ghostty · GHOSTTY_RESOURCES_DIR · TERM=xterm-ghostty. Also true inside cmux (cmux embeds Ghostty); use isCmux() first when the distinction matters. |
isWezTerm() |
TERM_PROGRAM=WezTerm · WEZTERM_EXECUTABLE · WEZTERM_PANE |
isAlacritty() |
ALACRITTY_SOCKET · ALACRITTY_LOG · ALACRITTY_WINDOW_ID · TERM=alacritty |
isKitty() |
KITTY_PID · KITTY_WINDOW_ID · KITTY_INSTALLATION_DIR · TERM=xterm-kitty |
isKonsole() |
KONSOLE_VERSION · KONSOLE_DBUS_SERVICE · KONSOLE_PROFILE_NAME |
isHyper() |
TERM_PROGRAM=Hyper |
isWarp() |
TERM_PROGRAM=WarpTerminal |
isWindowsTerminal() |
WT_SESSION · WT_PROFILE_ID |
isConEmu() |
ConEmuPID · ConEmuANSI · ConEmuBaseDir · TERM_PROGRAM=ConEmu |
isMintty() |
TERM_PROGRAM=mintty · MSYSCON=mintty.exe |
isTermux() |
TERMUX_VERSION · PREFIX rooted under /data/data/com.termux |
isFoot() |
TERM starts with foot |
isRio() |
TERM_PROGRAM=rio · TERM=rio |
IDE-integrated terminals
| Export | Signals checked |
|---|---|
isVSCode() |
TERM_PROGRAM=vscode · VSCODE_PID · VSCODE_INJECTION |
isCursor() |
TERM_PROGRAM=Cursor |
isJetBrains() |
TERMINAL_EMULATOR=JetBrains-JediTerm |
VTE-family (GNOME stack)
| Export | Signals checked |
|---|---|
isGnomeTerminal() |
TERM_PROGRAM=gnome-terminal · gnome-terminal-server |
isMateTerminal() |
TERM_PROGRAM=mate-terminal |
isXfceTerminal() |
TERM_PROGRAM=xfce4-terminal |
isTerminator() |
TERM_PROGRAM=terminator |
isVTE() |
VTE_VERSION (any VTE-based terminal — broadest VTE check) |
Multiplexers
| Export | Signals checked |
|---|---|
isTmux() |
TMUX · TERM starts with tmux |
isScreen() |
STY · TERM starts with screen (and not in tmux) |
isZellij() |
ZELLIJ · ZELLIJ_PANE_ID |
isMultiplexer() |
isTmux() ∨ isScreen() ∨ isZellij() |
Transport
| Export | Signals checked |
|---|---|
isSsh() |
SSH_CONNECTION · SSH_CLIENT · SSH_TTY |
Composite identification
| Export | Behavior |
|---|---|
terminalProgram(opts) |
Returns a TerminalProgram union. Defaults to the outermost GUI emulator. Pass { preferMultiplexer: true } to return the multiplexer instead. Falls back to "unknown". cmux is dispatched before Ghostty so cmux sessions are not reported as plain Ghostty. |
TerminalProgram union — exact strings returned:
type TerminalProgram =
| "iTerm2"
| "Apple_Terminal"
| "cmux"
| "Ghostty"
| "WezTerm"
| "Alacritty"
| "kitty"
| "Konsole"
| "Hyper"
| "Warp"
| "vscode"
| "Cursor"
| "JetBrains"
| "WindowsTerminal"
| "ConEmu"
| "mintty"
| "Termux"
| "foot"
| "Rio"
| "GNOME_Terminal"
| "MATE_Terminal"
| "Xfce_Terminal"
| "Terminator"
| "VTE"
| "tmux"
| "screen"
| "zellij"
| "unknown";
Reliability notes
- No subprocess, no FS, no escape-sequence round-trip. Every detector is
O(1)env-var lookup. Safe at module load. - SSH passthrough.
isIterm2()honoursLC_TERMINALso iTerm2 detection survives SSH whenSendEnv LC_*andAcceptEnv LC_*are configured. - Multiplexed sessions.
terminalProgram()returns the outer GUI emulator by default; multiplexer-inside-emulator returns the emulator. Use{ preferMultiplexer: true }to flip. - cmux vs Ghostty. cmux embeds Ghostty's terminal core, so
isGhostty()is intentionallytrueinside cmux. Always checkisCmux()beforeisGhostty()when the difference matters (socket commands, surface model, notification rings).terminalProgram()already does this dispatch. - Best-effort fallback. When no detector matches,
terminalProgram()returns"unknown"rather than guessing.
Design
- Synchronous env-only — no subprocesses, no filesystem, no network.
- Zero runtime dependencies.
- Pi-ecosystem oriented but framework-agnostic — useful in any Node CLI.
- Every detector documents the env vars it inspects so failure modes are debuggable from
printenvalone.
Status
Pre-1.0. API surface may grow; existing exports follow semver.
License
MIT