You are here: Home > Device Management > Apple > macOS > Scripts > Add Apps to the Dock

Add Apps to the macOS Dock with an Applivery Script

Add Apps to the Dock of your macOS Devices once with an Applivery Script, keeping each user's existing Dock and leaving it fully editable.

7 min read

TL;DR

Use an Applivery Script in Loop mode to add Apps to each user's macOS Dock once, without replacing or locking it.

A new Mac shows Apple's default Dock, and the Apps your organization deploys aren't in it. With this Script, you can add the Apps you choose to the end of each user's Dock, once. It doesn't replace what's already there and it doesn't lock anything: users can still reorder, remove, or add items afterwards.

Since it's a Bash Script, the Dock isn't managed by the Policy. The Script adds each App one time per user and then leaves the Dock alone.

Note

If you need the Policy to define the Dock, pin Apps so they can't be removed, or lock the Dock, use the Dock Configuration of the Policy instead. You can learn more about it by following this link.

Requirements

  • macOS Devices enrolled in Applivery and assigned to a Policy.

  • The Applivery MDM Agent enabled in that Policy. Scripts are run by the Agent. Learn more about the macOS Agent.

  • The Apps you want in the Dock deployed to the Devices. The Script doesn't install Apps, it only adds them to the Dock.

  • The add-dock-apps.sh Script, included at the end of this guide.

How the Script works

Each time it runs, the Script does the following:

  1. Finds the user logged in at the console of the Device. If there's none (for example, at the login window), it exits and tries again on the next run.

  2. Goes through the Apps in the list and decides which ones are still pending for that user:

    • An App that was already handled for that user on a previous run is skipped. This is what keeps the Dock editable: if the user removed the App, it stays removed.

    • An App that isn't installed on the Device yet is skipped, and checked again on the next run.

  3. If no App is pending, it exits without touching the Dock.

  4. Waits until that user's Dock is running and ready, for up to five minutes. If it isn't ready by then, it exits and tries again on the next run, so the Dock macOS builds on a first login is never replaced.

  5. For each pending App:

    • If the user already has it in the Dock, nothing changes.

    • Otherwise, it's added at the end of the Apps section of the Dock.

  6. Records each App it has handled for that user in ~/Library/Application Support/AppliveryDockSetup, so it isn't handled again.

  7. Restarts the Dock only if something was added, so the new Apps show up. The Dock blinks for a moment when this happens.

Note

The Script only uses tools included in macOS. You don't need to install anything else on the Device.

Choose the Apps

Open add-dock-apps.sh in a text editor and edit the APPS list with the full path of each App, one per line and between double quotes. This example adds four Apps:

APPS=(
    "/Applications/Google Chrome.app"
    "/Applications/Microsoft Teams.app"
    "/Applications/Slack.app"
    "/Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud.app"
)
Note

Apps are added in the order of the list. To get the exact path of an App, select it in Finder, hold the Option key, and choose Edit > Copy as Pathname (or press Option + Command + C). Then paste it between the quotes.

Upload the Script to Applivery

Once in the Applivery Dashboard, go to the Resources section 1. Select the Scripts tab 2 and click the + Create Script 3 button.

scripts

Fill in the form as follows:

  • Name: Add-DockApps-UserEditable (or any name you prefer).

  • Description: optional, for example Adds Apps to the user's Dock once and leaves it editable.

  • Language: Bash.

Then click Load from file and select your add-dock-apps.sh file, or paste the Script content directly into the editor. Click Create to save the Script.

add-dock-apps-script-form

Add the Script to your macOS Policy

Next, go to the Policies 1 section and select the Policy assigned to your macOS Devices, or create a new one. From the left-hand menu, select the Scripts 2 section.

Warning

Scripts are only available for macOS Devices and require the Applivery MDM Agent to be enabled in the Policy. If it isn't enabled yet, go to the Agent section of the Policy and enable it before continuing.

Click the + Add Script 3 button.

policy script

In the modal view, search for and select the Add-DockApps-UserEditable Script you created in the previous step. Set the Execution method to Loop and click 1d next to the Loop time field. The field is filled with 86400 seconds, so the Script runs once a day. Leave Arguments empty and click Add.

add-dock-apps-add-script-loop
Note

Loop is recommended over Once. The Script only acts on the user logged in at the console at the moment it runs, and only on Apps that are already installed. Running it every day picks up what a single run would miss: an App installed later, a Device that was at the login window, or another user of the same Mac. On Devices that are already set up, the daily run finds nothing pending and exits right away.

The Script now appears in the list. Click Save changes to publish a new version of the Policy. The Script is sent to every Device assigned to the Policy.

add-dock-apps-save-changes
Note

Before rolling it out to all your Devices, add the Script to a pilot Policy with one or two test Devices and check the result as described below.

Result on the Device

Once the Script has run, the user finds the Apps at the end of the Apps section of the Dock, right after the items that were already there. Nothing is removed or reordered.

From that point on, the Dock belongs to the user. They can reorder the new Apps, remove them, or add others as usual, and the Script won't undo those changes on its next runs.

Verify the execution

Open the Device in the Applivery Dashboard, go to the Scripts tab, and click the Execution history button to see the execution history of the Script. You can learn more about it in Scripts by following this link.

Warning

A run finishes successfully even when nothing was added, for example, because nobody was logged in or an App wasn't installed yet. Read the output of the run to know what happened. The Script only fails when an App couldn't be written to the Dock.

This is an example of the output of a first run on a Device where Slack isn't installed yet:

2026-11-09 09:12:40 [Dock] Not installed yet, will retry on next run: /Applications/Slack.app
2026-11-09 09:12:40 [Dock] Added: /Applications/Google Chrome.app
2026-11-09 09:12:40 [Dock] Added: /Applications/Microsoft Teams.app
2026-11-09 09:12:40 [Dock] Added: /Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud.app
2026-11-09 09:12:41 [Dock] Done for jane

And this is an example of the next run on the same Device, with Slack still not installed:

2026-11-10 09:12:38 [Dock] Handled before, left as the user has it: /Applications/Google Chrome.app
2026-11-10 09:12:38 [Dock] Handled before, left as the user has it: /Applications/Microsoft Teams.app
2026-11-10 09:12:38 [Dock] Not installed yet, will retry on next run: /Applications/Slack.app
2026-11-10 09:12:38 [Dock] Handled before, left as the user has it: /Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud.app
2026-11-10 09:12:38 [Dock] Nothing to add for jane

Troubleshooting

Output

Cause

What to do

No user logged in, will retry on next run

The Script ran with nobody logged in at the console: the Device was at the login window or still in Setup Assistant.

Nothing. It's applied on a later run with a user logged in.

Not installed yet, will retry on next run

The App isn't at the path set in the APPS list.

Deploy the App to the Device, or correct the path in the Script.

Already in Dock

The user already had the App in the Dock.

Nothing. The Dock isn't changed.

Handled before, left as the user has it

The App was handled on a previous run for this user.

Nothing. This is what keeps the Dock editable.

Nothing to add for <user>

No App is pending for this user.

Nothing.

Dock not ready yet, will retry on next run

The user's Dock wasn't running or ready after five minutes, usually during a first login.

Nothing. It's applied on the next run.

Could not add, will retry on next run

macOS rejected the change to the Dock. The run is reported as failed.

Check the rest of the output for the error. The App is retried on the next run.

Change the Apps later

To add more Apps to the Dock later, create a new Script with the updated APPS list, then replace the previous one in the Policy: in the Scripts section, click Remove on the old Script, add the new one with + Add Script, and click Save changes. Apps that were already handled for a user are left as that user has them, and only the new ones are added.

To add an App again for a user who removed it, delete its record on that Device. The record is a file with the name of the App inside the user's home folder. For example, run this as that user:

rm "$HOME/Library/Application Support/AppliveryDockSetup/Google Chrome.app"

The App is added again on the next run of the Script.

Script

#!/bin/bash
# Adds apps to the Dock of the user logged in at the console, once per user and app.
# Keeps the existing Dock and leaves it unmanaged, so the user can still reorder or remove anything.
# Deployed from Applivery (runs as root). Safe to run in Loop: an app already handled for a
# user is never added again, and an app that is not installed yet is retried on a later run.
set -uo pipefail

# Edit this list (full paths)
APPS=(
    "/Applications/Google Chrome.app"
    "/Applications/Microsoft Teams.app"
    "/Applications/Slack.app"
    "/Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud.app"
)

