The manual page for launchctl mentions that the load and unload subcommands are legacy subcommands, which implies that they're no longer needed for loading and starting a launchd job.

However, I'm not aware of any way to actually define a launchd job and its properties and then load it for the first time without using a plist file and passing it in to the load subcommand.

Does launchctl offer a way of defining and loading a job using its other subcommands? If so, how does that work?

1 Answer 1


Yes, it does offer such a way - and actually it's stated in the manual just below where it says that the others are legacy.

So to quote the man page for launchctl in the section for legacy subcommands - for the subcommands load and unload it says:

Recommended alternative subcommands: bootstrap | bootout | enable | disable

So those are the newer subcommands, you want to look at.

Here's a few examples:

Before if you used load like this:

launchctl load my.plist

You'll now write one of these:

sudo launchctl bootstrap system my.plist
launchctl bootstrap user/$(id -u) my.plist
launchctl bootstrap gui/$(id -u) my.plist

The difference being that you now have to specify the domain target. The difference here is that system means that it going to be a system daemon that runs as the super user, compared to user meaning that it will run as the given user, and gui meaning that it will run as the given user, but only be active when the user is logged in to the graphical user interface. There's also a session and pid target domain if you have more advanced needs.

The $(id -u) is basically just a short hand for finding your own user's id. You can run id -u in the Terminal to get it if you do not know it, and then you can just specificy it manually like for example so:

launchctl bootstrap gui/501 my.plist

The replacement for unload is quite similar:

sudo launchctl bootout system my.plist
launchctl bootout user/$(id -u) my.plist
launchctl bootout gui/$(id -u) my.plist

So the above covers how to move away from the legacy subcommands to the recommended subcommands instead.

The second part of your question is whether you can do this without using a plist file. The answer is no. The bootstrap subcommand requires you to specify a service-path, which can be either a plist, a XPC service bundle - or a directory of either of those. XPC service bundle are used by application developers, but they also include a plist file - so going that route is not going to save you from having a plist file.

You can of course do various sorts of work-arounds with scripts or utility programs so that you do not need to manually create and maintain plist files. You could even use for example a named pipe to avoid having to actually store the contents of the plist file on disk, but I cannot see the practical benefit of that.

  • Okay, that clears some things up, though it answers half of my question. The other half is: is there a way to start / bootstrap a launchd job without using a plist file?
    – Bri Bri
    Mar 29, 2022 at 21:36
  • Ah - I never actually say the other part of your question. It is really only in the title of the question - I read the question itself and thought that you only knew how to use load with a plist, and now wanted to use a non-legacy command with a plist.
    – jksoegaard
    Mar 29, 2022 at 21:45
  • I have answered the second part of your question now. By the way, could you expand on why you do not want to use a plist file? - Is there something else you would like to use instead? - or what were you thinking of?
    – jksoegaard
    Mar 29, 2022 at 22:00
  • I have an app that needs to make a temporary launchd job that runs once and then removes itself. Currently I'm doing this using a plist saved to a temporary location, but it's more complicated and error prone trying to fully clean everything up afterwards when a temporary file is involved. If it were possible to start the job with just an invocation to launchctl then that would simply things. But the temporary file works well enough.
    – Bri Bri
    Mar 31, 2022 at 15:15
  • Perhaps using launchctl is not the right choice. Why do you need to run a launchd job only once? What does the job do? Perhaps that can be solved in an easier manner
    – jksoegaard
    Mar 31, 2022 at 19:10

You must log in to answer this question.

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