cd /news/developer-tools/macos-launchd-services-2-plist-2-scr… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-8360] src=gist.github.com β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

🍎 macOS Launchd Services β€” 2 plist + 2 scripts: automated daily updates & system cleanup

MacOS automation setup using two launchd plist files and two shell scripts to perform daily system updates and hourly cleanup tasks. The daily-update script updates Homebrew, npm, and various developer tools, while the mo-extra script clears caches and removes old downloads, with a 72-hour cooldown to prevent redundant runs. The setup is designed to be privacy-focused, using only `$HOME` or placeholder variables, and requires users to customize file paths before loading the services with launchd.

read3 min views18 publishedMay 22, 2026

macOS (13+ Ventura, Apple Silicon & Intel) β€” 2 launchd plists and 2 shell scripts for keeping your dev machine up to date and clean, automatically.

Zero personal data. All paths use $HOME or PLACEHOLDER variables. Download β†’ tweak paths β†’ load with launchd β€” done.

No system paths, no tokens, no credentials.


🎯 What This Does #

Component What When
daily-update.sh + plist Updates Homebrew, npm, uv, bun, rustup, pipx, conda, pip3, gh extensions, Poetry, AI CLIs (Claude Code, Copilot, Cursor Agent, HuggingFace...), Mole, Orbstack and checks for macOS updates Every day at 09:00
mo-extra + plist Cleans caches (brew, npm, bun, uv, pip, go, cargo, Docker) and removes old ~/Downloads files (30+ days). Built-in 72h cooldown to avoid redundant runs Every hour (skips if within cooldown)

Result: Your machine stays updated and lean β€” automatically, in the background.


πŸ“‹ Files #

File Type Description
com.user.daily-update.plist launchd plist Runs daily-update.sh every morning at 09:00
daily-update.sh Bash script 15-step update: brew, npm, uv, bun, rustup, pipx, conda, AI CLIs, macOS
com.user.mo-extra.plist launchd plist Triggers mo-extra every hour (cooldown managed in script)
mo-extra Bash script 11 cleanup operations: caches, Docker, Downloads

πŸš€ Quick Start #

mkdir -p ~/.local/bin

cp daily-update.sh ~/.local/bin/
cp mo-extra ~/.local/bin/
chmod +x ~/.local/bin/daily-update.sh ~/.local/bin/mo-extra

~/.local/bin/daily-update.sh
~/.local/bin/mo-extra

cp com.user.daily-update.plist ~/Library/LaunchAgents/
cp com.user.mo-extra.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.user.daily-update.plist
launchctl load ~/Library/LaunchAgents/com.user.mo-extra.plist

echo 'alias daily-update="~/.local/bin/daily-update.sh"' >> ~/.zshrc
echo 'alias daily-clean="rm -f ~/.local/state/mo-extra/last-run && ~/.local/bin/mo-extra"' >> ~/.zshrc

πŸ”§ Customization #

Plist Placeholders

Placeholder Where Replace with
PROGRAM_PATH Both plists Absolute path to your script (e.g., /Users/jane/.local/bin/daily-update.sh)
LOG_PATH Both plists Log file path (e.g., /Users/jane/Library/Logs/daily-update.log)
ERROR_LOG_PATH mo-extra plist Error log path (e.g., /Users/jane/Library/Logs/mo-extra-err.log)
HOME_DIR mo-extra plist Your home directory (e.g., /Users/jane)

Script Config Variables

Edit the top of each script to tune:

daily-update.sh:

  • LOG_FILE β€” where logs go (default: ~/Library/Logs/daily-update.log)
  • Sections are modular β€” comment out any tool you don't use (conda, orb, mo, etc.)

mo-extra:

  • COOLDOWN_HOURS β€” minimum hours between runs (default: 72)
  • DOWNLOADS_OLD_DAYS β€” delete Downloads older than N days (default: 30)
  • LOG_DIR β€” log directory (default: ~/Library/Logs)

πŸ“ Requirements #

Tool Needs Notes
Scripts Bash 5+ macOS ships Bash 3; install via brew install bash
brew cleanup Homebrew Most operations depend on it
npm / bun / uv / go / cargo Optional Sections skip automatically if missing
Docker prune Docker or Orbstack Skips if Docker isn't running
mo clean Mole (brew install mo) + sudo NOPASSWD Optional β€” comment out if unused

🧹 Privacy #

This gist is fully generic:

  • No personal paths (/Users/real-username/...)
  • No API keys, tokens, or passwords
  • All user-specific values use $HOME or PLACEHOLDER
  • Example usernames (jane, you) are clearly examples
  • Must be configured before use

πŸ’‘ Pro Tips #

  • Test without launchd first: Run the scripts manually to make sure they work
  • Check logs: cat ~/Library/Logs/daily-update.log
  • Force cleanup early: rm -f ~/.local/state/mo-extra/last-run && mo-extra
  • Customize tool list: Open daily-update.sh and remove sections you don't need
  • Add your own tools: Each section follows the same pattern β€” just copy/paste

Part of my dev workflow. macOS native launchd β€” zero extra dependencies.

── more in #developer-tools 4 stories Β· sorted by recency
── more on @homebrew 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/macos-launchd-servic…] indexed:0 read:3min 2026-05-22 Β· β€”