log() { echo "$(date '+%F %T') [Dock] $*"; }

USER_=$(stat -f '%Su' /dev/console)
if [ -z "$USER_" ] || [ "$USER_" = "root" ] || [ "$USER_" = "loginwindow" ] || [ "$USER_" = "_mbsetupuser" ]; then
    log "No user logged in, will retry on next run"; exit 0
fi
UID_=$(id -u "$USER_")
# The non-root branch only exists so you can test the script by hand in your own session
as_user() { if [ "$(id -u)" -eq 0 ]; then launchctl asuser "$UID_" sudo -H -u "$USER_" "$@"; else "$@"; fi; }

# One marker per app in the user's home: this is what makes a removal by the user stick
MARKS="$(as_user sh -c 'echo "$HOME"')/Library/Application Support/AppliveryDockSetup"

# Apps still to handle for this user: no marker yet and installed on the device
PENDING=()
for app in "${APPS[@]}"; do
    if [ -e "$MARKS/$(basename "$app")" ]; then
        log "Handled before, left as the user has it: $app"
    elif [ ! -e "$app" ]; then
        log "Not installed yet, will retry on next run: $app"
    else
        PENDING+=("$app")
    fi
done
[ ${#PENDING[@]} -eq 0 ] && { log "Nothing to add for $USER_"; exit 0; }

# The Dock must be running and have its own list of apps. On a first login macOS is still
# building it, and writing at that point would replace the default Dock instead of adding to it.
CURRENT=""
for _ in $(seq 1 60); do
    pgrep -u "$UID_" -x Dock >/dev/null \
        && CURRENT=$(as_user defaults read com.apple.dock persistent-apps 2>/dev/null) \
        && [ -n "$CURRENT" ] && break
    CURRENT=""; sleep 5
done
[ -z "$CURRENT" ] && { log "Dock not ready yet, will retry on next run"; exit 0; }

as_user mkdir -p "$MARKS"
CHANGED=0
FAILED=0
for app in "${PENDING[@]}"; do
    if grep -qF "file://${app// /%20}" <<<"$CURRENT" || grep -qF "\"$app\"" <<<"$CURRENT"; then
        log "Already in Dock: $app"
    elif as_user defaults write com.apple.dock persistent-apps -array-add \
        "<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>${app//&/&amp;}</string><key>_CFURLStringType</key><integer>0</integer></dict></dict><key>tile-type</key><string>file-tile</string></dict>"; then
        log "Added: $app"; CHANGED=1
    else
        log "Could not add, will retry on next run: $app"; FAILED=1; continue
    fi
    as_user touch "$MARKS/$(basename "$app")"
done

# The Dock only shows the new apps after it restarts (it blinks for a moment)
[ $CHANGED -eq 1 ] && as_user killall Dock
log "Done for $USER_"
exit $FAILED

Key Takeaways

  • The Script adds Apps to the end of the Dock once per user and App.
  • It never removes, reorders, or locks anything in the Dock.
  • Apps that aren't installed yet are retried on the next run.
  • Loop mode, once a day, is the recommended execution method.
  • To manage or lock the Dock, use the Dock configuration of the Policy instead.

It adds the Apps you choose to the end of each user's Dock, once. It doesn't replace the existing Dock or lock anything, so users can still reorder, remove, or add items afterwards.

Use the Script when you want to add Apps once and let users manage their Dock. If you need the Policy to define the Dock, pin Apps so they can't be removed, or lock the Dock, use the Dock configuration of the Policy.

macOS Devices enrolled in Applivery and assigned to a Policy with the Applivery MDM Agent enabled, and the Apps you want in the Dock already deployed to the Devices.

No. It only adds Apps that are already installed. If an App isn't installed yet, the Script skips it and checks again on the next run.

No. The Script records each App it handles for each user, so an App the user removed stays removed.

The Script only acts on the user logged in at the moment and on Apps that are already installed. Running it daily picks up Apps installed later, Devices that were at the login window, or other users of the same Mac.

Open the Device in the Applivery Dashboard, go to the Scripts tab, and click Execution history. Read the output of each run, since a run can finish successfully even when nothing was added.

Delete the record of that App in the user's ~/Library/Application Support/AppliveryDockSetup folder. The App is added again on the next run of the Script.

Was this page helpful?

Last updated: November 12, 2026