shell_snapshot: PowerShell state+environment capture always returns None

Open 💬 0 comments Opened Aug 27, 2026 by xu-kai-quan

What issue are you seeing?

snapshot_state_and_environment_script(ShellType::PowerShell) always returns None, even though snapshot_script(ShellType::PowerShell) returns Some(...) and PowerShell is documented as a supported shell (only Cmd is called out as unsupported).

This is a source-level finding from reading codex-rs/shell-command/src/shell_snapshot.rs, not something reproduced by running the CLI end-to-end — I don't have a working Rust toolchain on this machine to build and run Codex, so I'm reporting the root cause directly.

// codex-rs/shell-command/src/shell_snapshot.rs
const EXPORT_CAPTURE_MARKER: &str = "# Capture exported variables";

pub fn snapshot_state_and_environment_script(shell_type: ShellType) -> Option<String> {
    let script = snapshot_script(shell_type)?;
    let (state, _) = script.split_once(EXPORT_CAPTURE_MARKER)?;
    Some(format!("{state}printf '\\0'\n/usr/bin/env -0\n"))
}

snapshot_state_and_environment_script locates the exports section by splitting on the literal comment "# Capture exported variables". That comment is present verbatim in the Zsh, Bash, and Sh snapshot templates (lines 60, 112, 167), but was never added to powershell_snapshot_script() (lines 202–225). A repo search confirms it:

$ grep -n "Capture exported variables" codex-rs/shell-command/src/shell_snapshot.rs
8:const EXPORT_CAPTURE_MARKER: &str = "# Capture exported variables";
60:# Capture exported variables      <- zsh_snapshot_script
112:# Capture exported variables     <- bash_snapshot_script
167:# Capture exported variables     <- sh_snapshot_script

Zero matches inside powershell_snapshot_script(). So for ShellType::PowerShell, script.split_once(EXPORT_CAPTURE_MARKER) returns None, and the ? propagates it — the function unconditionally returns None for PowerShell.

What steps can reproduce the bug?

No build is required to confirm this — it's provable by text inspection of codex-rs/shell-command/src/shell_snapshot.rs:

  1. Note EXPORT_CAPTURE_MARKER at line 8.
  2. Note it appears at lines 60 (zsh), 112 (bash), 167 (sh).
  3. Note powershell_snapshot_script() (lines 202–225) never contains that string.
  4. Therefore snapshot_state_and_environment_script(ShellType::PowerShell) always evaluates to None.

At the call site, codex-rs/exec-server/src/shell_snapshot.rs::capture_snapshot treats None as a hard error (invalid_params("unsupported shell snapshot script")), and a nearby match arm currently reads ShellType::PowerShell | ShellType::Cmd => unreachable!() — consistent with PowerShell shell-snapshot support being routed around today, and with the two Windows-specific shell-snapshot tests (core/src/shell_snapshot_tests.rs:330 and core/tests/suite/shell_snapshot.rs:712) being permanently #[ignore]d with no tracking note.

What is the expected behavior?

snapshot_state_and_environment_script(ShellType::PowerShell) should return Some(script), consistent with snapshot_script's contract (only Cmd is unsupported) and with the sibling POSIX-shell implementations.

Additional information

Root cause: the export-capture marker comment was added to the three POSIX shell templates but never ported to the PowerShell template.

Suggested fix — add the marker comment immediately before the export-capture block in powershell_snapshot_script(), mirroring the other three shells:

fn powershell_snapshot_script() -> &'static str {
    r##"$ErrorActionPreference = 'Stop'
...
Write-Output ''
# Capture exported variables
$envVars = Get-ChildItem Env:
Write-Output ("# exports " + $envVars.Count)
...
"##
}

Suggested test: add a case to codex-rs/shell-command/src/shell_snapshot_tests.rs asserting snapshot_state_and_environment_script(ShellType::PowerShell).is_some() and that it still contains "# exports ". Note the test module there is currently #[cfg(all(test, unix))] (line 3), so it never runs on Windows CI either — that gate would need to be relaxed (or a Windows-specific sibling module added) for a PowerShell case to actually run on the one platform it matters for.

Found via static code review (commit 7c3747941), not via a live repro — happy to provide more detail if useful.

Possibly related: #25833 and #28408 both show the runtime symptom this root cause would produce ("Failed to create shell snapshot for powershell: Shell snapshot not supported yet for PowerShell"), though I haven't confirmed the exact code path that logs that specific message traces back to this function.

View original on GitHub ↗