Skip to content

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

Open
sumanthratna wants to merge 3 commits intoHomebrew:mainfrom
sumanthratna:shellenv-fpath-idempotency
Open

shellenv: export FPATH so child zsh shells inherit fpath#21910
sumanthratna wants to merge 3 commits intoHomebrew:mainfrom
sumanthratna:shellenv-fpath-idempotency

Conversation

@sumanthratna
Copy link
Copy Markdown

@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.

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 on lines +28 to +32
if [[ "${HOMEBREW_SHELL_NAME}" == "zsh" ]] || [[ "${HOMEBREW_SHELL_NAME}" == "-zsh" ]]
then
echo "fpath[1,0]=\"${HOMEBREW_PREFIX}/share/zsh/site-functions\";"
echo "export FPATH;"
fi
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We've already done export FPATH; below. Why do we still need to do this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The export FPATH; that you've highlighted is for the early-return path (when $PATH is set, presumably because eval "$(./bin/brew shellenv zsh)") has already been run).

The export FPATH; below is for the "full output" branch, where eval "$(./bin/brew shellenv zsh)" hasn't been run yet and so HOMEBREW_PREFIX is not in PATH

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I understand. What I'm saying is that we don't need to print the fpath entry anymore when returning early because the full output already does export FPATH

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the catch, you're right, fixing

@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
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.
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

4 participants