fix(terminal): prefer $SHELL over bash for background process spawning - #42219
Closed
liuhao1024 wants to merge 1 commit into
Closed
fix(terminal): prefer $SHELL over bash for background process spawning#42219liuhao1024 wants to merge 1 commit into
liuhao1024 wants to merge 1 commit into
Conversation
_find_shell was an alias for _find_bash, which on macOS returns
/bin/bash (bash 3.2) via shutil.which("bash"). When spawn_local uses
this shell with -lic flags and stdin=/dev/null, bash 3.2 sources
~/.bash_profile which on many macOS setups contains "exec /bin/zsh -l".
That exec replaces bash with zsh but drops the -c argument, so the
background command never runs — the subprocess exits 0 with no output.
Change _find_shell to prefer $SHELL on POSIX (typically /bin/zsh on
macOS Catalina+), falling back to _find_bash when $SHELL is unset or
points to a non-existent path. _find_bash is unchanged — callers that
explicitly need bash (like _run_bash) continue to get it.
Fixes NousResearch#42203
Collaborator
|
Salvaged into #53106 (rebased onto current main, 506 commits ahead — cherry-pick applied cleanly). All credit to @liuhao1024 for the original fix. Thanks for the contribution! |
This was referenced Jun 26, 2026
kshitijk4poor
pushed a commit
that referenced
this pull request
Jun 26, 2026
#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from #42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes #42203. Supersedes #42290.
pai-scaffolde
pushed a commit
to pai-scaffolde/hermes-agent
that referenced
this pull request
Jun 28, 2026
NousResearch#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from NousResearch#42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes NousResearch#42203. Supersedes NousResearch#42290.
waefrebeorn
pushed a commit
to waefrebeorn/slermes
that referenced
this pull request
Jul 2, 2026
NousResearch#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from NousResearch#42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes NousResearch#42203. Supersedes NousResearch#42290.
habarmc1223-sudo
pushed a commit
to habarmc1223-sudo/hermes-agent-fluxmem
that referenced
this pull request
Jul 8, 2026
NousResearch#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from NousResearch#42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes NousResearch#42203. Supersedes NousResearch#42290.
santhreal
pushed a commit
to santhreal/hermes-agent
that referenced
this pull request
Jul 13, 2026
NousResearch#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from NousResearch#42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes NousResearch#42203. Supersedes NousResearch#42290.
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
NousResearch#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from NousResearch#42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes NousResearch#42203. Supersedes NousResearch#42290.
leewenjie
pushed a commit
to leewenjie/hermes-agent
that referenced
this pull request
Aug 7, 2026
NousResearch#42203) On macOS, terminal(background=true) silently failed: the process returned a session_id and exit_code=0 but the command never ran (empty stdout, no side effects). Root cause is two interacting issues: 1. _find_shell was aliased to _find_bash, which prefers `shutil.which("bash")` → /bin/bash (GNU bash 3.2, still shipped on macOS) over $SHELL (/bin/zsh). 2. process_registry.spawn_local runs [shell, "-lic", "set +m; <cmd>"] with stdin=/dev/null. bash 3.2 as a login shell sources ~/.bash_profile, which on many macOS setups contains `exec /bin/zsh -l`; that exec replaces bash but drops the -c argument, so the command is swallowed (exit 0, no output). Decouple _find_shell from _find_bash: _find_shell now prefers the user's configured $SHELL on POSIX (the shell they actually log in with), falling back to _find_bash when $SHELL is unset/missing. _find_bash is unchanged, so callers that genuinely need bash (e.g. the _run_bash login-shell snapshot) keep bash semantics. zsh handles -lic correctly even with redirected stdin. Salvaged from NousResearch#42219 by @liuhao1024 (authorship preserved via cherry-pick). On top of the original (8 unit tests covering $SHELL-set/unset/missing/empty, Windows-ignores-$SHELL, _find_bash-unchanged), added an E2E regression test that reproduces the real bash-3.2 login-shell swallow (exit 0 / no file) and asserts the shell _find_shell selects actually executes a -lic background command. Mutation-verified: reverting _find_shell to the bash alias fails the $SHELL-preference test. Bug reproduced directly: /bin/bash 3.2 -lic with a .bash_profile->exec-zsh creates no file; zsh -lic does. Closes NousResearch#42203. Supersedes NousResearch#42290.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fixes background process spawning on macOS by preferring the user's
$SHELL(typically/bin/zsh) over bash forspawn_local. On macOS Catalina+,_find_shellreturned/bin/bash(bash 3.2) which silently swallowed commands when~/.bash_profilecontainedexec /bin/zsh -l.Related Issue
Fixes #42203
Type of Change
Changes Made
tools/environments/local.py: Replace_find_shell = _find_bashalias with a proper function that prefers$SHELLon POSIX, falling back to_find_bashwhen$SHELLis unset or invalid. On Windows, behavior is unchanged.tests/tools/test_find_shell.py: 7 regression tests covering$SHELLpreference, fallback to_find_bash, empty/missing$SHELL, Windows passthrough, and return-type invariant.How to Test
_find_shell()returns/bin/zsh(or whatever$SHELLis set to):$SHELLand verify fallback to bash:pytest tests/tools/test_process_registry.py -v -k "spawn_local"Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/ACode Intelligence
_find_shell,_find_bashintools/environments/local.py;spawn_localintools/process_registry.py_find_shell:process_registry.py(PTY spawn at line 550, pipe spawn at line 588)_find_bash:local.py(_run_bashat line 502),local.py(_find_shellfallback)_find_shellis only used byspawn_localfor background processes; foreground terminal execution uses_find_bashviaLocalEnvironment._run_bash_find_bashfunction is unchanged — callers that explicitly need bash continue to get it