Skip to content

feat(doctor): add mo doctor command for Mac health diagnostics#659

Closed
sebastianbreguel wants to merge 10 commits intotw93:mainfrom
sebastianbreguel:feat/mo-doctor
Closed

feat(doctor): add mo doctor command for Mac health diagnostics#659
sebastianbreguel wants to merge 10 commits intotw93:mainfrom
sebastianbreguel:feat/mo-doctor

Conversation

@sebastianbreguel
Copy link
Copy Markdown
Contributor

@sebastianbreguel sebastianbreguel commented Mar 30, 2026

Summary

mo doctor — a TUI-based Mac health diagnostic that scores your system across 7 categories (100 points total). Categories appear one-by-one with a spinner during scanning, then transition to an interactive view where you can expand each category for details.

What it checks

Storage (15 pts)

Check What it measures Pass Warn Fail
Free space Disk space available ≥20% free 10–20% <10%
Recoverable cache ~/Library/Caches + Logs size ≤2 GB 2–5 GB >5 GB
Purgeable space macOS purgeable storage Informational
node_modules Total size across directories <5 GB 5–10 GB >10 GB
iOS backups MobileSync backup size <5 GB ≥5 GB

Performance (20 pts)

Check What it measures Pass Warn Fail
RAM usage Wired + compressed memory ≤60% 60–80% >80%
Swap usage Active swap in use ≤0.5 GB 0.5–2 GB >2 GB
Uptime Days since last restart ≤7 days 7–14 days >14 days

Battery (15 pts) — skipped on desktops

Check What it measures Pass Warn Fail
Cycle count Battery charge cycles ≤500 500–900 >900
Health Capacity vs design capacity ≥90% 80–90% <80%

Security (15 pts)

Check What it measures Pass Warn Fail
FileVault Disk encryption Enabled Disabled
Firewall System firewall Enabled Disabled
SIP System Integrity Protection Full Partial Disabled
macOS version Current vs latest release Current 1 behind 2+ behind

Maintenance (15 pts)

Check What it measures Pass Warn Fail
Broken launch agents LaunchAgents with missing executables 0 1–3 >3
Unused apps (90+ days) Apps not opened in 90 days 0 1–5 >5
Heavy processes Non-system processes using >5% CPU or >500 MB 0 1–2 >2

Dev Environment (15 pts)

Check What it measures Pass Warn Fail
Version mismatches psql client/server, node/nvm conflicts 0 1 2+
Common tools git, node, python3, brew, docker, go, xcode-select All present ≤2 missing >2 missing
Xcode CLI tools Command Line Tools installed Installed Missing
IDE extensions Duplicate VS Code / Cursor extensions 0 1–2 3+

Mole (5 pts)

Check What it measures Pass Warn Fail
Version Installed vs latest GitHub release Up to date Outdated
Config Whitelist file validity Valid Errors
Permissions Binary executable, config writable OK Not writable

UX

  • Progressive scanning: categories appear one-by-one with a spinner, each revealed after a brief delay
  • Interactive results: navigate with ↑↓/jk, Enter to expand/collapse, Esc/q to quit
  • Scoring: color-coded progress bars per category + overall score
  • Tips: actionable suggestions generated from failing checks
  Mac Doctor  (3/7)

  ✓ Storage                          ████████████ 15/15
  ✓ Performance                      ██████████░░ 18/20
  ⚠ Battery                          ████████░░░░ 10/15
  \ Checking Security ...
  Mac Doctor                        Score: 91/100
  █████████████████████████████████░░░

  ▸ ▸ Storage ✓                      ████████████ 13/15
    ▸ Performance ✓                  ██████████░░ 18/20
    ▸ Battery ✓                      ████████████ 15/15
    ▸ Security ✓                     ████████████ 15/15
    ▸ Maintenance ⚠                  ████████░░░░ 10/15
    ▸ Dev Environment ✓              ████████████ 15/15
    ▸ Mole ✓                         ████████████ 5/5

  ↑↓ navigate  Enter expand  q quit
  ─────────────────────────────────────────
  Tips: Close heavy background processes to improve performance

Test plan

  • go build ./cmd/doctor/ succeeds (darwin + linux stub)
  • go test ./cmd/doctor/ — all tests pass
  • go vet ./cmd/doctor/ — clean
  • Progressive scanning shows categories one-by-one
  • Interactive view: expand/collapse, scroll, keyboard nav all work
  • Battery category skipped gracefully on desktop Macs

TUI dashboard (Bubble Tea) that scores system health across 6 categories:
- Storage (20pts): free space, recoverable cache, purgeable space
- Performance (20pts): RAM pressure (wired+compressed), swap, uptime
- Battery (20pts): cycle count, health percentage
- Security (20pts): FileVault, Firewall (Sequoia-compatible), SIP, macOS version
- Maintenance (15pts): broken launch agents, unused apps, heavy processes
- Mole (5pts): version check, config validation, permissions

