Shell snapshot aliases are lost for same-shell commands

Open 💬 0 comments Opened Jul 9, 2026 by connorads

Summary

Shell snapshot replay can lose shell-local state before the user's command is parsed.

I noticed this through a normal shell shortcut: I have mi aliased to mise install, and expected !mi --help to behave the same way it does in my terminal. Instead, Codex can report the alias command as not found even though the session shell has that alias.

What seems to be happening

Codex already has a shell snapshot mechanism that captures user shell state such as aliases, functions, and exports.

The issue is the replay step for same-shell commands: Codex sources the snapshot in the session shell, then execs a fresh shell for the actual command. Alias/function state restored from the snapshot is shell-local, so it is gone before the original user command is parsed.

This is not specific to mi, zsh, or my dotfiles. It is about honouring the shell snapshot contract: if Codex captures shell-local state, same-shell commands should evaluate in the restored shell context.

Expected

For a same-shell command, shell-local state from the snapshot should be available when the original command is parsed. For example, if the snapshot contains:

alias mi='mise install'

then a shell escape like this should resolve through the alias:

!mi --help

Actual

The alias can be present in the user's configured shell state, but the shell escape still fails because the command is evaluated in a fresh shell after the snapshot restore step.

Candidate fix

I pushed a candidate fix branch here:

https://github.com/openai/codex/compare/main...connorads:codex/shell-snapshot-aliases

The approach is:

  • For same-shell shell -lc <script> commands, source the snapshot and eval the original script in that same shell process.
  • Keep the existing exec <original-shell> -c <script> behaviour for cross-shell commands.
  • Enable bash alias expansion before evaluating the original script.
  • Fix bash/sh snapshot capture so unalias -a is emitted into the restore script instead of being executed during capture, which otherwise drops aliases before they are recorded.

I could not open this as a PR because GitHub says PR creation is currently limited to repository collaborators.

Testing on the candidate branch

Manual:

  • Built the local codex binary from the branch.
  • Launched it in a tmux session.
  • Verified !type mi reports mi is an alias for mise install.
  • Verified !mi --help runs through the alias and prints mise install help.

Automated:

  • Added a bash integration test that captures an alias from an isolated .bashrc, replays the snapshot, and verifies the alias works in the wrapped command.
  • Verified that test fails with the old same-shell replay behaviour: trailing args survive, but alias expansion is lost.
  • Ran cargo test -p codex-core shell_snapshot::tests -- --nocapture.
  • Ran cargo test -p codex-core tools::runtimes::tests -- --nocapture.
  • Ran cargo fmt --check.
  • Ran git diff --check.

View original on GitHub ↗