LaunchControl 2 is the only fully-featured launchd(8) GUI for macOS. Use it to learn about launchd(8) and to create, manage and debug launchd(8) services.
The user inteface is split into two parts. The sidebar and the main view.
Note: Learn your way around the interface using tooltips. You can enable tootips by selecting from the menu.
Note: LaunchControl will present alerts before all destructive actions to avoid accidental modifications. All of these alerts may be disabled. To re-enable all of them select .
The sidebar displays a list of jobs with their respective status. It also shows a filter panel which is used to change which jobs are displayed in the job list. When a job is selected from the job list it is displayed in the main view.
The sidebar can be shown or hidden by selecting either or from the menu. Alternatively you can click the Sidebar icon () from the toolbar.
The Filter SectionUse the filter section to change which jobs are displayed in the job list. You can filter by service type, runtime status, job properties, and the job status in the override database. The filter section can be hidden by selecting from the menu. Service TypesThe first section allows filtering by service type. LaunchControl differentiates nine different job types:
Note: On a fresh install of macOS the domain User Agents is empty. If the job list is grouped by service type on a service type checkbox or its label will scroll the job list to the respective service type.
RuntimeHere you can specifiy if you want the job list to display jobs which are currently loaded or unloaded. Further you can filter jobs by their status:
The status filters (Running, Ok, Error, Signalled) will only be applied if the Status checkbox has been checked. on a runtime filter will check this filter exclusively. will select all runtime filters. Property ListUse this section to display jobs in the job list based on the value of their Disabled key and on their validation status.
The property list filters (Ok, Warning, Error, Invalid) will only be applied if the Property List checkbox has been checked. on a property list filter will check this filter exclusively. will select all property list filters. Override DBUse this section to display jobs based on their record in the launchd(8) override database. The override db filters (Enabled, Disabled) will only be applied if the Override DB checkbox has been checked. on an override db filter will check this filter exclusively. will select all override db filters. System SettingsUse this section to display jobs depending on their status in System Settings>General>Login Items>Allow in the Background. The system settings filter (Enabled, Disabled) will only be applied if the System Settings checkbox has been checked. |
|
This is a list of all jobs matching the criteria set in the filter panel. Selecting a job in this list will load it in the Main View. It consists of three columns: File, Enabled, Status.
The first column displays the file names of the job definition files. The extension (.plist) is omitted unless the configuration option “Show .plist extension in Job List” is enabled. The color of the file name is displayed represents its validation status.
| Color | Validation status | Description |
|---|---|---|
| Black | Ok | Every aspect of the job definition is ok. The job should run just fine. |
| Yellow | Warning | There are one or more minor problems with this job definition. A warning will not keep the job from running. It just might not behave as expected. |
| Red | Error | There is a severe problem with the job definition. launchd(8) will not be able to start this job. |
Note: The colors in this column do not reflect the run-time status of a job but rather the outcome of LaunchControl’s validation.
The checkboxes in the second column indicate if a job is enabled or not. An enabled job will be loaded automatically on system boot (daemons) or login (agents). The check mark indicates if the Disabled key of the job definition has been set to true (not checked) or false (checked). The background color indicates if this setting has been overridden with true (red) or false (green).
If a checkbox is grey or blue, the status of the checkbox will tell you if the job is enabled or not. If a checkbox is green, the job is enabled no matter what the checkbox status indicates. If a checkbox is red, the job is disabled no matter what the checkbox indicates.
| Checked | Color | Description |
|---|---|---|
| No | Grey | The job’s Disabled key is set to true. The job is effectively disabled and will not be automatically loaded by launchd(8). |
| Yes | Blue | The job’s Disabled key is set to false or not set at all. The job is effectively enabled and will be automatically loaded by launchd(8). |
| No | Green | The job’s Disabled key is set to true, but this value is ignored as it has been overridden. The job is effectively enabled and will be automatically loaded by launchd(8). |
| Yes | Green | The job’s Disabled key is set to false or not set at all, but this value is ignored as it has been overridden. The job is effectively enabled and will be automatically loaded by launchd(8). |
| No | Red | The job’s Disabled key is set to true, but this value is ignored as it has been overridden. The job is effectively disabled and will not be automatically loaded by launchd(8). |
| Yes | Red | The job’s Disabled key is set to false or not set at all, but this value is ignored as it has been overridden. The job is effectively disabled and will not be automatically loaded by launchd(8). |
| No | Purple | (macOS Ventura only) The job has been disabled in System Settings>General>Login Items>Allow in the Background. The job is effectively disabled and will not be automatically loaded by launchd(8). |
| Yes | Purple | (macOS Ventura only) The job has been disabled in System Settings>General>Login Items>Allow in the Background. The job is effectively disabled and will not be automatically loaded by launchd(8). |
Clicking on a check box will set a job’s Disabled key. Use the to change the override. The override of a job can be changed via LaunchControl but removing a job from the override database requires a rather complicated procedure.
Note: Don’t confuse this with the job state. Just because a job is enabled does not mean that the job is loaded or even running and vice versa.
The third column displays the job state. A job is either loaded or unloaded. Loaded jobs may have the following sub-states:
| State | Description |
|---|---|
| Ok | In case it has been already executed, is has returned successfully. |
| Running or <PID> | It is currently being executed. The text “Running” is replaced by the processes current process ID (PID) if the preferences option Look & Feel>Display PID of Job instead of ‘Running’ has been enabled. |
| Error <CODE> | It has been executed and it returned an error. The return code is provided in the status column. |
| SIG<NAME> | It has been executed and it terminated with the signal given in the status column. |
A job may also be in state ‘Unknown’. In this case LaunchControl was either unable to parse the job definition file or it could not find the job label. Possible reasons for the first case might be that LaunchControl was unable to read the file due to insufficient permissions or due to a malformed job definition.
This is where the details of a job are displayed. You can place a variety of specialized subviews in this area. Place new subviews via the six rightmost toolbar buttons or corresponding items in the View menu. You can change/swap a view by selecting its icon in its header and then selecting the view you’d like to show instead from the popup menu.
If LaunchControl detects problems with the selected job it will offer guidance in the info panel at the bottom of the main view. If multiple suggestions are offered you can navigate them using the buttons on the right hand side of the panel or using the ⌘[ (back) and ⌘] (forward) keys.
This editor provides dedicated controls for every key supported by launchd(8). It is the heart of LaunchControl. Here you are shown which problems LaunchControl foresees and how to fix them. It discovers problems immediately, even before you run the job. If, for example, you provide the key Program, LaunchControl will check if the program exists and if it is executable. If Program is a relative path, LaunchControl will check for the key WorkingDirectory. If this key is set, LaunchControl will assume the program is in this directory. It also considers the keys User and Group when evaluating the permissions. It performs as many checks as possible to ensure that the job definition is valid before you load it into launchd(8).
Using this mode will guarantee that the resulting job definition is valid.
Changes made in this editor are mirrored immediately in the Expert Editor and the XML View.
Note: Modifications won’t affect the running instance until you save the property list and load it into launchd(8). When saving a property list via LaunchControl will offer to load the job automatically.
Click on the + button below the last key control panel or press ⌘⇧P to open the key palette.
In the Palette panel you’ll find any key officially supported by launchd(8). To make it easier for you to find the right key, LaunchControl has grouped keys into sections. Selecting a section using the popup button in the upper part of the palette panel will limit the number of displayed keys. You may also use the key filter below the section popup button to search for keys by name or description.
You can either drag a key from the palette and drop it onto the Standard Editor or simply press ⏎ to add it to the currentl job.
Click on the small cross symbol in the upper right corner of the key control.
LaunchControl allows you to store notes for services. Select from the menu to add the Notes control to the Standard Editor. This control behaves very much like key controls in the Standard Editor.
Notes are stored in the LaunchControl settings independently of the service definition. Changes to notes therefore have no effect on the change status of a job definition. Removing the Notes control removes the notes associated with the service. The user will be prompted to save changes to notes when another service is selected, when the window/tab is closed, or when LaunchControl is terminated.
Note: LaunchControl associates services with notes using the URL of the service definition. If you rename/move a service definition outside of LaunchControl this connection will be broken and the notes of this service will not be visible anymore.
launchd supports more configuration keys then are officially supported and documented. For these keys LaunchControl offers no controls in the Standard Editor. Use the Expert Editor in cases where you want to use these keys. The Expert Editor is also the only way to fix an invalid property list. In this case the Standard Editor will point out the problem but the Expert Editor is the editor to fix it.
The Expert Editor offers no guidance. It performs no validation at all.
Changes made in this editor are mirrored immediately in the Standard Editor and the XML View.
Note: Modifications won’t affect the running instance until you save the property list and load it into launchd(8). When saving a property list via LaunchControl will offer to load the job automatically.
Move the mouse pointer over a key. Two or more symbols will appear next to the key name: Add child, Add sibling and Remove. Click one of the first two.
Move the mouse pointer to the key you’d like to remove. Two or more symbols will appear next to the key name: Add child, Add sibling and Remove. Click the last one.
This view presents the property list of the selected job as XML. It is not possible to modify the property list in this view. This way LaunchControl ensures that any property list created is structurally intact. To modify the job use the Standard Editor or the Expert Editor for this.
The XML View is most useful for users who want to gain a deeper understanding of launchd(8).
Use these views to monitor the standard output/error streams of a job. For this feature to work you have to add the StandardOutPath/StandardErrorPath keys to a job.
Each of these views provides five controls.
The text field is updated in real time as the job is running. Use this button to keep this view from updating or resume operation.
Use this button to append a marker including a time stamp to the log. This might help telling similar log entries apart.
Use this button to clear the contents of the view. The contents of the log file will not be changed by this operation.
Use this button to bring up a search field in this view. Search terms will be highlighted.
Use this button to move a log file to the Trash.
Use this view to check the launchd(8) log file. The log shows only messages relevant to the current job. The controls work similar to the controls in the Standard Output / Error Views.
This view presents the internals of a loaded job as seen by launchd(8). Its contents resembles the output of the command launchctl print.
LaunchControl allows you to interact with the currently selected job via natural language. It does so by accessing large language models (LLMs) offered by various providers.
Model providers are configured in the AI Section of the LaunchControl Settings
LaunchControl currently supports these language model providers:
To select a provider, select it from the providers popup. When done, select the model from the models popup.
LaunchControl only shows model providers which offer at least one model. Local model providers must have their models loaded in order for them to be displayed in the model popup.
When the model provider configuration is changed, the provider and model popups are updated automatically. Use the reload button to the right of the models popup to refresh the list of model providers and models without changing the configuration.
After you have selected a provider and model, enter your question or request regarding the currently selectd job in the input field at the bottom of the AI Chat View. The answer will appear in the response field above. LaunchControl provides the path, the contents of the job definition, and all findings as seen in the Standard Editor to the LLM.
Note: Modifications won’t affect the running instance until you save the property list and load it into launchd(8). When saving a property list via LaunchControl will offer to load the job automatically.
Note: The usefulness of the AI integration depends entirely on the quality of the selected language model.
In addition to the Job List LaunchControl provides a search facility to quickly locate jobs. Click to bring up the search panel. The search field will already be selected so you can start typing. LaunchControl will search every job definition file name and label as well as the content of the Program/ProgramArguments keys. The results are displayed immediately below the search field. Use the ↑ and ↓ keys to navigate the result set. When the proper job is selected hit ⏎ to jump to the job definition.
The search can be further customized by changing the options available in the menu attached to the magnifying glass icon in the search bar.
The third option is to drag and drop a launchd property list onto the LaunchControl Dock icon. The job will be opened in a new LaunchControl window.
Selecting from the menu will bring up a panel where you can choose what type of job you want to create. Clicking Create will create an empty job skeleton. The job will have its name set according to the preferences setting ‘Custom prefix’ appended by the string ‘.job’. The value of key Program defaults to /usr/bin/env which may be customized by changing the preferences value ‘Custom program’.
Every job definition saved as a template will appear in the menu. Selecting a template from this menu will create an instance of it.
on the name in the Job List or press ⏎ while it is selected and the Job List has input focus. You can edit the name inline. The extension (.plist) is appended automatically.
Note: Job definition files cannot be renamed while there are unsaved modifications.
Note: If the configuration option ‘Synchronize file name and label’ has been checked, renaming a job definition file will change the job’s label as well.
Select from the menu to move the currently selected job definition to the trash. You may recover accidentally removed job definitions by selecting them in the Trash and choosing from the Finder menu. LaunchControl will detect that the file has been restored and, given the filter criteria still match, add it to the job list again.
There is a configuration option “Remove job definitions” where you can choose to delete jobs instead of moving them to the trash. Deleted jobs cannot be restored. The menu item will be labelled .
Depending on the state of the currently selected job, the load/unload button in the toolbar will either load () or unload (
) the job. Alternatively you may select the appropriate action from the menu.
Note: Loading a job does not necessarily start it. How/when a job is started is determined by the keys you provided for launchd(8). If you want to start a job immediately, load it and select either (⌘⇧T) from the menu or click the start button () in the menu bar.
Note: Templates cannot not be loaded. Instances of templates can.
If you want to change tye type of a job, say, you want to change a User Agent into a Global Agent, follow these steps:
Sometimes it is desirable to quickly load/unload/start/stop a job on demand without hunting it down in LaunchControl every time. QuickLaunch is a small menu extra in your menu bar showing selected jobs and their status. Once started via the Utilities section of the LaunchControl preferences panel it runs independently of LaunchControl.
The menu contains a hierarchy of jobs, their respective status and controls.
For folders QuickLaunch displays a summary of the status of all the jobs contained in this folder and all its subfolders. This summary is represented as a square box cotaininf one to four colored dots. For jobs the status is represented by a simple colored dot. QuickLaunch knows four job states: Unloaded (grey), Loaded (blue), running (green) and Error (red).
Clicking on a job in QuickLaunch opens it in LaunchControl.
The controls for jobs and job groups are the same as in LaunchControl:
| Icon | Description |
|---|---|
| Start job | |
| Stop job | |
| Load job | |
| Unload job |
QuickLaunch can also operate on groups of jobs. In the image above there are four groups: the root group and the grous “Backup”, “Web”, and “Web Development”. Selecting an action in the root group menu item will perform this action on all jobs in the root group. Note that in the screenshot above no actions are enabled because the group contains no services, only groups. Selecting an action in the “Web Development” group will perform this action on all jobs in the “Web Development” group. These actions don’t affect jobs in subgroups unless you hold down the ⌥ key while selecting the action. In this case the action will be performed on all jobs in the group and its subgroups.
Note: macOS 13 and older don’t allow for alternating menu items as used by QuickLaunch. For this reason the availability of actions and the action’s scope (recursive or non-recursive) is set via a checkbox.
Select from the QuickLaunch menu item menu to bring up the QuickLaunch preferences window:
Use the buttons in the menu bar to add jobs, add folders, add menu separators or delete the selected item from the QuickLaunch menu. The checkbox does just what you’d expect. The Update frequency is the time QuickLaunch waits between status checks. If set to 60 seconds QuickLaunch will update the Menu Extra icon every minute. When the menu is open the Menu Extra icon and all status indicators/controls in the menu are updated every second.
Note: For obvious reasons job templates cannot be added to QuickLaunch.
Use this utility to receive notifications via the macOS Notification Center whenever a launchd(8) job is added, removed or modified. Once started via the Utilities section of the LaunchControl preferences panel it runs independently of LaunchControl.
You can configure a list of jobs you’d like to exclude from being reported in the Utilities section of the LaunchControl preferences.
Note: Changes applied via LaunchControlare not reported.
While debugging a job it is not necessary to load/unload it manually every time a change to the configuration is made. Event triggered jobs might not be executed at all when loading. The preferred method is to start the job unconditionally by selecting (⌘⇧T) from the menu. When a change is detected, a request panel will appear: click the button.
It is important to remember that launchd is responsible for turning a process into a background process. When referencing a shell script in Program or ProgramArguments make sure the script does not put the actual program into the background. Some programs require special command line arguments (something like --foreground) to prevent them from daemonizing themselves. If in doubt try to run the program/script from the terminal. The program/script should only return after the process is done.
The same goes for resource limits, redirection of standard input/output/error, re-nicing and so on. launchd supports a wealth of configuration options. Use them and don’t try to emulate their effects.
Pipes (|), redirection (<,>) and variable expansion ($VAR) are only three examples for shell constructs that won’t be interpreted by launchd(8). If you want to write shell code, give it to the shell. Instead of
cat /etc/passwd | sort
write
/bin/sh -c "cat /etc/passwd | sort"
This is the obvious first step. Make sure you understand every warning and error that LaunchControl reports. Hovering over a warning or error sign in a config sections header will provide details about the error/warning.
Check for the exit code of the job in the status column of the job list. Move your mouse over the error code to bring up a tool tip with a likely error reason.
Open the launchd(8) Log View and repeat the failed load or start operation. Watch out for warnings and errors.
Make sure you configure the keys StandardErrorPath and StandardOutPath. The job might write relevant information to these files. After running the job either click on the trace button in the standard out/error config section which will open the corresponding file in Console.app, or add the Standard Output/Error subviews to your workspace.
Custom jobs are just like regular jobs with the exception that they might be located anywhere on the filesystem. Use them to work with jobs not (yet) installed on your system. When creating a new custom job the user is asked for the location. Existing jobs can be imported by selecting from the menu.
Templates are used as skeletons for new jobs.
Every job definition you select may be turned into a template by selecting .
Templates are stored in the folder ~/Library/Application Support/LaunchControl/Templates.
Renaming and removing templates works like renaming and removing regular job definitions. on a definition in the job list or press ⏎ while it is selected and the job list has input focus. to rename it. The menu will move the selected job definition to the trash.
All templates will appear in the menu. Selecting a template from this menu will bring up a dialog where you can choose the type of service to be created.
LaunchControl supports dynamic values in job definitions. When a job definition is saved every occurrence of such a variable will be replaced by its value.
Currently only a single variable is supported: #Label#
Note: Variables will also be replaced if you rename a file and have the ‘Synchronize file name and label’ configuration option set.
LaunchControl supports importing of jobs from a crontab file. First select the domain (e.g. User Agent, Global Daemon, etc) you want the cron jobs to be imported into using the job domain selector in the upper left of the window. Then select from the menu and select a crontab to open the cron import window.
When the import window opens a list of all jobs configured in the crontab will be displayed. Use the filter field to filter the list of cron jobs by the command field.
To select a cron job for import click the check box in the first column. Alternatively you may use the ↑ or ↓ key to navigate to the job and press the ␣ key to mark it for import. You don’t have to leave the filter field for this.
Environment variables defined in the crontab are listed in additional columns of the result table. Their title is prefixed with a $ sign. If a job relies on an environment variable you should check the corresponding check box.
Crontabs may contain an additional field, the user field. Use the “crontab is a system crontab” checkbox to switch between types.
To mark all jobs in the table for import click the “Check all” button in the lower left. Click “Uncheck all” for the reverse effect. Use the “Show checked only” checkbox to display only jobs which have been marked for import.
Click the button to import all marked jobs into the current domain.
LaunchControl will create jobs with the appropriate keys:
Created jobs will have names like “tmp.cronimport.#” where # is a
number. Use the job filter (⌘⇧J) to find them quickly.
LaunchControl supports exporting of jobs to crontab files. Select from the menu to open the cron export window.
When the export window opens a list of all launchd jobs will be displayed. Use the filter field to filter the list of cron jobs. Using the filter menu you can choose to filter by Label, filename, Program/ProgramArguments, StandardOutPath and StandardErrorPath. You can also choose to include system jobs in your search or to display only jobs of the currently active domain.
To select a cron job for export click the check box in the first column. Alternatively you may use the ↑ or ↓ key to navigate to the job and press the ␣ key to mark it for export. You don’t have to leave the filter field for this.
To mark all jobs in the table for export click the button in the lower left. Click for the reverse effect. Use the checkbox to display only jobs which have been marked for export.
Click the button and select a destination directory. LaunchControl will create one crontab per user in this directory.
LaunchControl translates the following keys to their cron equivalents:
The LaunchControl preferences panel is divided into seven sections: General, Utilities, Info Panel, Palette, Session, Look & Feel, and AI.
If set LaunchControl will synchronize the label and filename of a job. When you rename a job LaunchControl will set the Label of the job to the name of the property list without the .plist extension. Changing the Label will not, however, rename the file.
When you create a job in LaunchControl you are required to enter a job name. launchd(8) job names usually follow the Reverse Domain Name Notation. By default LaunchControl uses the name local.job possibly appended by a number separated by a dash (local.job-1) in case the name is already taken. Use this setting to change the prefix.
Every launchd(8) job requires a program to run. By default LaunchControl supplies /usr/bin/env for new jobs. This is the place to change the dafault value.
The Program and ProgramArguments key control offers functionality to edit the referenced script or any text files appearing in the command line. By default LaunchControl uses TextEdit.app to edit text files. You can make LaunchControl use your favorite text editor here.
Here you configure what LaunchControl should to when removing a job definition. LaunchControl will either permanently delete it or to move it to the Trash.
This setting affects which jobs LaunchControl will display in the Main View and the Search Panel. By default LaunchControl will only show jobs having the file extension .plist.
LaunchControl ships with several utilities: fdautil, QuickLaunch and JobWatch. Here you can install/start them.
Add the label — or a glob pattern matching the label — of jobs you’d like JobWatch to ignore in table view below.
The Info Panel is a yellow area at the bottom of the Main View. In this configuration section you tell LaunchControl which information you’d like to see and which not.
Keys which have been deprecated by Apple do still work but they are bound to become unsupported eventually. When this option is enabled LaunchControl will inform you if a job definition contains a deprecated key.
LaunchControl will (in addition to the colored checkbox in the Job List and the Window Title) point out that a job’s Disabled key is ignored by launchd(8) if the job has a record in the Override Database.
Only because a job is loaded it is not necessarily started. It requires a key which tells launchd(8) when to start it. Check this checkbox if you want LaunchControl to point out that no such key is defined for the current job.
Note: Keys without a run condition can be useful. They might be used for manual starts, maybe via QuickLaunch.
When a job has failed and the keys StandardOutPath or StandardErrorPath are missing LaunchControl will suggest to add them to the job in order to help you understand why it failed.
When a job has failed and the file defined for keys StandardOutPath contains data LaunchControl will suggest to review its contents in order to help you understand why it failed.
When a job has failed and the file defined for keys StandardErrorPath contains data LaunchControl will suggest to review its contents in order to help you understand why it failed.
Keys which have been deprecated by Apple do still work but they are bound to become unsupported eventually. Uncheck this option if you don’t want the palette to displays these keys.
launchd(8) has seen many changes over the years. In this time new keys have been added, some have been deprecated, and some are not supported anymore.
LaunchControl knows which key is supported on which version of macOS. Disabling this option will show only keys in the Palette which are supported by the version of macOS currently running.
If this option is enabled you will also see unsupported keys. This might be useful in case you are creating a job for a different version of macOS.
Some keys only make sense for daemons. You can add them to an agent but they will have no effect. Disable this option if you’d like LaunchControl to hide such keys in the palette when editing an agent.
Here you configure how you want LaunchControl to behave when starting or opening a new tab/window.
Use the and menu items to store the custom settings.
Click on the reset buttons to restore the default Startup Session and New Tab/Window settings.
As the extension .plist is common for all valid job definition files LaunchControl chooses to hide it in the job list. Check this option if you prefer to see it.
By default LaunchControl displays the status Running for a job if it is currently running. Check this option if you’d like to see the job’s process identifier (PID) instead.
In this section you configure the language model providers. Depending on the provider you may have to enter an API key and/or an API URL.
Unfold the model provider by clicking on the disclosure triangle or by pressing the → key while the provider is selected.
To change a configuration value, select its row and then click on it or press ⏎ while it is selected. Press ⏎ to apply the change.
The status column shows the connection status. Grey indicates that no connection check has been performed yet. Red indicates a configuration issue, the model provider is not accessible. Green indicates that the configuration is valid and that the model provider is reachable.
When launchd(8) is about to load a job it will check if it has the Disabled key set. Disabled jobs will not be loaded. The value of this key can be overridden in the launchd(8) override database so that if a job has a record there the value of its Disabled key will be ignored.
With macOS 11 (Big Sur) Apple introduced Signed System Volumes (SSV). In essence, the SSV is a read-only system volume that is cryptographically signed to help ensure the integrity of the operating system.
This security feature makes it is impossible to remove records from the launchd override database.
With macOS Mojave Apple added yet another security measure. Applications requiring access to sensitive data need special permissions beyond Unix permissions and ACLs. This is accomplished by granting them Full Disk Access in the Security & Privacy System Settings Panel. While this solution works well for applications it is flawed when it comes to scripts. To grant a script (be it Shell, Python, Perl, …) Full Disk Access you have grant Full Disk Access to the executing interpreter. This approach is flawed as it grants every script of this type Full Disk Access.
LaunchControl provides a command line utility to avoid this situation. The utility is called fdautil and can be installed via the LaunchControl preferences Utilities panel to /usr/local/bin. When installing fdautil LaunchControl will ask you to add it to the list of programs with Full Disk Access.
To grant a job Full Disk Access you’ll have to prefix the command line you’d like to execute with /Applications/LaunchControl.app/Contents/MacOS/fdautil exec. If for example your original job performed the command
/Users/Me/Scripts/CheckDownloads.py
you change it to
/Applications/LaunchControl.app/Contents/MacOS/fdautil exec exec /Users/Me/Scripts/CheckDownloads.py
LaunchControl requires admin privileges to add your script (including the specific options and arguments) to the fdautil configuration file.
Note: On macOS Ventura services which run with fdautil are displayed as “Robby Pahlig” in System Settings>General>Login Items>Allow in the Background. Apple chose to display the name of the signing entity of an executable instead of a more informative text.
fdautil stores the complete command you want to execute with Full Disk Access in the configuration file /Library/Preferences/com.soma-zone.LaunchControl.fdautil.plist. This configuration file is writable only by root. Only commands (including arguments/options) stored in this configuration file are executed by fdautil, others are rejected. It uses execvp(3) to replace itself with the command you’d like to run. LaunchControl does all the configuration for you. When you change the Program/ProgramArguments key it is updating the fdautil configuration automatically.
You get the benefit of Apple’s new security feature and can use
scripts with Full Disk Access.
OS X 10.11 El Capitan introduced System Integrity Protection (SIP). This feature provides an additional layer of security by protecting certain sytem files from modification even by root. In order to make changes to those protected files you have to disable SIP:
csrutil disable and press the ⏎ key.reboot and press the ⏎ key.SIP is now disabled.
It is recommended to enable SIP again. Follow the instructions above. The command to enable SIP is csrutil enable.
In addition to SIP macOS 10.15 Catalina separates the Operating System (OS) from the user data. The OS is mounted read-only, so even with SIP disabled you cannot make changes to system files. In order to mount the OS partition in read/write mode disable SIP (see above), open Termina.app and enter:
sudo mount -uw /