Skip to content

shellenv: export FPATH so child zsh shells inherit fpath#21910

Merged
carlocab merged 7 commits into
Homebrew:mainfrom
sumanthratna:shellenv-fpath-idempotency
Apr 12, 2026
Merged

shellenv: export FPATH so child zsh shells inherit fpath#21910
carlocab merged 7 commits into
Homebrew:mainfrom
sumanthratna:shellenv-fpath-idempotency

Conversation

@sumanthratna
Copy link
Copy Markdown
Contributor

@sumanthratna sumanthratna commented Apr 3, 2026

zsh's fpath is not an exported environment variable, so child shells (tmux/Zellij panes, nested zsh) lose Homebrew's completions path. The shellenv idempotency check only inspects PATH, which IS inherited, so it early-returns and never emits the fpath line. Exporting FPATH after setting fpath ensures child zsh shells inherit it.

Fixes #21879

Supersedes #21884


  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests (excluding integration tests) for your changes? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) with your changes locally?

  • AI was used to generate or assist with generating this PR. Please specify below how you used AI to help you, and what steps you have taken to manually verify the changes.

zsh's fpath is not an exported environment variable, so child shells
(tmux/Zellij panes, nested zsh) lose Homebrew's completions path. The
shellenv idempotency check only inspects PATH, which IS inherited, so
it early-returns and never emits the fpath line. Exporting FPATH after
setting fpath ensures child zsh shells inherit it.

Fixes Homebrew#21879

Supersedes Homebrew#21884
Copilot AI review requested due to automatic review settings April 3, 2026 21:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates brew shellenv output for zsh so that Homebrew’s completion search path is inherited by child zsh shells (e.g., tmux panes / nested shells) by exporting FPATH after updating fpath.

Changes:

  • Emit export FPATH; in the zsh branch of brew shellenv output.
  • Adjust the integration spec to assert that FPATH is exported when running brew shellenv zsh.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
Library/Homebrew/cmd/shellenv.sh Exports FPATH for zsh so child shells inherit Homebrew’s completion path.
Library/Homebrew/test/cmd/shellenv_spec.rb Updates integration expectation to check for export FPATH in zsh output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Library/Homebrew/test/cmd/shellenv_spec.rb Outdated
The idempotency early return fires when PATH already contains
Homebrew's bin/sbin, skipping all output. This is correct for
exported env vars but breaks zsh's fpath which is not inherited.
Move shell detection before the check so the early-return path
can still emit fpath and export FPATH for zsh.
Comment thread Library/Homebrew/cmd/shellenv.sh Outdated
@MikeMcQuaid
Copy link
Copy Markdown
Member

  • AI was used to generate or assist with generating this PR. Please specify below how you used AI to help you, and what steps you have taken to manually verify the changes.

@sumanthratna you didn't use anything at all here? are you sure?

@sumanthratna
Copy link
Copy Markdown
Contributor Author

  • AI was used to generate or assist with generating this PR. Please specify below how you used AI to help you, and what steps you have taken to manually verify the changes.

@sumanthratna you didn't use anything at all here? are you sure?

sorry I forgot the checkbox; fixed. For this PR, I used Opus 4.6 with high reasoning, with context (a) from original issue, (b) output of below

$ echo $FPATH
$ zsh
$ echo $FPATH
$ eval "$(./bin/brew shellenv zsh)"
$ echo $FPATH

The parent shell's shellenv already exported FPATH with the Homebrew
site-functions entry. Child shells inherit it, so re-prepending via
fpath[1,0]= is unnecessary when the idempotency early return triggers.
@sumanthratna
Copy link
Copy Markdown
Contributor Author

Hi @MikeMcQuaid @carlocab gentle bump to see if you have any other feedback here?

@carlocab
Copy link
Copy Markdown
Member

My comment from #21910 (comment) still applies. You made a change in 505e9dd, but that doesn't seem to address the comment fully.

zsh preserves the export attribute of FPATH when inherited from the
parent environment, so child shells already have FPATH exported without
re-emitting it on the early-return path. Verified with `typeset -p FPATH`
across parent, child, and grandchild zsh shells.
@sumanthratna
Copy link
Copy Markdown
Contributor Author

Thanks @carlocab I re-read your message and realized what you meant. I didn't know that zsh preserves the export attribute of FPATH when inherited from the parent environment but I validated with typeset -p FPATH and it's true.

Can you take another look whenever you get a chance? And thanks again for the help

Copy link
Copy Markdown
Member

@carlocab carlocab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more suggestion, and I think this should be ready.

Comment thread Library/Homebrew/test/cmd/shellenv_spec.rb Outdated
Copy link
Copy Markdown
Member

@carlocab carlocab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@carlocab carlocab enabled auto-merge April 12, 2026 01:33
@carlocab carlocab added this pull request to the merge queue Apr 12, 2026
Merged via the queue into Homebrew:main with commit 0f46368 Apr 12, 2026
36 checks passed
@sumanthratna sumanthratna deleted the shellenv-fpath-idempotency branch April 12, 2026 01:50
@GunniBusch
Copy link
Copy Markdown
Contributor

@sumanthratna Thanks a lot ❤️! This fixes autocompletions inside codex. I always thought the issue was in codex not using a login shell.

@mhanberg
Copy link
Copy Markdown

mhanberg commented May 1, 2026

I have no idea why, but the line added in this PR, when run inside tmux, never returns. i ran the commands all one by one and they all return immediately except for export FPATH, which seems to hang indefinitely. I'm not sure why it only happens inside tmux. It doesn't to matter if you initialized brew in the base terminal before hand or wait until you launch a tmux window and then run it.

I can open a new issue i that is preferable.

@MikeMcQuaid
Copy link
Copy Markdown
Member

@mhanberg Given how many people use tmux, zsh and brew: this seems highly likely to be specific to your setup. We'll review a PR to fix (not revert) this but I don't think an issue makes sense, sorry.

@mhanberg
Copy link
Copy Markdown

mhanberg commented May 1, 2026

@MikeMcQuaid sorry for the noise. I went on a vision quest and determined that it was a confluence of zsh from nixpkgs + portable ruby + demons that was causing crowdstrike to give my shell startup the hug of death. I just reverted to using /bin/zsh (which is code signed in a way that crowdstrike says "carry on") and all seems working.

Apologies!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

brew shellenv idempotency check skips fpath setup in child/nested zsh shells

6 participants