Shell Host and Environment Refresh

Stale PATH and other environment variables after installs are a chronic shell and IDE pain. Host apps inherit a snapshot; "open a new terminal" often fails inside VS Code and Cursor; Chocolatey refreshenv is unreliable. Microsoft historically closed or dismissed PATH-reload requests; a concrete Refresh Environment button (vscode#299940, PR #299941) should not be the only bet.

OpenShellOrg owns the reusable fix. DevCentr consumes it and keeps a thin built-in inject stub until then.

Repositories

Repo Role

openshellorg/env-refresh (planned)

CLI + Nushell module — working refresh command

openshellorg/terminal (fork of microsoft/terminal)

shell-host product base — Windows Terminal fork where we add env-health chrome and inject UX. Local clone: Z:\code\github.com\openshellorg\.forks\terminal

Practitioner background (Dev-Centr general-knowledge): shell-env-refresh (published under general-knowledge Antora when assembled).

Problem summary

  • Processes get an environment block at start; installers update the stored Machine/User (or profile) environment.

  • New shells spawned by a stale host (editor, terminal emulator) inherit the stale block.

  • Chocolatey refreshenv is session-scoped, often missing outside Chocolatey PowerShell profiles, inconsistent across shells, and cannot fix host inheritance.

  • Nushell users hit the same Windows friction; promoting Nu without fixing PATH refresh leaves a gap in the ecosystem we advocate.

Ownership

Actor Role

OpenShellOrg env-refresh

Correct per-shell (and Nu-first) reload of PATH and other system/user vars into the current process; structured output for hosts; short command users can type

OpenShellOrg terminal (shell-host)

Windows Terminal fork: per-tab env health, desync banner between tab bar and shell, Fix / Insert command split control, PTY inject

DevCentr

Repo-scoped terminal now; prefer OpenShellOrg terminal / env-refresh when installed; minimal built-in inject until then

A. Planned product: env-refresh

Repository (planned): openshellorg/env-refresh

Goals

  • One reliable command that reloads PATH and other system/user environment variables into the current process — and actually works.

  • Nushell as primary interactive target — ship a Nu module; document $env updates clearly.

  • Thin wrappers or documented aliases for PowerShell, bash/zsh, fish, and cmd so users can type something short (env-refresh or a blessed alias) in whichever shell they are in.

  • Explicitly supersede reliance on Chocolatey refreshenv.

  • Exit codes and Nu-friendly structured output (for example JSONL via patterns aligned with nu-emit) so host apps can confirm success and which keys changed.

  • Document the second layer honestly: refreshing the shell does not automatically refresh a parent IDE; hosts must reload their own block or inject into each session.

Non-goals (v1)

  • Replacing package managers

  • Forking Nushell

  • Fixing every GUI app on the machine (focus: shells + cooperating hosts)

Acceptance sketch

  • After a Machine/User PATH change, running env-refresh (or Nu module equivalent) in that session makes newly installed tools resolvable without restarting the shell process.

  • Same command family works under Nushell first; documented recipes for pwsh/bash/fish/cmd.

  • Host apps can call it non-interactively and parse structured success/failure.

B. Product: terminal (shell-host) — Windows Terminal fork

Repository: openshellorg/terminal (fork of microsoft/terminal).

We do not greenfield a terminal emulator. We fork Windows Terminal and insert OpenShellOrg env-refresh UX into its tab + content chrome.

Goals

  • Monitor Machine/User env (Windows: registry / WM_SETTINGCHANGE where available).

  • Per-tab health light — small green/orange indicator on each tab (session-scoped drift: a tab that was refreshed can go green while others stay orange).

  • Desync notification bar — when PATH (or watched vars) desync for the active tab, show a bar between the tab bar and the shell/PTY area (outside scrollback).

  • Split action control on that bar:

    • Primary Fix — inject the shell-appropriate refresh command into the PTY and submit (auto-run) so power users are not stuck pressing Enter.

    • Dropdown / secondary Insert command — paste the exact command into the shell input without submitting, so users can read, edit, or learn it.

  • Show a short preview of the command on the bar (or in the dropdown header) so the action is never opaque.

  • Shell detection: Nushell, pwsh, cmd, bash/zsh, fish — prefer env-refresh when on PATH.

  • Preferential integration from DevCentr (Open external → this fork when installed).

UX layout (committed)

+-- tab bar ----------------------------------------------------------+
| [● nu]  [● pwsh]  [● cmd]     <- health light inside each tab      |
+---------------------------------------------------------------------+
| ! PATH changed on this session                                     |
|   will run: env-refresh                         [ Fix | v ]        |
|                                                 +----------------+ |
|                                                 | Fix (run now)  | |
|                                                 | Insert command | |
|                                                 +----------------+ |
+-- notification bar (only when desync) ------------------------------+
|                                                                     |
|   classical shell / PTY surface                                     |
|                                                                     |
+---------------------------------------------------------------------+

Split control semantics:

  • Fix (run now) — primary: inject shell-appropriate refresh into the PTY and submit.

  • Insert command — dropdown: inject only (no submit) so the user can read, edit, or learn the command.

Rules:

  • Health light is per tab, not global-only (window may still show aggregate if useful later).

  • Notification bar appears only for the active tab when that tab is desynced; dismissing without fix may leave the tab orange.

  • Fix = inject + submit. Insert command = inject only. Do not make "click Enter yourself" the only path.

  • Prefer calling env-refresh in the preview when installed; fall back to built-in shell recipes.

Non-goals (v1)

  • Multiplexing remote SSH farms beyond what upstream Terminal already does

  • Inventing a second structured shell language

  • Waiting on microsoft/vscode to merge env-refresh UI

Upstream relationship

  • Track microsoft/terminal; keep OpenShellOrg changes in clearly named modules/files where practical.

  • Branding / package identity can diverge later (shell-host product name vs repo terminal); v1 identity is the fork repo.

C. Nushell ecosystem advocacy

OpenShellOrg promotes Nushell as the default structured shell. PATH/env refresh pain must be a non-issue in that story:

  • First-class Nu module and docs for env-refresh

  • Host (this Terminal fork, DevCentr) detect Nu and show Nu recipes, not only PowerShell one-liners

  • Prefer upstream-friendly module shape; contribute patches upstream when that is better than a companion

  • Do not invent a rival shell to paper over Windows env quirks

Relation to VS Code

We cite and learn from:

  • vscode#47816, #226510 — host inheritance

  • Closed / not-planned PATH reload threads (for example #159986, #168020)

  • Author proposal: #299940 and PR #299941 (inject shell-appropriate refresh into all terminals)

Product responsibility for a working solution is OpenShellOrg + DevCentr, not waiting on microsoft/vscode merge outcomes. Shipping in a Terminal fork is the chosen path.

Implementation sequence

  1. Spec and docs (this page + Dev-Centr general-knowledge / terminal spec) — done; UX refined here.

  2. Fork + clone openshellorg/terminal to openshellorg/.forks/terminaldone (https://github.com/openshellorg/terminal).

  3. Spike in fork: per-tab health light, EnvRefreshInfoBar + Fix/Insert SplitButton, OS Path poll — landed (see OPENSHELLORG.adoc in the fork).

  4. Scaffold openshellorg/env-refresh — Nu module + CLI; wire Terminal to prefer it.

  5. Hook WM_SETTINGCHANGE (WindowEmperor already notes GH#15102); regenerate host process env for new tabs.

  6. DevCentr: prefer this Terminal build for "Open external"; upgrade repo terminal stub to match Fix/Insert semantics.

  7. Optional: upstream Nu docs/module coordination; keep SOS / nu-emit / nu-require as separate tracks.

Spike insertion points (fork)

Already wired to upstream layout:

  • Tab light → TabHeaderControl.xaml + TerminalTabStatus.IsEnvStale

  • Banner → TerminalPage.xaml Row 1 InfoBar stack (same slot as keyboard/close-on-exit bars)

  • Inject → TermControl.SendInput (Fix appends \r)

  • Helpers → EnvRefreshHelpers.cpp (til::env::regenerate for OS Path)