terminal: Skip SHLVL when loading login shell environment (#46273)

rari404 created

Fixes #33958

## Problem

PR #44835 attempted to fix SHLVL starting at 2 by removing it from the
`env` HashMap passed to alacritty. However, that HashMap is only an
**overlay** — alacritty uses the parent process environment as a base
and applies the overlay on top. Since alacritty never calls
`env_remove("SHLVL")`, the terminal shell still inherits `SHLVL` from
Zed's process environment.

## Root Cause

The real issue is in `load_login_shell_environment()`:

1. `shell_env::capture()` spawns a login shell to capture environment
variables
2. That login shell increments `SHLVL` (from 0→1 or n→n+1)
3. The captured env (including the incremented `SHLVL`) is written to
Zed's **process environment** via `env::set_var`
4. When you open a terminal, the shell inherits Zed's `SHLVL` and
increments it again → starts at 2
5. On reload, `shell_env::capture()` runs again with the
already-elevated `SHLVL`, incrementing it further → +2 per reload

## Fix

Skip `SHLVL` when setting Zed's process environment in
`load_login_shell_environment()`. This prevents the login-shell capture
from polluting Zed's env, so terminals start fresh with the correct
`SHLVL`.

Change summary

crates/util/src/util.rs | 7 +++++++
1 file changed, 7 insertions(+)

Detailed changes

crates/util/src/util.rs šŸ”—

@@ -365,6 +365,13 @@ pub async fn load_login_shell_environment() -> Result<()> {
         .await
         .with_context(|| format!("capturing environment with {:?}", get_system_shell()))?
     {
+        // Skip SHLVL to prevent it from polluting Zed's process environment.
+        // The login shell used for env capture increments SHLVL, and if we propagate it,
+        // terminals spawned by Zed will inherit it and increment again, causing SHLVL
+        // to start at 2 instead of 1 (and increase by 2 on each reload).
+        if name == "SHLVL" {
+            continue;
+        }
         unsafe { env::set_var(&name, &value) };
     }