(EDIT OF 06/02/2023 : Previous title was Variables set using launchctl setenv aren't part of environment in Mac OS 12 )

I'm a daily Linux user and decided to try Mac recently. I have a Macbook pro 13" early 2015 that currently run macOS Monterey (12.6.3).

I'm struggling since a few day to setup SSH_AUTH_SOCK environment variable for my whole session

I relied on the following plist file in $HOME/Library/LaunchAgents/:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">




I then activate the agent using launchctl bootstrap gui/501/com.moolticute.mc-agent (or something similar, i don't remember well) and restart my session.

The binary mc-agent is running as expected but:

  • when i check SSH_AUTH_SOCK variable, it still contains the default value, not the one superseeded by my script.
  • when i run virt-manager (which make use of this variable) from the Launchpad, it obviously doesn't have the correct value.
  • when i run launchctl getenv SSH_AUTH_SOCK the variable value is the one expected.

did i missed something ?


After the first answer, which is correct but doesn't fullfill my needs, i noticed that my question wasn't clear enought.

At the end, i want to mimic the behaviour of regular ssh-agent. On raw MacOS installation, ssh-agent is launched using a plist file at GUI session launch, out of any shell.

I want my agent to be launched at GUI session startup and the environment variable set for the whole session, in or out the shell.

The goal is, when i launch virt-manager (which is a graphical app) directly from the finder or launchpad, no shell is spawned to launch it, virt-manager won't inherit the variable set in my .zshenv or .bashrc, right ? This is the same i guess for any IDE with git connectivity.

For example, in Linux, this would be achieved by tweaking Xsession for your favourite DM or by using legacy startup mode for xsession and setting a .xinitrd or .Xsession. Then, every variable set this way will be inherit by any applications launched from the window manager as it's part of its environment.

I have read this week end several methods to do this with launchctl/ launchd but it seems that all of them stopped working on later MacOS versions...

2 Answers 2


The variables that you set using launchd are only valid for the sub-shell in which it executes.

When you check SSH_AUTH_SOCK, or run virt-manager you are opening an interactive shell (via Terminal or iTerm) and that shell process has no clue what environment variables were set in the non-interactive shell opened by launchd. Therefore, the environment variables are unchanged/unset as you've discovered.

If you want that variable to propagate both in your interactive and non-interactive shell(s) then you should set the PATH variable in .zshenv. See the post ZSH: .zprofile, .zshrc, .zlogin - What goes where? for further details.

Passing variables to other shells

You can use export to pass variables to sub-shells.

export PATH=“/foo/bar:/hello/world:/acme;road_runner/coyote” 

The variable is “exported” from the parent shell to the child sub-shell. However, since Finder is not a sub-shell of the launchd shell executing your script, the variables wont be passed through.

From Apple Support

Use environment variables in Terminal on Mac

Although child processes of a shell inherit the environment of that shell, shells are separate execution contexts that don’t share environment information with each other. Variables you set in one Terminal window aren’t set in other Terminal windows.

To solve your issue, you need to use .zshenv or .zprofile or .zshrc. Since it’s a GUI app, you can place it in Login Items and have it launch within Finder, but Finder gets it’s variables set by one of these files anyway.

  • Ok, understood launchd limitations. Anyway, my problem isn't setting a variable for shell & sub-shell but for the whole graphical session. I'll edit my question
    – binarym
    Commented Feb 6, 2023 at 8:21
  • No not limitations - this is normal Unix behaviour. Setting a variable only effects the current process and its subprocesses. Terminal is not a subprocess of your mc-agent. The difference is that in macOS the boot process does not start from a shell. In Linux and other all processes are a subprocess of a shell and so inherit that shell's variables
    – mmmmmm
    Commented Feb 6, 2023 at 10:30
  • @Allan I don't think "but Finder gets it’s variables set by one of these files anyway" is correct. It is like any other GUI app and so only from launchd
    – mmmmmm
    Commented Feb 6, 2023 at 14:34
  • Finder is technically launched from a login shell, so that’s where it gets its environment variables from
    – Allan
    Commented Feb 6, 2023 at 14:47

I don't know if you're still dealing with this, but I have an answer (documented more fully at Add system-wide environment-variables in MacOS Ventura).

As you have gathered, when an application is started from Finder/launchd, no shell is involved and no shell setup scripts are loaded or run, so you can't address this that way. What you can do is use the launchctl setenv command, which tells launchd what values to pass on to any apps it spawns. You would run this command from a terminal, but it's not about the terminal's environment variables, it's sending configuration commands to the entirely different process/subsystem. Now, these changes are not preserved across login sessions, so if you want them to last, you need to set up a mechanism for re-setting them every session. I've seen conflicting comments about whether or not you can do that with specific plist files, depending on the OS version and ... stuff. I have a shell script set up to run on every login to set the variables, which is ugly but it works.

Except for PATH. It seems like PATH is special-cased somewhere under the hood, and I haven't found out where yet.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .