macos – When opening terminal applications, launchd is setting the initial $PATH inconsistently. Why?


I recently discovered that launchd on macOS provides an initial, default $PATH to new terminal windows that is not the default path set by macOS at log in, but instead is produced by launchd according to (presumably) its own internal logic — without changes ever having been made via either launchctl or any .plist file that I could find.

This is the case whether using the Terminal.app distributed by Apple, or a third-party terminal such as Alacritty.app.

The default path on macOS at log in, as can be verified with sysctl -n user.cs_path, is

/usr/bin:/bin:/usr/sbin:/sbin

But when I placed echo $PATH on the first line of ~/.zshenv, which is sourced before /etc/zprofile and any other shell configuration file, I was seeing an entirely different $PATH when opening a new window in Alacritty:

/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin

Which I verified to be coming from launchd by searching the output of launchctl dumpstate:

pid/72911 = {
    type = pid
    originator = /Applications/Alacritty.app
    creator = alacritty[72911]
    ...
    environment = {
        PATH => /usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin
        ...
    }
        ...
}

After restarting Alacritty, with only one window and one instance of the shell the same echo command produced:

/usr/bin:/bin:/usr/sbin:/sbin

Which is what it should be. But then, opening the default Terminal.app, I get

/usr/bin:/bin

Which is, again, not the OS default.

This doesn’t necessarily affect my ability to use the shell because I can set $PATH in .zshenv or .zprofile to whatever I’d like, but it does require that I override the $PATH that launchd sets if I wish to control search order. In fact, what launchd is doing makes controlling search order crucial because there is apparently no guarantee that the initial $PATH handed to the shell will be consistent.

Does anybody know why launchd is providing an inconsistent $PATH? Is there any rhyme or reason to what it decides to include or not include in the $PATH that it provides to every shell created with every new terminal window, and varying it by terminal application?

Again, I have never

  1. issued launchctl setenv PATH <path>
  2. issued either sudo launchctl config user <path> or config system <path>
  3. modified any .plist file anywhere (or found any that set the PathEnvironmentVariable key).

I am running macOS Sequoia 15.4 (24E248) on an M2 MacBook Pro, using the stock Zsh shell.

The closest answer I could find mentions that launchd manipulates the default $PATH, but the author doesn’t specify how or why.


Update 1

For the stock Terminal app, launchctl dumpstate is showing

pid/45557 = {
    type = pid
    originator = /System/Applications/Utilities/Terminal.app
    creator = Terminal[45557]
        ...
    environment = {
        PATH => /usr/bin:/bin:/usr/sbin:/sbin
                ...
        }
        ...
}

Which is indeed the correct, default $PATH. However, for the stock Terminal app, an echo $PATH statement on the first line of .zshenv continues to result in the truncated

/usr/bin:/bin

Update 2

The developers working on Alacritty have told me that they do not touch the $PATH variable.


Update 3

With echo $PATH as the first line in .zshenv producing

/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin

in Alacritty, and

/usr/bin:/bin

in Terminal, subsequently executing

/usr/bin/env -i /bin/zsh -l -osourcetrace

per Gairfowl’s suggestion (see comments) shows that same echo command outputting a completely different $PATH in both Alacritty and Terminal:

+/Users/Me/.zshenv:1> <sourcetrace>      # line 1
/bin:/usr/bin:/usr/ucb:/usr/local/bin    # line 2 `echo $PATH`

There is no /usr/ucb directory or file, hidden or not, that I could find. But given that a Google search for “ucb” tells me it is a reference to “University of California, Berkeley” (and that the output is from env -i zsh), could it be Zsh itself is manipulating the initial $PATH? And then either it or something else in macOS is inconsistently transforming /usr/ucb into one of these not-configured paths before completing echo $PATH on the first line of .zshenv, and sometimes informing launchd of the change (causing it to appear in the launchctl dumpstate output)?

Note that those two lines from the env output are printed before /etc/zprofile is sourced, thus Apple’s path_helper utility is not yet in play.


I should point out that in all my examples thus far the shell has been consistently in both login and interactive states, verified with setopt.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img