Supports --json for scripted output and --sudo for admin-only checks.
Battery points auto-redistribute to other categories on desktop Macs.
6 test files covering all pure-logic functions:
- format_test.go: humanizeBytes, progressBar, statusIcon, categoryIcon
- scoring_test.go: calculateTotalScore, redistributeBatteryScore, generateTips
- json_test.go: statusString
- category_battery_test.go: parseIORegInt, checkBatteryCycles, checkBatteryHealth
- category_performance_test.go: parseVMStatValue
- category_storage_test.go: expandHome
- Storage 15, Performance 20, Battery 15, Security 15, Maintenance 15, Mole 5, Dev Environment 15
- Add hardwareProfile and cacheBreakdownItem types
- Rescale battery (8+7), security (4+4+4+3)
- Add new threshold constants for v2 checks
- Show all tips instead of only the first one
- Add TUI scroll support with viewport and auto-scroll
- Add Esc key to quit
- Dynamic macOS version check (no longer hardcoded to >= 15)
- Context cancellation on quit to stop in-flight goroutines
- Extract buildCategory helper to reduce boilerplate across 7 categories
- Parallelize checkUnusedApps mdls calls (10x faster)
- Expand system process exclusion list (8 daemons)
- Fix integer rounding in battery score redistribution
- Improve thermal throttling detection patterns
- Secure temp file creation in checkMolePermissions (0600 vs 0644)
- Add tests for maintenance, mole config, and buildCategory (49 total)
@sebastianbreguel sebastianbreguel requested a review from tw93 as a code owner March 30, 2026 01:42
CI runs on Linux where all doctor files have //go:build darwin.
Add a main_other.go stub that prints an unsupported message on
non-macOS platforms so `make build` succeeds.
- Use min/max builtins instead of if-else patterns (modernize)
- Use strings.SplitSeq for efficient iteration (modernize)
- Use WaitGroup.Go instead of Add+go+Done (modernize)
- Check f.Close() return value (errcheck)
- Remove unused diagCtx variable (unused)
Categories now appear one by one during scanning with a spinner,
then transition to an interactive collapsed view. Enter to expand
individual categories and see check details.
- Remove unused hasSudo flag and err field
- Use strings.SplitSeq for range loops (modernize)
- Use WaitGroup.Go in bench test (modernize)
- Use min() builtin for viewport bounds (modernize)
@tw93
Copy link
Copy Markdown
Owner

tw93 commented Mar 30, 2026

@sebastianbreguel Thanks for the work here. I spent some time comparing this against the current command surface, and I’m going to close this one for now.

The main issue is product scope rather than implementation quality. mo status already covers live system health, mo optimize already handles check-and-fix style maintenance, and mo clean already provides cleanup hints for adjacent cases. Adding a separate mo doctor command would create too much overlap and increase long-term maintenance cost.

There are a few ideas here that could make sense later in a much smaller form inside existing commands, but I do not want to merge a new standalone diagnostic surface in its current shape.

Thanks again for putting this together.

@tw93 tw93 closed this Mar 30, 2026
@sebastianbreguel
Copy link
Copy Markdown
Contributor Author

@tw93 Thanks for the thoughtful review — totally understand the concern about overlap and maintenance cost.

Looking at it more carefully, I agree mo doctor as a standalone command is too broad. But there are a few checks that don't live anywhere today and could fit naturally inside existing commands. Would any of these be interesting as small, focused PRs?

For mo status:

  • Battery cycle count / design capacity health scoring (status shows the raw numbers but never warns on thresholds)
  • macOS version currency check (flag outdated OS)
  • Uptime warning (suggest restart after X days)

For mo analyze:

  • node_modules total size across home (proactive flag, not just when you navigate there)
  • iOS backup size detection
  • Recoverable cache breakdown (Spotify, JetBrains, Xcode DerivedData, etc.)

New territory (no current home):

  • Security posture: FileVault / Firewall / SIP status
  • Broken launch agents (plists pointing to missing binaries)
  • Dev environment: missing tools, version mismatches (psql client vs server, nvm node), duplicate IDE extensions
  • Mole self-check: version vs latest release, config validation

Happy to pick whichever subset makes sense and submit them as small PRs into the existing commands. Or if none of these fit the product direction, no worries at all — appreciate the feedback either way!

@tw93
Copy link
Copy Markdown
Owner

tw93 commented Apr 1, 2026

@sebastianbreguel Thank you very much. It's okay. You can merge the necessary submissions into the ability first.

sebastianbreguel added a commit to sebastianbreguel/Mole that referenced this pull request Apr 1, 2026
Design for adding broken launch agents, dev tool presence, and version
mismatch checks to mo optimize/check flow. Based on tw93's feedback
from PR tw93#659 to integrate doctor features into existing commands.
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.

2 participants