How to control order of startup items for users at login?

If you're using a shell script to open applications, try something like this:

osascript -e 'launch app "ScreenRecycler"'
pgrep -qx Alfred||open -jga Alfred
sleep 10
pgrep -qx Mail||open -jga Mail
pgrep -qx Transmission||open -jga Transmission

You can run the script at login by for example saving the plist below as ~/Library/LaunchAgents/some.label.plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>some.label</string>
  <key>ProgramArguments</key>
  <array>
    <string>bash</string>
    <string>-c</string>
    <string>osascript -e 'launch app "ScreenRecycler"'
pgrep -qx Alfred||open -jga Alfred
sleep 10
pgrep -qx Mail||open -jga Mail
pgrep -qx Transmission||open -jga Transmission</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

osascript -e 'launch app "AppName" and osascript -e 'activate app "AppName" are blocked until the application finishes opening. launch doesn't make an application frontmost but activate does. If an application like TextEdit or Mail is not running, launch and activate open a new visible default window. osascript -e 'tell app "TextEdit"' -e reopen -e activate -e end also reopens a default window if TextEdit is running but has no open windows.

open -jg usually opens an application hidden (-j) and without making it frontmost (-g). For some applications like TextEdit and Mail, it opens a new visible window if the application is running but has no open windows. To avoid that, check if the application is already running with for example pgrep. The -j option for open was added in 10.8 and it is only shown in the help message and not on the man page.

lsappinfo launch launchandhide=true nofront=true /Applications/TextEdit.app also always opens TextEdit hidden and without making it frontmost. lsappinfo was added in 10.9. I don't know how to use lsappinfo to wait until an application finishes opening.

The settings for login items are stored in ~/Library/Preferences/com.apple.loginitems.plist. You can add a login item with AppleScript:

osascript -e 'tell application "System Events" to make new login item at end with properties {path:"/Applications/TextEdit.app", name:"TextEdit", hidden:true}'

Some applications and processes are started up via property lists in ~/Library/LaunchAgents/, /Library/LaunchAgents/, or /Library/LaunchDaemons/. _com.apple.SMLoginItemBookmarks in /var/db/launchd.db/com.apple.launchd.peruser.$UID/overrides.plist is used to configure login items for helper applications used by sandboxed applications like ScreenFlow, DayOne, and TuneUp.

Since 10.7 there has been a relatively long delay before some login items or launchd jobs are started. I don't know any way to reduce it, but KeyRemap4MacBook's FAQ says it is caused by Resume:

KeyRemap4MacBook does not work after boot on OS X 10.7. What should I do?

"Resume" feature introduced by Lion delays launching apps at login.

Until KeyRemap4MacBook.app is launched at login, the keyboard layout is not changed. Please wait a minute until menu of KeyRemap4MacBook is shown.


So since I've not seen any recommendations I'm going to go ahead and put forth the answer that I've gone forward with so far.

The solution so far for me has been Startupizer. It's not optimal obviously since it is both a paid for solution and it is not a method that is directly available from the OS, but it works and has allowed me to create dependency conditions and various other delays to the order that has been helpful and met my needs.

Hope this helps someone and I certainly hope someone recommends a more OS integral solution soon.