Scripting

Diagnose and doctor

--diagnose#

One line that says what the Mac is doing, the evidence for it, and what was checked. This one is from the M5 Pro while it ran plottypus’s own test suite (the busy process is a cargo test binary):

text
$ plottypus --diagnose
Busy: plottypus_ui-807fb56e02002983 using 7.7 cores
  - cpu active: 100%
  - top process: plottypus_ui-807fb56e02002983 (pid 478) at 7.7 cores
checked:
  cpu      100% active, top plottypus_ui-807fb56e02002983 at 7.7 cores
  memory   18.3G of 24.0G used, 719M swapped, pressure nominal
  thermal  nominal, cpu 86 °C

On a quiet Mac:

text
$ plottypus --demo --diagnose
All normal
checked:
  cpu      10% active, top WindowServer at 0.1 cores
  memory   12.8G of 24.0G used, 820M swapped, pressure nominal
  thermal  nominal, cpu 43 °C

Like --json, it waits one interval to measure rates, and for the slow collectors to report, before it answers. It exits 0 whatever the verdict, so read the first line, or use plottypus --json | jq -r .verdict.kind for a machine-readable kind.

The verdict#

The same verdict sits in the footer of the dashboard (click a Busy: verdict to select that process). The first rule that matches wins:

Order Kind Headline When
1 throttling Throttling: thermal pressure is serious macOS thermal pressure is serious or critical
2 memory_tight Memory tight: 2.1G swapped or Memory tight: pressure warn memory pressure is warn or critical, or swap is growing by 1 MiB/s or more
3 busy Busy: Safari using 3.1 cores or Busy: CPU at 90% one process uses 1.5 cores or more, or the whole CPU is 75% or more active
4 normal All normal none of the above

The kind battery_drain exists in the JSON schema, but 1.0.0 never produces it.

In the dashboard, a new kind of verdict has to hold for 5 seconds before it replaces the one shown, so a one-tick spike never flips the footer.

“Cores” in a headline is per-core CPU divided by 100: Busy: … using 7.7 cores means that process was using about 7.7 cores’ worth of CPU time.

doctor#

plottypus doctor prints what this Mac exposes: the model and chip, how many SMC keys of each kind, every HID temperature service, how many processes are readable without root, which collectors are working, and what plottypus itself costs. It samples for a couple of seconds and exits. Paste it into bug reports, especially from a chip we have not seen.

From the M5 Pro development machine, trimmed, captured while it was running a test suite at 100% CPU (which is why self-cost reads high):

text
plottypus 1.0.0

[machine]
model        Mac17,8
chip         Apple M5 Pro
macos        27.0 (26A428)
chip table   curated
cores        0E + 12P + 6S, 20 GPU cores, 24 GB

[smc]
keys         3626 (285 temperature, 51 fan, 77 power)
types        flt:2091 hex_:311 ui16:268 ui8:260 ui32:246 si32:138 …

[hid temperature services]
   1  NAND CH0 temp
   3  PMU tdie1

   6  gas gauge battery

[processes]
readable     608 of 904 (296 need root)

[collectors]
cpu          Ok
memory       Ok
gpu          Ok
network      Ok
disk         Ok
processes    Ok
sensors      Ok
fans         Ok
thermal      Ok
battery      Ok

[self-cost]
cpu          2.19% over 8 ticks at 250 ms (mean tick 1.3 ms)

What to look at:

  • chip table is curated when plottypus has a temperature-sensor table for this model or chip, and none (prefix fallback) when it is guessing zones from SMC key name prefixes.
  • [smc] is the size of this Mac’s SMC key list. A fanless Air has no fans to count; that is expected.
  • [processes] is the count behind the rows in the process table: processes the kernel will not describe to a normal user. See Processes.
  • [collectors] shows which readings work on this Mac. A collector for hardware the Mac does not have shows as absent rather than failed.
  • [self-cost] is measured on the spot at the fastest interval, 250 ms, while doctor runs. The dashboard at its 500 ms default costs less, and draws nothing while idle.

doctor cannot be combined with --demo: it describes real hardware only.

Doctor output contains your Mac’s model, macOS build and process counts; it contains no process names, user names or serial numbers. Read it before you paste it anywhere.