From 2125dd7aac33a7b06fdd3f97acb456baba0a1264 Mon Sep 17 00:00:00 2001 From: Emma Thorpe Date: Tue, 14 Jul 2026 16:42:41 +0100 Subject: [PATCH] fix(shell): don't exec tmux during VS Code's shell-env probe VS Code on macOS resolves the shell environment at startup by running an interactive login shell with stdout piped and no controlling terminal. The order-200 auto-tmux block treated that probe as a normal interactive shell and ran `exec tmux new-session`, which fails without a tty ("open terminal failed: not a terminal") and exits non-zero. VS Code then reports "Unable to resolve your shell environment: Unexpected exit code from spawned shell (code 1)". Gate the exec on a real terminal (-t 1) and skip it when VSCODE_RESOLVING_ENVIRONMENT is set. Real terminals still land in tmux; the integrated terminal was already exempt via TERM_PROGRAM. --- home/shell.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/home/shell.nix b/home/shell.nix index c539dc2..ecba544 100644 --- a/home/shell.nix +++ b/home/shell.nix @@ -96,6 +96,15 @@ in # runs before oh-my-zsh/compinit so the exec replaces the shell before # that setup is wasted. Guards, each preventing a real breakage: # interactive only -> don't hijack scp / `ssh host cmd` / scripted shells + # stdout is a tty -> VS Code (macOS) resolves the shell environment on + # startup by running an interactive login shell with + # stdout piped, no controlling terminal. Without this + # guard `exec tmux` runs there, fails ("open terminal + # failed: not a terminal"), exits non-zero, and VS + # Code reports "Unable to resolve your shell + # environment". A real terminal always has a tty here. + # not VS Code env -> also skip VS Code's env-resolution probe explicitly, + # in case a future version allocates a pty for it. # $TMUX empty -> a pane's zsh won't re-exec tmux (infinite loop) # not SSH -> don't force inbound SSH logins into a server tmux # not VS Code -> its integrated terminal manages itself @@ -103,6 +112,8 @@ in # $NO_TMUX unset -> escape hatch: `NO_TMUX=1 ` opens a bare shell (lib.mkOrder 200 '' if [[ $- == *i* ]] \ + && [[ -t 1 ]] \ + && [[ -z "$VSCODE_RESOLVING_ENVIRONMENT" ]] \ && [[ -z "$TMUX" ]] \ && [[ -z "$NO_TMUX" ]] \ && [[ -z "$SSH_CONNECTION" && -z "$SSH_TTY" ]] \