Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
launchctl/launchd cheat sheet

I've never had great understanding of launchctl but the deprecation of the old commands with launchctl 2 (10.10) has been terrible as all resources only cover the old commands, and documentation for Apple utilities is generally disgracefully bad, with launchctl not dissembling.

Mad props to which contains most details


Internally, launchd has several domains, but launchctl 1 would only ask for service names, inferring the domain based on context. This made for straightforward commands (once you've loaded a plist you just use the service name it specifies) but had rough edge cases or odd behaviours.

Launchctl 2 separates service names, domain targets and service targets:

  • a service target is <domain-target>/<service-name> and used to point to most services
  • a service name is what is specified in the plist file
  • a domain target is a namespace for services, each namespace has specific behaviours associated:
    • system is privileged (runs services as root) and requires root for interaction
    • user/<uid> runs as that user, but does not require that the user be logged in
    • gui/<uid> runs as that user, but is only active when the user is logged in at the GUI

important commands

bootstrap <domain-target> <paths...>

The paths can be plist files, XPC bundles, or directories of them. Each plist or bundle is loaded into the specified domain.

bootout <service-target> | <domain-target> <paths...>

Unloads the specified service(s).


The paths are actually optional, you can unload an entire domain, which you probably should not do.

enable <service-target> | disable <service-target>

Marks the service as runnable (or not), allows overriding a Disabled plist key. Behaviour is a bit odd and I haven't looked much into it, you may need to bootstrap a service (it will complain that the service is disabled), enable it, then bootstrap it again.

kickstart <service-target>

Starts a service. -k will kill then restart existing instances.

Supposedly -p will print the service's pid (even if it's already started), doesn't seem to work for me.

print <service-target>

Dumps the service's definition, properties & metadata.


The output of print is not officially structured, do not rely either on the format or on the information.

print <domain-target>

Prints the domain's metadata, including but not limited to all services in the domain.

kill <signame | signum> <service-target>

Sends a signal to a service's process (without having to look it up manually).

Copy link

fantix commented May 3, 2021

I think it's bootstrap?


Copy link

masklinn commented May 8, 2021

Sure, probably.


Copy link

mailinglists35 commented Jun 30, 2021

$ launchctl list|egrep -i 'team'
81131   -9      com.teamviewer.service
76878   -9      com.teamviewer.desktop
76955   -9      com.teamviewer.teamviewer

how do I gracefully terminate these with launchctl? very unclear and confused what command should use

$ sudo launchctl bootout system/com.teamviewer.service
Boot-out failed: 3: No such process
$ sudo launchctl bootout user/501/com.teamviewer.service
Boot-out failed: 3: No such process
$ sudo launchctl bootout gui/501/com.teamviewer.service
Boot-out failed: 36: Operation now in progress
$ sudo launchctl kill 15 system/com.teamviewer.service
Could not find service "com.teamviewer.service" in domain for system
$ sudo launchctl kill 15 gui/501/com.teamviewer.service
Could not find service "com.teamviewer.service" in domain for login: 100009
$ sudo launchctl kill 15 user/501/com.teamviewer.service
Could not find service "com.teamviewer.service" in domain for uid: 501


Copy link

tqwhite commented Aug 22, 2021

Please!! Someone answer mailinglists35's question.

I have exactly the same experience with a process of my own. I can load/unload it but cannot find any way to make the un-deprecated commands touch it in any way.


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