Skip to content

feat(check): detect orphan LaunchAgents in mo check#695

Open
sebastianbreguel wants to merge 1 commit intotw93:mainfrom
sebastianbreguel:feat/check-orphan-launch-agents
Open

feat(check): detect orphan LaunchAgents in mo check#695
sebastianbreguel wants to merge 1 commit intotw93:mainfrom
sebastianbreguel:feat/check-orphan-launch-agents

Conversation

@sebastianbreguel
Copy link
Copy Markdown
Contributor

Summary

Adds check_orphan_launch_agents() to mo check, parallel to check_disk_smart. Read-only scan of ~/Library/LaunchAgents and /Library/LaunchAgents that flags plists whose Program (or ProgramArguments[0]) points to an absolute path that no longer exists — the classic leftover after dragging an app to trash without uninstalling its background helper.

Extends the orphan-detection pattern from #682 (SystemExtensions / LaunchAgents in lib/uninstall/batch.sh) into the check side. Surfaces for awareness only, mirroring check_login_items. Zero delete, no new flag, no new command.

Behavior

  • Skip com.apple.* (system XPC handlers without on-disk Program paths)
  • Skip relative paths (PATH-resolved binaries)
  • Use plutil -extract Program raw (fallback ProgramArguments.0) for safe plist parsing — no grep/eval
  • Honor is_whitelisted "check_orphan_launch_agents"
  • Output mirrors check_login_items: count + preview of up to 3 labels

Real-world audit

Tested across every plist on my Mac:

  • 1 true positive: com.logitech.manager.daemon (Logi Options uninstalled, helper plist orphaned)
  • 1 true negative: com.lwouis.alt-tab-macos (binary present, correctly not flagged)
  • Zero false positives on remaining plists

Tests

3 new BATS cases in tests/check_system.bats:

  • Orphan detection + valid Program ignored + com.apple.* skipped (combined)
  • None orphaned when clean
  • Whitelist honored

All 7 tests in the file pass. Hidden MOLE_LAUNCH_AGENT_DIRS env var (colon-separated) provides directory override for test isolation — no production surface.

Diff

  • lib/check/all.sh: +34 LOC
  • tests/check_system.bats: +55 LOC
  • Total: 2 files, +89 / -0

Test plan

  • bats tests/check_system.bats — 7/7 passing
  • Manual smoke against real ~/Library/LaunchAgents + /Library/LaunchAgents
  • Whitelist verified (mo whitelist add check_orphan_launch_agents silences it)

Add check_orphan_launch_agents() next to check_disk_smart in
lib/check/all.sh. Read-only scan of ~/Library/LaunchAgents and
/Library/LaunchAgents that flags plists whose Program (or
ProgramArguments[0]) points to an absolute path that no longer
exists on disk — the classic leftover after dragging an app to
trash without uninstalling its background helper.

Conservative defaults:
- Skip com.apple.* (system XPC handlers)
- Skip relative paths (PATH-resolved binaries)
- Use plutil -extract over grep for safe plist parsing
- Honor is_whitelisted "check_orphan_launch_agents"
- Zero delete; mirrors check_login_items reporting style

Extends the orphan-detection pattern from tw93#682 (SystemExtensions
and LaunchAgents in lib/uninstall/batch.sh) into the check side,
parallel to check_disk_smart. Surfaces for awareness only — actual
removal stays on the uninstall path.

Real-world audit on author's Mac across all plists:
- 1 true positive (com.logitech.manager.daemon — Logi Options
  uninstalled, helper plist orphaned)
- 1 true negative (com.lwouis.alt-tab-macos — binary present,
  correctly not flagged)
- Zero false positives across remaining plists

Tests: 5 new BATS cases in tests/check_system.bats covering empty
state, orphan detection, com.apple.* skip, valid Program ignored,
and whitelist honored. Hidden MOLE_LAUNCH_AGENT_DIRS env var
provides directory override for test isolation. All 9 tests in
the file pass.
@sebastianbreguel sebastianbreguel requested a review from tw93 as a code owner April 8, 2026 02:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant