Skip to content

Launch agent host terminals as login shells on macOS#312057

Merged
anthonykim1 merged 3 commits intomicrosoft:mainfrom
anthonykim1:anthonykim1/launchWithLogin
Apr 23, 2026
Merged

Launch agent host terminals as login shells on macOS#312057
anthonykim1 merged 3 commits intomicrosoft:mainfrom
anthonykim1:anthonykim1/launchWithLogin

Conversation

@anthonykim1
Copy link
Copy Markdown
Contributor

@anthonykim1 anthonykim1 commented Apr 23, 2026

Fixes #312059 + shell detection (see my review comments

The agent host terminal manager spawns zsh/bash without --login on macOS, which means things like zprofile and bash profile do not run and can lead to missing reference for node, cargo, etc.

This is what we do in terminal profile:

if (options.os === OperatingSystem.Macintosh && path.parse(executable).name.match(/(zsh|bash)/)) {
// macOS should launch a login shell by default
args = ['--login'];

However, the agent host was passing empty args here, skipping the login variant:

let shellArgs: string[] = [];
const injection = await getShellIntegrationInjection(
{ executable: shell, args: [], forceShellIntegration: true },

The shell integration injection maps empty args to -i instead of -il

case 'zsh': {
if (!originalArgs || originalArgs.length === 0) {
newArgs = shellIntegrationArgs.get(ShellIntegrationExecutable.Zsh);
} else if (areZshBashFishLoginArgs(originalArgs)) {
newArgs = shellIntegrationArgs.get(ShellIntegrationExecutable.ZshLogin);
addEnvMixinPathPrefix(options, envMixin, shell);
} else if (originalArgs === shellIntegrationArgs.get(ShellIntegrationExecutable.Zsh) || originalArgs === shellIntegrationArgs.get(ShellIntegrationExecutable.ZshLogin)) {
newArgs = originalArgs;
}

/cc @meganrogge @connor4312

On macOS, the agent host terminal manager was spawning zsh/bash
without --login, resulting in /etc/zprofile and ~/.zprofile not
being sourced. This could cause missing PATH entries (e.g.
homebrew, nvm, pyenv) since macOS relies on path_helper in
/etc/zprofile for standard PATH setup.

The regular VS Code terminal already handles this via the profile
resolver, but the agent host bypasses that layer and spawns shells
directly via node-pty. This adds the same --login logic inline.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 23, 2026 01:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the agent host’s terminal spawning logic to better match VS Code’s integrated terminal behavior on macOS by launching zsh/bash as login shells, ensuring standard profile scripts are sourced and PATH is correctly initialized.

Changes:

  • Detect zsh/bash on macOS and pass --login when spawning the shell via node-pty.
  • Plumb the computed shell args through getShellIntegrationInjection so shell integration can translate login intent appropriately.
Show a summary per file
File Description
src/vs/platform/agentHost/node/agentHostTerminalManager.ts Adds macOS login-shell argument handling for zsh/bash before shell integration injection and PTY spawn.

Copilot's findings

  • Files reviewed: 1/1 changed files
  • Comments generated: 1

Comment thread src/vs/platform/agentHost/node/agentHostTerminalManager.ts Outdated
@anthonykim1 anthonykim1 marked this pull request as draft April 23, 2026 02:04
@anthonykim1 anthonykim1 self-assigned this Apr 23, 2026
Address review feedback:
- Use regex match /(zsh|bash)/ instead of strict equality to handle
  versioned shell names like bash-5.2 (matching the profile resolver)
- Reuse getSystemShell() from src/vs/base/node/shell.ts instead of
  a custom _getDefaultShell(), which handles edge cases like
  /bin/false fallback and userInfo().shell when $SHELL is unset

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@anthonykim1 anthonykim1 added this to the 1.118.0 milestone Apr 23, 2026
return process.env['COMSPEC'] || 'cmd.exe';
}
return process.env['SHELL'] || '/bin/sh';
private _getDefaultShell(): Promise<string> {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match

async getDefaultSystemShell(osOverride: OperatingSystem = OS): Promise<string> {
return getSystemShell(osOverride, process.env);

let shellArgs: string[] = [];
if (platform.isMacintosh) {
const shellName = pathParse(shell).name;
if (shellName.match(/(zsh|bash)/)) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match

if (options.os === OperatingSystem.Macintosh && path.parse(executable).name.match(/(zsh|bash)/)) {

@anthonykim1 anthonykim1 marked this pull request as ready for review April 23, 2026 02:42
TylerLeonhardt
TylerLeonhardt previously approved these changes Apr 23, 2026
@anthonykim1 anthonykim1 merged commit 85a0e01 into microsoft:main Apr 23, 2026
33 of 49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent host terminal should launch as login shell on macOS

4 participants