Run your own scripts as part of the Mac login itself, before macOS opens the user's home folder. Works with automatic login too.
Status: still works on macOS 27 (October 2026). The original project was last updated in 2018 and says it was "tested on 10.9". This fork rebuilt it natively for Apple silicon and tested it on macOS 27.0 on an M1 Mac mini, 13 major macOS releases later. The only code change is one small defensive patch. See What was tested on macOS 27.
LoginScriptPlugin was written in 2014 by Per Olofsson at the University of Gothenburg (original repository), based on Apple's Technical Note TN2228, "Running At Login". It hooks into the macOS login process, so your scripts run before any login items, LaunchAgents or apps start. That avoids race conditions that other login-time tricks can't avoid, and it works the same for typed and automatic logins.
This fork adds:
- a one-command build script, because the last release package only contains Intel code (why that matters),
- a ready-made script for one common problem: keeping your home folder on an external drive while still using automatic login,
- this README, which explains that problem, how the plugin fixes it, and how to set it up even if you've never touched the macOS login system before.
- Is this your problem?
- What's actually going on
- Why the usual fixes don't work
- How LoginScriptPlugin fixes it
- Other things you can use it for
- Setup guide
- Checking that it works
- Undo and emergency recovery
- After macOS updates
- Writing your own scripts
- What was tested on macOS 27
- Related problems with an external home folder
- Why you have to build it yourself
- What this fork changes
- Credits and license
You moved your home folder to an external drive. That's the folder with your name in /Users, which holds your documents, settings and app data. People often do this because a Mac with a small internal SSD, such as a 256 GB Mac mini, runs out of room. You also turned on automatic login, maybe because the Mac is a headless server you reach through Screen Sharing, SSH or a remote-desktop app. Since then, after restarting you see some of these:
- A "Sign in to your Apple Account" screen, as if the Mac were new. Signing in fails, even though you're already signed in.
- Apps such as password managers asking for your "login" keychain password, even though automatic login normally unlocks the keychain.
- iCloud saying some data isn't syncing, or settings that don't stick from one restart to the next.
- A partly filled
Libraryfolder on the internal disk "underneath" your home folder, which you can only see when the external drive is unmounted. - It happens after some restarts but not others.
If that sounds familiar, the cause is almost certainly a race between automatic login and the external drive. This plugin fixes it without giving up automatic login or moving your home folder back to the internal disk.
Mounting is how macOS attaches a drive to a folder. The drive's contents appear inside a folder on the internal disk, called the mount point. In the examples here the mount point is /Users/alice. Before the drive is mounted, /Users/alice is just an empty folder on the internal disk. Once it's mounted, the drive covers that folder, and everything you see at that path is on the external drive.
When the Mac starts up, two things happen at the same time:
- macOS finds the external drive and mounts it at
/Users/alice. A USB or Thunderbolt drive takes a few seconds to show up. - Automatic login starts your session straight away, without stopping at the login window.
If the login wins, macOS looks in /Users/alice, finds an empty folder, and treats you as a brand-new user. It quietly creates a fresh Library folder there, with a new keychain, a new signed-out Apple Account database, and no record that setup was ever finished. A few seconds later the drive mounts over that folder and hides it. Programs that started early keep using the hidden copy on the internal disk, while everything that starts later uses your real home folder on the drive. You end up with two half-profiles at the same path, which explains every symptom above.
This is one boot where the login won, on the test Mac, taken from the system logs:
| Time | What happened |
|---|---|
| 16:35:21 | System services report "home directory is inaccessible" (only the empty mount point exists) |
| about 16:35:22 | Automatic login starts the user's session (estimated from when the user's preferences service started) |
| 16:35:25 | macOS starts mounting the external SSD |
| 16:35:29 | The mount finishes, about 7 seconds after the session started |
To check whether this is happening to you: every open file is on a particular device (drive), and you can compare those device numbers. While logged in, run this, replacing alice with your user name:
echo "home drive: $(stat -f '%Hd,%Ld' /Users/alice) internal disk: $(stat -f '%Hd,%Ld' /System/Volumes/Data)"
sudo lsof -u alice 2>/dev/null | awk '$9 ~ "^/Users/alice" {print $6}' | sort | uniq -cThe second command counts the files your session has open in your home folder, grouped by device. If any are on the internal disk's number, some of your programs are using the hidden copy.
| What people try | What happens |
|---|---|
Mount external drives at startup with AutomountDisksWithoutUserLogin |
Needed (setup step 1), but not enough. The drive mounts earlier, but automatic login can still win by a few seconds. |
Make the empty mount point unwritable (owned by root, mode 000) |
On macOS 27 the folder was reset to normal home-folder ownership and permissions during the login, most likely by the login process itself, and the new profile was created anyway. |
A login hook (defaults write com.apple.loginwindow LoginHook ...) |
It runs too late. Apple's TN2228: "The login hook is run at one specific time during the login process (after the home directory has been mounted)". Login hooks are also deprecated. |
| A LaunchAgent or login item that waits for the drive | Also too late: "Agents always run after the home directory has been mounted" (TN2228). |
| Turn on automatic login only once the drive is mounted, then restart the login window | Restarting the login window doesn't trigger automatic login again. This was tested on macOS 27. |
| Turn off automatic login | Works, but after every restart or power cut the Mac sits at the login window until someone logs in. |
| Move the home folder back to the internal disk | Works, but defeats the purpose if the internal disk is too small. |
Every login on a Mac, automatic or typed, goes through the same checklist of steps. The checklist is a rule named system.login.console in the macOS authorization database, and each step is called a mechanism. Here is the list on macOS 27 with the plugin added. The <- notes are explanations, not part of the list.
builtin:prelogin
builtin:policy-banner
loginwindow:login
builtin:login-begin
builtin:reset-password,privileged
loginwindow:FDESupport,privileged
builtin:forward-login,privileged
builtin:auto-login,privileged <- automatic login supplies the user name and password
builtin:authenticate,privileged
builtin:login-success
loginwindow:success
LoginScriptPlugin:premount-root,privileged <- added: runs premount-root-* scripts as root
LoginScriptPlugin:premount-user,privileged <- added: runs premount-user-* scripts
HomeDirMechanism:login,privileged <- macOS opens (or creates) the home folder
HomeDirMechanism:status
MCXMechanism:login
CryptoTokenKit:login
LoginScriptPlugin:postmount-root,privileged <- added: runs postmount-root-* scripts as root
LoginScriptPlugin:postmount-user,privileged <- added: runs postmount-user-* scripts
loginwindow:done <- your desktop starts
Apple's TN2228 describes this approach. To run before the home folder is mounted, "you should install your mechanism before any instance of HomeDirMechanism in the array." LoginScriptPlugin is that kind of mechanism. It runs the scripts in /Library/Application Support/LoginScriptPlugin, waits for each one to finish, and refuses the login if a script exits with code 77.
The included script, examples/premount-root-wait-for-home.sh, runs at the premount-root step:
- It reads
/etc/fstabto see whether the home folder that's logging in is on a drive that fstab mounts. If it isn't, for example an admin account on the internal disk, the login carries on immediately. - If it is, the script checks once a second until the drive is mounted, then lets the login carry on. Only then does macOS open the home folder, so it always finds the real one.
- If the drive still hasn't appeared after 90 seconds (it's unplugged or broken), the script refuses the login rather than letting macOS build an empty profile. The Mac stays at the login window, and other accounts can still log in.
Here's a real boot on the test Mac with the plugin installed (user name changed):
17:23:05.900 running mechanism builtin:auto-login,privileged (8 of 20)
17:23:06.893 running mechanism LoginScriptPlugin:premount-root,privileged (12 of 20)
17:23:08 /Users/alice mounted (check 3) <- the script waited about 2 seconds
17:23:08.984 running mechanism HomeDirMechanism:login,privileged (14 of 20)
17:23:40.742 Succeeded authorizing right 'system.login.console'
Without the plugin, this boot would have lost the race. With it, the whole session started on the external drive, with no Apple Account or keychain prompts.
The external home folder is just one example. What the plugin really provides is a way to run scripts as part of the login itself: before or after the home folder is opened, for typed and automatic logins alike, with the option to block the login. Some other uses are listed below. They are ideas; this fork has only tested the wait script.
- Waiting for other storage. Network home folders (SMB or NFS), or anything else that has to be ready before the session starts.
- Preparing or repairing the home folder before it's used. For example, create it from a template, or fix ownership after a migration.
- Setting things up before any app starts. A
postmount-rootscript runs after the home folder is available but before login items, LaunchAgents and apps start, so they see its changes the first time they launch. This is useful on lab, classroom, kiosk and shared Macs, for example to reset an account to a known state at every login. - Blocking logins. Exit with 77 to refuse a login, for example when a required drive or server is missing, or while a maintenance flag file exists.
- Logging. Record every login before the session starts.
- Replacing a login hook. Apple has deprecated login hooks, and there can only be one (TN2228). This plugin runs any number of scripts, in name order.
The *-user modes run scripts as the user who's logging in, but the source notes that they still run in root's session. Use *-root scripts where you can.
This guide covers the external home folder setup. For other uses, follow steps 2, 3, 5 and 6, and use your own scripts instead of step 4.
Warning
This changes how every login on the Mac works, and a broken setup can stop everyone from logging in at the login window. Before you start, make sure you have another way in. Turn on Remote Login (System Settings > General > Sharing), and check that you can SSH in from another computer as an admin account whose home folder is on the internal disk. Step 5 backs up the original login rules, so you can restore them with one command.
Short version for experienced admins
./build.sh "Apple Development: Your Name (TEAMID)"
sudo cp -R build/LoginScriptPlugin.bundle /Library/Security/SecurityAgentPlugins/
sudo chown -R root:wheel /Library/Security/SecurityAgentPlugins/LoginScriptPlugin.bundle
sudo install -d -o root -g wheel -m 755 "/Library/Application Support/LoginScriptPlugin"
sudo install -o root -g wheel -m 755 examples/premount-root-wait-for-home.sh "/Library/Application Support/LoginScriptPlugin/"
sudo defaults write /Library/Preferences/SystemConfiguration/autodiskmount AutomountDisksWithoutUserLogin -bool true
security authorizationdb read system.login.console | sudo tee /var/root/system.login.console.orig.plist >/dev/null
sudo bash "Installer Resources/Scripts/configureplugin.sh" enable
sudo shutdown -r now # authd only picks up the new rule after a restartThe home folder must be mounted by an /etc/fstab entry. The script waits for the longest fstab mount point that contains the home folder.
- A Mac with Apple silicon. Testing was done on an M1 Mac mini running macOS 27.0. The build script targets macOS 11 or later and builds for Intel when you run it on an Intel Mac, but older macOS versions and Intel Macs haven't been tested.
- Xcode, or just the Command Line Tools (
xcode-select --install). - A code-signing certificate. An Apple Development certificate from a paid developer account worked. To create one, open Xcode > Settings > Accounts, add your Apple Account, then choose Manage Certificates > + > Apple Development. Xcode can also create one for a free Apple Account (a "Personal Team"), but that hasn't been tested with this plugin.
- An admin account and its password.
- For the external home folder use case:
- The drive formatted as APFS, with ownership turned on. Check with
diskutil info /Users/alice | grep Owners, which should sayEnabled. - FileVault turned off. Automatic login isn't available while FileVault is on (Apple).
- The drive formatted as APFS, with ownership turned on. Check with
External home folder only. The script uses /etc/fstab to work out which drive a home folder lives on, and the drive has to mount without waiting for anyone to log in.
a. Mount the drive with /etc/fstab. The tested setup mounts the drive's volume directly on the home folder's path. The top level of the drive is the home folder, so the account keeps its normal home path. The fstab line looks like this:
UUID=11111111-2222-3333-4444-555555555555 /Users/alice apfs rw,auto 0 0
Find your volume's UUID with diskutil info "/Volumes/My SSD" | grep 'Volume UUID'. Then edit fstab with sudo vifs. It opens the vi editor: press G then o to start a new line at the end, type or paste the line, then press Esc and type :wq to save.
If your home folder is somewhere else, such as /Volumes/My SSD/Users/alice, an fstab entry that mounts the volume at /Volumes/My SSD works too, because the script waits for whichever fstab mount point contains the home folder. In fstab, write a space in a path as \040, and write paths without symbolic links.
Haven't moved your home folder yet? (outline, not tested step by step)
- Back up everything first.
- Format the external drive as APFS in Disk Utility, then turn ownership on:
sudo diskutil enableOwnership "/Volumes/My SSD". - Log out of
aliceand log in as a different admin account. - Copy the contents of
/Users/aliceto the top level of the drive, keeping owners and permissions:sudo ditto /Users/alice "/Volumes/My SSD". Terminal may need Full Disk Access first (System Settings > Privacy & Security > Full Disk Access). - Move the old home folder aside and create an empty mount point:
sudo mv /Users/alice /Users/alice.old && sudo mkdir /Users/alice. - Add the fstab line from step 1a, then mount the drive in its new place:
sudo diskutil unmount "/Volumes/My SSD" && sudo diskutil mount -mountPoint /Users/alice <Volume UUID>. - Log in as
aliceand check that everything is there. Keep/Users/alice.oldfor a few weeks before deleting it.
b. Let macOS mount external drives without waiting for a login:
sudo defaults write /Library/Preferences/SystemConfiguration/autodiskmount AutomountDisksWithoutUserLogin -bool trueBy default macOS only mounts external drives after someone logs in. The login is about to wait for the drive, so the drive mustn't wait for the login. Without this setting, the script would most likely time out and refuse the login. That's inferred from the boot logs, not tested.
c. Optional: lock the empty mount point. With the plugin installed, a login can no longer create a profile in the empty folder, so this is only an extra guard. Only run this while the drive is unmounted. While it's mounted, /Users/alice is the drive.
sudo chown root:wheel /Users/alice && sudo chmod 000 /Users/alice && sudo chflags uchg /Users/aliceThe drive still mounts over a folder with the uchg (immutable) flag; this was tested. To rename or delete the folder later, first run sudo chflags nouchg /Users/alice.
To check this step, restart and wait at the login window. Then SSH in as your admin account and run mount | grep ' on /Users/alice ('. The drive should already be mounted.
git clone https://github.com/aayy-dev/LoginScriptPlugin.git
cd LoginScriptPlugin
./build.sh # lists your signing certificates
./build.sh "Apple Development: Your Name (AB12CD34EF)"The last two lines of output should say valid on disk and satisfies its Designated Requirement. If you're connected over SSH and signing fails with errSecInternalComponent, your keychain is locked in that session. Run security unlock-keychain ~/Library/Keychains/login.keychain-db and try again.
sudo mkdir -p /Library/Security/SecurityAgentPlugins
sudo rm -rf /Library/Security/SecurityAgentPlugins/LoginScriptPlugin.bundle
sudo cp -R build/LoginScriptPlugin.bundle /Library/Security/SecurityAgentPlugins/
sudo chown -R root:wheel /Library/Security/SecurityAgentPlugins/LoginScriptPlugin.bundle
codesign --verify --strict /Library/Security/SecurityAgentPlugins/LoginScriptPlugin.bundle && echo "plugin OK"D="/Library/Application Support/LoginScriptPlugin"
sudo mkdir -p "$D"
sudo cp examples/premount-root-wait-for-home.sh "$D/"
sudo chown -R root:wheel "$D"
sudo chmod 755 "$D" "$D/premount-root-wait-for-home.sh"Run it once by hand. The drive is mounted right now, so it should print exit=0 and log a mounted (check 1) line:
sudo "$D/premount-root-wait-for-home.sh" "$(id -u alice)" "$(id -g alice)" /Users/alice; echo "exit=$?"
tail -1 /var/log/wait-for-home.logsecurity authorizationdb read system.login.console | sudo tee /var/root/system.login.console.orig.plist >/dev/null
sudo bash "Installer Resources/Scripts/configureplugin.sh" enable
security authorizationdb read system.login.console 2>/dev/null | grep -E 'auto-login|LoginScriptPlugin|HomeDirMechanism'The first line saves the current rules in root's home folder on the internal disk, so the backup is there even when the external drive isn't. It prints YES (0) when it succeeds. The last command should show the two premount lines directly above HomeDirMechanism:login,privileged:
<string>builtin:auto-login,privileged</string>
<string>LoginScriptPlugin:premount-root,privileged</string>
<string>LoginScriptPlugin:premount-user,privileged</string>
<string>HomeDirMechanism:login,privileged</string>
<string>HomeDirMechanism:status</string>
<string>LoginScriptPlugin:postmount-root,privileged</string>
<string>LoginScriptPlugin:postmount-user,privileged</string>
sudo shutdown -r nowDon't skip this. In testing, a login right after enabling the plugin still used the old rules. The plugin only ran after a restart.
After the restart, give automatic login a minute, then SSH in as your admin account and run:
tail -5 /var/log/wait-for-home.log
log show --last boot --style compact --predicate 'process == "authd"' \
| grep -E 'LoginScriptPlugin:premount-root|HomeDirMechanism:login,|Succeeded authorizing right .system.login.console'
who | grep consoleWhat a pass looks like:
- The wait log has a new line with this boot's time.
check 1means the drive was already mounted. A higher number means the plugin held the login until the drive was ready. Both are fine. - The authd lines appear in this order:
LoginScriptPlugin:premount-root, thenHomeDirMechanism:login, thenSucceeded authorizing right 'system.login.console'. - Your user is listed on
console, meaning automatic login worked.
Then run the device check from What's actually going on. Every open home-folder file should be on the home drive's device number, and none on the internal disk's.
If a login is refused, look at /var/log/wait-for-home.log. A not mounted after 90s line means the drive didn't mount. Fix the drive and restart. Accounts with home folders on the internal disk can still log in.
To switch the plugin off from SSH, use either of these, then restart:
sudo bash "Installer Resources/Scripts/configureplugin.sh" disable
# or restore the exact rules from before step 5:
sudo sh -c 'security authorizationdb write system.login.console < /var/root/system.login.console.orig.plist'The quickest switch-off is to move the scripts out of the folder. With no scripts to run, the plugin does nothing and every login goes ahead. The plugin looks for scripts on every login, so this takes effect at the next login, without a restart.
sudo mkdir -p /var/root/LoginScriptPlugin-disabled
sudo mv "/Library/Application Support/LoginScriptPlugin/"* /var/root/LoginScriptPlugin-disabled/To uninstall completely, run configureplugin.sh disable first, then delete the files, then restart. If the login rules still list a plugin that has been deleted, logins will probably fail (inferred, not tested).
sudo bash "Installer Resources/Scripts/configureplugin.sh" disable
sudo rm -rf /Library/Security/SecurityAgentPlugins/LoginScriptPlugin.bundle "/Library/Application Support/LoginScriptPlugin"
sudo shutdown -r nowNo SSH and no other account? Start up in macOS Recovery, open Terminal, and move the scripts out of Library/Application Support/LoginScriptPlugin on the Data volume, for example /Volumes/Macintosh HD - Data. You may have to mount that volume in Disk Utility first. This path hasn't been tested.
"During some macOS upgrades and updates, the list of login mechanisms in the authorization database gets reset to its default state" (Elliot Jordan). After every macOS update, check that the plugin is still enabled. This should print 4:
security authorizationdb read system.login.console 2>/dev/null | grep -c LoginScriptPluginIf it prints 0, run sudo bash "Installer Resources/Scripts/configureplugin.sh" enable again and restart. Keep this repository, or at least configureplugin.sh, somewhere on the Mac. It's also worth checking that defaults read /Library/Preferences/SystemConfiguration/autodiskmount still shows AutomountDisksWithoutUserLogin = 1.
Put scripts in /Library/Application Support/LoginScriptPlugin. The plugin runs scripts whose names match these patterns, at these points in the login:
| Name starts with | Runs | As |
|---|---|---|
premount-root- |
before the home folder is opened | root |
premount-user- |
before the home folder is opened | the user logging in |
postmount-root- |
after the home folder is opened | root |
postmount-user- |
after the home folder is opened | the user logging in |
For example, a script named postmount-user-com.example.redirect_library.sh runs as the user logging in, after the home folder has been mounted. Each script gets these arguments:
| Variable | Value | Example |
|---|---|---|
$1 |
UID | 501 |
$2 |
GID | 20 |
$3 |
Home folder | /Users/alice |
Rules and behaviour:
- Permissions. Every script, its folder and every folder above it must be owned by root, must not be a symbolic link, and must not be writable by anyone other than root and the
wheeloradmingroups. Scripts must be executable and must be on the startup disk. A script that breaks these rules is skipped silently, and the login goes ahead. - Exit codes. Exit 0 to let the login carry on. Exit 77 (
EX_NOPERM) to refuse it. Any other exit code also lets the login carry on. - Order. Scripts in the same phase run one after another, in alphabetical order. The first one that exits with 77 stops the rest.
- No time limit. The plugin waits as long as a script runs, and the login waits with it. Always build your own timeout into anything that waits, as the example script does.
- A minimal environment. The session hasn't started yet, so
$HOMEand$USERaren't set and$PATHis very basic. Use full paths such as/bin/sleepand/sbin/mount. - Logging. The plugin logs through Apple's old ASL system, which is deprecated. This fork didn't check whether those messages still show up in the unified log on macOS 27, so have your scripts write their own log file.
Test setup: M1 Mac mini, macOS 27.0 (build 26A428), Apple clang 21.0.0, an NVMe SSD in a USB-C enclosure (JMicron bridge, 10 Gb/s) holding the whole home folder, mounted with /etc/fstab, automatic login on.
Verified
- The 2014 code builds with current clang for arm64, with only deprecation warnings.
configureplugin.sh enableworks unchanged. It took the default 16-step login rule to 20 steps, with thepremountsteps right beforeHomeDirMechanism.- Automatic login runs through the same rule:
builtin:auto-login(step 8 of 20), then the plugin (step 12), thenHomeDirMechanism:login(step 14). - On cold boots, the wait script held the login for 1 to 2 seconds (
check 2andcheck 3) until the SSD was mounted. The session then started entirely on the SSD, with no Apple Account or keychain prompts. - macOS loaded the plugin signed with an Apple Development certificate, using the hardened runtime and a secure timestamp. No Developer ID certificate was needed.
- authd only used the changed login rule after a restart.
build.sh(withMIN_MACOS=13.0) produces the same compiled code as the tested binary: identical__text,__cstringand__constsections and the same UUID./and/System/Volumes/Datareport the same device number, so the original "is the script on the boot volume?" check already passes on macOS 27. The patch in this fork is a safety net for systems where they differ (details).- Restarting the login window (
killall loginwindow) doesn't trigger automatic login again. - A root-owned, mode
000mount point was reset to normal home-folder ownership during a login that beat the drive, and then filled. The login process most likely did this, but that wasn't confirmed. - Mounting a drive over a folder with the
uchgflag works. sudo sysadminctl -autologin set ...failed withSACSetAutoLoginPassword error:22. It set the user name but didn't create/etc/kcpassword. Setting automatic login in System Settings worked.- Signing over SSH failed with
errSecInternalComponentuntil the keychain was unlocked withsecurity unlock-keychain.
Observed but not explained. The MCXMechanism:login step took about 31 seconds on the first login after each cold boot, compared with 0.4 seconds later on. It doesn't break anything, but it makes an unattended login slower.
Inferred, not tested
AutomountDisksWithoutUserLoginis required, because otherwise the drive would wait for a login that is waiting for the drive.- Deleting the plugin while it's still listed in the login rules would make logins fail.
Not tested: Intel Macs, macOS versions other than 27.0, ad-hoc signatures, free "Personal Team" certificates, the *-user script modes, the old Xcode project and installer package, and recovery from macOS Recovery.
These aren't fixed by the plugin, but people with an external home folder are likely to run into them.
A screen-recording prompt after every restart. Since macOS 15 Sequoia, apps that capture the screen without the system's picker, such as remote-desktop apps, show a recurring prompt: "... is requesting to bypass the system private window picker and directly access your screen and audio". With an external home folder it can come back after every restart, even after you click Allow. On the test Mac, the service that stores those approvals, replayd, couldn't save them. It logged persistClientListToDisk ... NSCocoaErrorDomain Code=513, and the sandbox log showed deny(1) file-write-create /Users/alice/.TemporaryItems/.... The likely reason is that macOS's safe-save writes a temporary copy on the same drive as the file, in the drive's .TemporaryItems folder, and replayd's sandbox doesn't allow that (inferred).
The workaround, tested with RustDesk, is to add the approval by hand with the current date. replayd reads it but can't overwrite it, so redo it within 30 days; that's the 2592000-second interval. An entry dated far in the future was thrown away.
APP_ID=com.carriez.rustdesk # the app's bundle ID: defaults read /Applications/RustDesk.app/Contents/Info.plist CFBundleIdentifier
P="$HOME/Library/Group Containers/group.com.apple.replayd/ScreenCaptureApprovals.plist"
PB=/usr/libexec/PlistBuddy
NOW="$(LC_ALL=C date -u '+%a %b %d %H:%M:%S GMT %Y')"
cp "$P" "$P.bak"
$PB -c "Delete :$APP_ID" "$P" 2>/dev/null
$PB -c "Add :$APP_ID dict" "$P"
$PB -c "Add :$APP_ID:kScreenCaptureAlertableUsageCount integer 1" "$P"
for k in kScreenCaptureApprovalLastAlerted kScreenCaptureApprovalLastUsed kScreenCapturePrivacyHintDate; do
$PB -c "Add :$APP_ID:$k date '$NOW'" "$P"
done
$PB -c "Add :$APP_ID:kScreenCapturePrivacyHintPolicy integer 2592000" "$P"
killall replayd # restarts by itself and rereads the file; do this while no screen capture is runningPlistBuddy's Set command rejects this date format, but Add accepts it, which is why the script deletes the entry and adds it again.
A slow drive behind a dock or hub. A home folder mostly does small random reads and writes, which suffer badly over the older USB storage protocol (BOT). Check which protocol the drive uses with ioreg -l -w0 | grep -oE '"bInterfaceProtocol"=[0-9]+' | sort -u. 98 is UASP, which is what you want, and 80 is BOT. On the test Mac, the same enclosure showed 80 through a Thunderbolt dock and 98 when plugged straight into the Mac. Shut down before you move the drive. Never unplug a mounted home folder.
Keychain-unlock workarounds. If you wrote a script to unlock your login keychain after logging in, you probably don't need it once logins can no longer land in the empty internal folder. Automatic login can then unlock the real keychain itself (inferred).
The last release, 1.0b32 from February 2016, contains only an Intel (x86_64) binary, built against the OS X 10.11 SDK for OS X 10.7 and later. Apple silicon Macs can't load Intel code into a native process: "The system prevents you from mixing arm64 code and x86_64 code in the same process" (Apple). macOS 27 still includes an Intel helper for authorization plugins (authorizationhosthelper.x86_64.xpc), but it needs Rosetta, and that route wasn't tested. Rosetta also has an end date: Apple says it "will be available through macOS 27 — as a general-purpose tool", after which only "a subset of Rosetta functionality aimed at supporting older unmaintained gaming titles" will remain (Apple). A native build avoids all of this, and build.sh makes it one command.
The Xcode project from 2018 targets OS X 10.7 and signs with the University of Gothenburg's Developer ID. It hasn't been updated or tested in this fork; use build.sh instead.
Compared with the original (last commit April 2018):
LoginScriptPlugin/LoginScriptPlugin.c: the check that a script is on the startup disk also accepts the Data volume (/System/Volumes/Data). Since macOS 10.15 the startup disk has been split into a read-only System volume at/and a Data volume that holds/Library. The original check compared each script's device number with/only. On macOS 27 both volumes report the same device number, so the original check passes there anyway, and this change is a harmless safety net for systems where they differ. Scripts on external drives are still rejected.build.sh: builds and signs the plugin with clang, without Xcode.examples/premount-root-wait-for-home.sh: waits for an fstab-mounted home folder.- This README, which also keeps the original documentation in Writing your own scripts.
configureplugin.sh, the Xcode project and the installer resources haven't changed.
LoginScriptPlugin was created by Per Olofsson at the University of Gothenburg. The changes in this fork are released under the same license.
Copyright 2014 Per Olofsson, University of Gothenburg. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.