Summary
When BASH_ENV (or ENV in --sh mode) is set in the environment, brush returns an "unimplemented" error instead of sourcing the named file, breaking non-interactive -c invocations.
Reproduction
echo 'echo loaded' > /tmp/empty.sh
BASH_ENV=/tmp/empty.sh brush -c 'echo hello'
Expected:
Actual:
error: not yet implemented: load config from $ENV/BASH_ENV for non-interactive, non-login shell
Workaround: pass --noenv.
Why this matters
It's common for users to have BASH_ENV exported from their login profile (e.g., to point at a shared init script for non-interactive bash). Once BASH_ENV is set, every non-interactive brush -c invocation fails. That makes brush hard to use as a drop-in bash -c replacement from other tools (CI runners, editor "run shell command" features, parent processes that exec a shell to run a one-liner) without surgery on the caller's environment.
Source
The bailout is at brush-core/src/shell/initscripts.rs and is already TODO'd:
// TODO(well-known-vars): look at $ENV/BASH_ENV; source its expansion if that
// file exists
return error::unimp(
"load config from $ENV/BASH_ENV for non-interactive, non-login shell",
);
Bash semantics worth mirroring
Per bash(1) (INVOCATION section):
- For non-interactive non-login shells: if
BASH_ENV is set in the environment, expand the value and source the resulting file (if it exists and is readable)
- In POSIX/
sh mode: same behavior using ENV instead of BASH_ENV
- The value undergoes parameter expansion, command substitution, and arithmetic expansion before being used as a filename
- Bash silently continues if the file does not exist (no error)
- Behavior is suppressed when the effective UID/GID differ from the real ones (bash skips env-file reads in privileged contexts)
Environment
- brush 0.4.0 (installed via Homebrew on macOS)
- Darwin 25.4.0, arm64
Happy to take a stab at this — would follow up with a draft PR using the existing source_if_exists helper and the basic expansion path used elsewhere for shell variables.
Summary
When
BASH_ENV(orENVin--shmode) is set in the environment, brush returns an "unimplemented" error instead of sourcing the named file, breaking non-interactive-cinvocations.Reproduction
Expected:
Actual:
Workaround: pass
--noenv.Why this matters
It's common for users to have
BASH_ENVexported from their login profile (e.g., to point at a shared init script for non-interactive bash). OnceBASH_ENVis set, every non-interactivebrush -cinvocation fails. That makes brush hard to use as a drop-inbash -creplacement from other tools (CI runners, editor "run shell command" features, parent processes that exec a shell to run a one-liner) without surgery on the caller's environment.Source
The bailout is at
brush-core/src/shell/initscripts.rsand is already TODO'd:Bash semantics worth mirroring
Per
bash(1)(INVOCATION section):BASH_ENVis set in the environment, expand the value and source the resulting file (if it exists and is readable)shmode: same behavior usingENVinstead ofBASH_ENVEnvironment
Happy to take a stab at this — would follow up with a draft PR using the existing
source_if_existshelper and the basic expansion path used elsewhere for shell variables.