macpm 0.24__tar.gz → 2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- macpm-2.1/CHANGELOG.md +79 -0
- macpm-2.1/MANIFEST.in +6 -0
- macpm-2.1/PKG-INFO +286 -0
- macpm-2.1/README.md +245 -0
- macpm-2.1/RELEASE.md +155 -0
- macpm-2.1/macpm/__init__.py +3 -0
- macpm-2.1/macpm/__main__.py +3 -0
- macpm-2.1/macpm/dump.py +21 -0
- macpm-2.1/macpm/ioreport.py +252 -0
- {macpm-0.24 → macpm-2.1}/macpm/macpm.py +425 -356
- macpm-2.1/macpm/processes.py +681 -0
- macpm-2.1/macpm/sampler.py +422 -0
- macpm-2.1/macpm/sensors.py +128 -0
- macpm-2.1/macpm/smc.py +309 -0
- macpm-2.1/macpm/soc.py +210 -0
- macpm-2.1/macpm.egg-info/PKG-INFO +286 -0
- macpm-2.1/macpm.egg-info/SOURCES.txt +36 -0
- {macpm-0.24 → macpm-2.1}/macpm.egg-info/entry_points.txt +1 -0
- macpm-2.1/macpm.egg-info/requires.txt +3 -0
- macpm-2.1/packaging/README.txt +69 -0
- macpm-2.1/packaging/build.sh +63 -0
- macpm-2.1/packaging/entry_tui.py +4 -0
- macpm-2.1/packaging/install.sh +26 -0
- macpm-2.1/packaging/macpm.command +4 -0
- macpm-2.1/pyproject.toml +3 -0
- macpm-2.1/setup.py +51 -0
- macpm-2.1/tests/test_calc_freq.py +32 -0
- macpm-2.1/tests/test_cli.py +38 -0
- macpm-2.1/tests/test_layout.py +81 -0
- macpm-2.1/tests/test_processes.py +157 -0
- macpm-2.1/tests/test_sampler.py +35 -0
- macpm-2.1/tests/test_sensors.py +89 -0
- macpm-0.24/PKG-INFO +0 -118
- macpm-0.24/README.md +0 -100
- macpm-0.24/macpm.egg-info/PKG-INFO +0 -118
- macpm-0.24/macpm.egg-info/SOURCES.txt +0 -12
- macpm-0.24/macpm.egg-info/requires.txt +0 -3
- macpm-0.24/setup.py +0 -39
- {macpm-0.24 → macpm-2.1}/LICENSE +0 -0
- {macpm-0.24 → macpm-2.1}/macpm.egg-info/dependency_links.txt +0 -0
- {macpm-0.24 → macpm-2.1}/macpm.egg-info/not-zip-safe +0 -0
- {macpm-0.24 → macpm-2.1}/macpm.egg-info/top_level.txt +0 -0
- {macpm-0.24 → macpm-2.1}/setup.cfg +0 -0
- {macpm-0.24/macpm → macpm-2.1/tests}/__init__.py +0 -0
macpm-2.1/CHANGELOG.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 2.1 — 2026-11-11
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- The power panel is titled `Power` instead of `CPU+GPU+ANE Power`, and every
|
|
8
|
+
panel title is clipped to its box so a long title never wraps the frame.
|
|
9
|
+
- The Temps & Fans panel now uses its spare rows for CPU/GPU peak temperatures
|
|
10
|
+
and fan limits instead of leaving them blank.
|
|
11
|
+
- Per-core gauges are labelled `E1…` / `P1…` instead of `Core-1` / `C-1`, so
|
|
12
|
+
narrow gauges keep the percentage readable.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Temps & Fans panel** in the default view — hottest CPU and GPU sensor in
|
|
17
|
+
°C and the current RPM of every fan, read from `AppleSMC` without root.
|
|
18
|
+
- **Process view** on key `3` — a macmon-style two-box layout: a
|
|
19
|
+
CPU/GPU/RAM summary box (with wired/active/inactive/free memory) and a
|
|
20
|
+
process table with PID, NAME, USER, CPU%, MEM and GPU% columns, sorted with
|
|
21
|
+
`s`, scrolled with `↑`/`↓` and paused with `Space`. The table refreshes
|
|
22
|
+
every 2 seconds to keep macpm's own CPU low. There is no power column.
|
|
23
|
+
|
|
24
|
+
### Removed
|
|
25
|
+
|
|
26
|
+
- The separate `macpm-sensors` command. The SMC reader is now part of the TUI
|
|
27
|
+
(`macpm.sensors.SensorReader`).
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Impossible power peaks (such as `peak: 6208.38W`) caused by coalesced or
|
|
32
|
+
reset Energy Model counters are now discarded instead of being recorded.
|
|
33
|
+
- When the unprivileged Energy Model counters never report, the power panel
|
|
34
|
+
shows `n/a` instead of a misleading `0.00W`; the total is withheld only when
|
|
35
|
+
both CPU and GPU are unreadable.
|
|
36
|
+
|
|
37
|
+
## 2.0 — 2026-11-10
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **Rootless by default**: macpm no longer runs `sudo`, `powermetrics` or any
|
|
42
|
+
privileged helper. Data is collected from IOReport, IOKit, `psutil`,
|
|
43
|
+
`sysctl`, `ioreg` and `pmset`.
|
|
44
|
+
- Reworked the sampler into `macpm.sampler`, with ctypes bindings in
|
|
45
|
+
`macpm.ioreport` and SoC/DVFS discovery in `macpm.soc`.
|
|
46
|
+
- The terminal layout, panel titles, charts, colours and key bindings remain
|
|
47
|
+
the same as macpm 0.x.
|
|
48
|
+
- Version bumped to 2.0.
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- `macpm-sensors` / `macpm.sensors` — read SMC temperatures and fan speeds
|
|
53
|
+
without root (read-only).
|
|
54
|
+
- `macpm-dump` / `macpm.dump` — print the rootless metrics as JSON for
|
|
55
|
+
debugging.
|
|
56
|
+
- Optional per-core view improvements and reset/peak handling retained from
|
|
57
|
+
0.24.
|
|
58
|
+
- `--version` flag.
|
|
59
|
+
- Compatibility notes for macOS 12–27, M1–M4 and partial M5/Ultra support.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- `--show_cores` now accepts a real boolean value and `--show_cores` alone.
|
|
64
|
+
- Zero-division guards for `--avg < --interval` and for chips without E cores.
|
|
65
|
+
- No child `powermetrics` process is left behind when the TUI exits.
|
|
66
|
+
- `ioreg` output is filtered at the source to avoid retaining tens of MB of
|
|
67
|
+
XML in the Python allocator.
|
|
68
|
+
- Only the required `Energy Model` channels are subscribed, reducing memory
|
|
69
|
+
and CPU usage.
|
|
70
|
+
|
|
71
|
+
### Removed
|
|
72
|
+
|
|
73
|
+
- `sudo echo` pre-authentication and the `sudo nice powermetrics` subprocess.
|
|
74
|
+
- The `macpm2` development package (merged into `macpm`).
|
|
75
|
+
|
|
76
|
+
## 0.24
|
|
77
|
+
|
|
78
|
+
- Last 0.x release: `sudo` + `powermetrics` based sampler, Python TUI with
|
|
79
|
+
CPU/GPU/ANE power, RAM, disk and network panels.
|
macpm-2.1/MANIFEST.in
ADDED
macpm-2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: macpm
|
|
3
|
+
Version: 2.1
|
|
4
|
+
Summary: Rootless performance monitoring CLI tool for Apple Silicon
|
|
5
|
+
Home-page: https://github.com/visualcjy/macpm
|
|
6
|
+
Author: Jinyu Chen
|
|
7
|
+
Author-email: visualcjy@mail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Source, https://github.com/visualcjy/macpm
|
|
10
|
+
Project-URL: Issues, https://github.com/visualcjy/macpm/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/visualcjy/macpm/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: macpm apple-silicon monitor performance ioReport psutil
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Operating System :: MacOS
|
|
20
|
+
Classifier: Environment :: Console
|
|
21
|
+
Classifier: Topic :: System :: Monitoring
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: dashing>=0.1
|
|
26
|
+
Requires-Dist: psutil>=5.9
|
|
27
|
+
Requires-Dist: humanize>=4.0
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
Dynamic: project-url
|
|
38
|
+
Dynamic: requires-dist
|
|
39
|
+
Dynamic: requires-python
|
|
40
|
+
Dynamic: summary
|
|
41
|
+
|
|
42
|
+
# macpm
|
|
43
|
+
|
|
44
|
+
**Rootless performance monitoring CLI for Apple Silicon.**<br>
|
|
45
|
+
macpm 2.1 reads the same hardware counters as `powermetrics`, but through
|
|
46
|
+
IOReport/IOKit/SMC — no `sudo`, no password, no privileged helper.
|
|
47
|
+
|
|
48
|
+
A Python-based `nvtop`-inspired terminal monitor for Apple Silicon Macs,
|
|
49
|
+
forked from [asitop](https://github.com/tlkh/asitop).
|
|
50
|
+
|
|
51
|
+
## Demo
|
|
52
|
+
|
|
53
|
+
Default view — CPU/GPU/ANE utilisation and power, memory, temperatures/fans,
|
|
54
|
+
disk I/O and network, updating once per second:
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
Same view in another colour theme (press ← / → to cycle through them):
|
|
59
|
+
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
Per-core view (`--show_cores`, or press `2` while running):
|
|
63
|
+
|
|
64
|
+

|
|
65
|
+
|
|
66
|
+
## Highlights
|
|
67
|
+
|
|
68
|
+
- **No sudo required.** `macpm` runs as a normal user process.
|
|
69
|
+
- CPU E/P core utilisation and frequency, plus an optional per-core view
|
|
70
|
+
- GPU utilisation and frequency
|
|
71
|
+
- CPU / GPU / ANE power, rolling average, peaks and throttle state
|
|
72
|
+
- RAM and swap usage
|
|
73
|
+
- CPU/GPU temperature and fan RPM panel (SMC, read-only, no root)
|
|
74
|
+
- Disk IOPS/throughput and network throughput
|
|
75
|
+
- Process view with per-process CPU, memory and GPU usage, sortable with `s`
|
|
76
|
+
- Familiar terminal layout, colours, charts and key bindings from macpm 0.x
|
|
77
|
+
|
|
78
|
+
## Install
|
|
79
|
+
|
|
80
|
+
Requirements: **Apple Silicon Mac**, **macOS 12+**, **Python 3.9+**.
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
python3 -m pip install --upgrade macpm
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then run:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
macpm
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
There is **no `sudo macpm`** since 2.0. Running it with `sudo` still works, but it
|
|
93
|
+
is unnecessary and no longer recommended.
|
|
94
|
+
|
|
95
|
+
Prefer a standalone binary with no Python installation? See
|
|
96
|
+
[Standalone binaries](#standalone-binaries).
|
|
97
|
+
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
macpm [--interval INTERVAL] [--color COLOR] [--avg AVG] [--show_cores [BOOL]] [--version]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Option | Meaning |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `--interval SECONDS` | Sampling and display interval (default `1`) |
|
|
107
|
+
| `--color 1-8` | Display colour (default `2`) |
|
|
108
|
+
| `--avg SECONDS` | Averaging window for power values (default `30`) |
|
|
109
|
+
| `--show_cores [BOOL]` | Start in the per-core view |
|
|
110
|
+
| `--version` | Print the version |
|
|
111
|
+
|
|
112
|
+
Keys:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
q / ESC quit
|
|
116
|
+
← / → change colour
|
|
117
|
+
1 / 2 / 3 default / per-core / process view
|
|
118
|
+
s cycle the process sort column (process view)
|
|
119
|
+
↑ / ↓ scroll the process list (process view)
|
|
120
|
+
Space pause / resume the process list (process view)
|
|
121
|
+
Ctrl+R reset peaks
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Colour themes
|
|
125
|
+
|
|
126
|
+
Pick one with `--color N`, or press ← / → while macpm is running. The default
|
|
127
|
+
is `2` (green).
|
|
128
|
+
|
|
129
|
+
| | |
|
|
130
|
+
|---|---|
|
|
131
|
+
| **1 — red**<br> | **2 — green (default)**<br> |
|
|
132
|
+
| **3 — yellow**<br> | **4 — blue**<br> |
|
|
133
|
+
| **5 — magenta**<br> | **6 — cyan**<br> |
|
|
134
|
+
| **7 — white**<br> | **8 — grey**<br> |
|
|
135
|
+
|
|
136
|
+
## Why no sudo?
|
|
137
|
+
|
|
138
|
+
macpm 0.x called `sudo powermetrics`. In 2.0 the sampler reads the underlying
|
|
139
|
+
counters directly. The data is not secret; the old `powermetrics` CLI simply
|
|
140
|
+
requires root and Apple's private entitlements.
|
|
141
|
+
|
|
142
|
+
| Metric | Source |
|
|
143
|
+
|---|---|
|
|
144
|
+
| CPU E/P load and frequency | IOReport `CPU Stats` performance states |
|
|
145
|
+
| Per-core load | IOReport `CPU Core Performance States` |
|
|
146
|
+
| GPU load and frequency | IOReport `GPU Stats` / `GPU Performance States` |
|
|
147
|
+
| CPU / GPU / ANE power | IOReport `Energy Model` |
|
|
148
|
+
| RAM / swap | `psutil` |
|
|
149
|
+
| Disk / network | `psutil` counters |
|
|
150
|
+
| Per-process CPU / memory | `psutil`, plus `/bin/ps` for other users |
|
|
151
|
+
| Per-process GPU | `IOAccelerator` user clients in the IORegistry |
|
|
152
|
+
| CPU/GPU temperature, fan RPM | `AppleSMC` via the IOKit user client |
|
|
153
|
+
| Thermal throttle | `pmset -g therm` |
|
|
154
|
+
| SoC name / core counts | `sysctl` |
|
|
155
|
+
| GPU core count | `ioreg` `gpu-core-count` |
|
|
156
|
+
|
|
157
|
+
The DVFS frequency tables are parsed from the `pmgr` IORegistry node;
|
|
158
|
+
M1–M3 store Hz there, M4+ store kHz.
|
|
159
|
+
|
|
160
|
+
## Temperatures and fans
|
|
161
|
+
|
|
162
|
+
The default view has a **Temps & Fans** box next to the memory gauge. It shows
|
|
163
|
+
the hottest CPU and GPU sensor in °C and the current RPM of every fan, for
|
|
164
|
+
example:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
┌ Temps & Fans ──────────────────────────┐
|
|
168
|
+
│ CPU 52.4°C GPU 43.1°C │
|
|
169
|
+
│ Fan 1 2318 rpm Fan 2 2502 rpm │
|
|
170
|
+
└────────────────────────────────────────┘
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The values come from `AppleSMC` through the IOKit user client (read-only, no
|
|
174
|
+
root). SMC key names differ between chip generations, so the CPU/GPU sensor
|
|
175
|
+
groups are selected per chip family and a missing key is simply shown as `--`.
|
|
176
|
+
Fan **control** requires root and is not implemented.
|
|
177
|
+
|
|
178
|
+
## Process view
|
|
179
|
+
|
|
180
|
+
Press `3` for a macmon-style two-box layout. The top box is titled with the
|
|
181
|
+
SoC and core counts (as in views 1/2) and keeps the top-style CPU (E/P
|
|
182
|
+
percentages and frequencies), GPU (%, MHz), RAM/swap and
|
|
183
|
+
wired/active/inactive/free memory summary. The second box is the
|
|
184
|
+
process table with `PID`, `NAME`, `USER`, `CPU%`, `MEM` and `GPU%`; there is no
|
|
185
|
+
power column. The list is sorted by CPU usage by default; press `s` to cycle
|
|
186
|
+
through CPU → MEM → GPU → PID → NAME → USER, and `↑` / `↓` to scroll. The
|
|
187
|
+
header shows the current sort column and direction. Press `Space` to pause the
|
|
188
|
+
list while you scroll through it; the footer changes to `Space resume` and the
|
|
189
|
+
summary keeps updating. The process table refreshes every 2 seconds (or
|
|
190
|
+
`--interval`, if larger) to keep macpm's own CPU usage low; the summary above
|
|
191
|
+
it refreshes every interval. macpm's own process is listed as `macpm`.
|
|
192
|
+
|
|
193
|
+
Per-process CPU and memory come from `psutil`, with `/bin/ps` for processes
|
|
194
|
+
owned by other users (so system processes such as WindowServer appear too).
|
|
195
|
+
GPU usage is the GPU time of the process' `IOAccelerator` user clients;
|
|
196
|
+
processes without a readable GPU client show `0.0`.
|
|
197
|
+
|
|
198
|
+
## Compatibility
|
|
199
|
+
|
|
200
|
+
Tested on macOS 27.2 with an M3 Max. Behaviour depends more on the chip
|
|
201
|
+
generation than on the macOS version:
|
|
202
|
+
|
|
203
|
+
| Environment | Status |
|
|
204
|
+
|---|---|
|
|
205
|
+
| macOS 12–15, M1–M4 | Works |
|
|
206
|
+
| macOS 26, M1–M4 | Likely works |
|
|
207
|
+
| macOS 26, M5 / M5 Pro / Max | Partial: new CPU tier/channel names (`MCPU`/`SCPU`) and `acc-clusters` DVFS data are not fully handled |
|
|
208
|
+
| macOS 15/26, M1/M2 Ultra | Needs verification: multi-die complex channels may be `ECPU0/1` |
|
|
209
|
+
| macOS 27 | Works on the tested M3 Max; some 27 builds restrict unprivileged `Energy Model` refreshes |
|
|
210
|
+
| Intel Macs | Not supported; the Apple-Silicon IOReport groups are absent |
|
|
211
|
+
|
|
212
|
+
## Standalone binaries
|
|
213
|
+
|
|
214
|
+
Standalone unsigned/ad-hoc arm64 binary (`macpm`) can be built with
|
|
215
|
+
`packaging/build.sh` and attached to a GitHub release. It bundles Python and
|
|
216
|
+
all dependencies, so the target Mac needs no Python installation.
|
|
217
|
+
|
|
218
|
+
On first launch from a browser download, macOS Gatekeeper may ask you to
|
|
219
|
+
right-click → Open, or you can remove the quarantine flag:
|
|
220
|
+
|
|
221
|
+
```sh
|
|
222
|
+
xattr -d com.apple.quarantine ./macpm ./macpm.command
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
See [packaging/README.txt](https://github.com/visualcjy/macpm/blob/main/packaging/README.txt) for details.
|
|
226
|
+
|
|
227
|
+
## Development
|
|
228
|
+
|
|
229
|
+
```sh
|
|
230
|
+
git clone https://github.com/visualcjy/macpm.git
|
|
231
|
+
cd macpm
|
|
232
|
+
python3 -m venv .venv
|
|
233
|
+
. .venv/bin/activate
|
|
234
|
+
python3 -m pip install -e .
|
|
235
|
+
python3 -m unittest discover -s tests -v
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Build source and wheel distributions:
|
|
239
|
+
|
|
240
|
+
```sh
|
|
241
|
+
python3 -m pip install build twine
|
|
242
|
+
python3 -m build
|
|
243
|
+
python3 -m twine check dist/*
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Build standalone arm64 binaries (build machine needs Python + PyInstaller +
|
|
247
|
+
runtime dependencies; the output has no Python dependency):
|
|
248
|
+
|
|
249
|
+
```sh
|
|
250
|
+
PYTHON=python3 packaging/build.sh
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Release steps are documented in [RELEASE.md](https://github.com/visualcjy/macpm/blob/main/RELEASE.md).
|
|
254
|
+
|
|
255
|
+
## Troubleshooting
|
|
256
|
+
|
|
257
|
+
- **`macpm: command not found`** — add your Python user-base `bin` directory to
|
|
258
|
+
`PATH`, or run `python3 -m macpm`.
|
|
259
|
+
- **Power readings freeze or show `n/a` on macOS 27** — some builds restrict
|
|
260
|
+
unprivileged `Energy Model` refreshes. CPU/GPU usage and frequency still
|
|
261
|
+
work; a counter that never reports is shown as `n/a` instead of `0.00W`.
|
|
262
|
+
Run `macpm-dump` to inspect the raw values.
|
|
263
|
+
- **M5/Ultra values look wrong** — CPU tier/channel mapping is not complete;
|
|
264
|
+
see the compatibility table.
|
|
265
|
+
- **The Temps & Fans box says `SMC unavailable`** — the AppleSMC user client
|
|
266
|
+
could not be opened on this macOS build; the rest of macpm still works.
|
|
267
|
+
- **A temperature shows `--`** — not every SMC key exists on every chip; the
|
|
268
|
+
reader only reports the keys that are present.
|
|
269
|
+
|
|
270
|
+
## Changelog
|
|
271
|
+
|
|
272
|
+
See [CHANGELOG.md](https://github.com/visualcjy/macpm/blob/main/CHANGELOG.md). The 2.0 release removes the dependency on
|
|
273
|
+
`sudo`, `powermetrics` and temporary files.
|
|
274
|
+
|
|
275
|
+
## Credits
|
|
276
|
+
|
|
277
|
+
- [asitop](https://github.com/tlkh/asitop) — original Python TUI this project
|
|
278
|
+
was forked from
|
|
279
|
+
- [macmon](https://github.com/vladkens/macmon) and
|
|
280
|
+
[Stats](https://github.com/exelban/stats) — IOReport/SMC reference
|
|
281
|
+
implementations
|
|
282
|
+
- The IOReport sample-delta and DVFS-table ideas follow those projects
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
MIT. See [LICENSE](https://github.com/visualcjy/macpm/blob/main/LICENSE).
|
macpm-2.1/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# macpm
|
|
2
|
+
|
|
3
|
+
**Rootless performance monitoring CLI for Apple Silicon.**<br>
|
|
4
|
+
macpm 2.1 reads the same hardware counters as `powermetrics`, but through
|
|
5
|
+
IOReport/IOKit/SMC — no `sudo`, no password, no privileged helper.
|
|
6
|
+
|
|
7
|
+
A Python-based `nvtop`-inspired terminal monitor for Apple Silicon Macs,
|
|
8
|
+
forked from [asitop](https://github.com/tlkh/asitop).
|
|
9
|
+
|
|
10
|
+
## Demo
|
|
11
|
+
|
|
12
|
+
Default view — CPU/GPU/ANE utilisation and power, memory, temperatures/fans,
|
|
13
|
+
disk I/O and network, updating once per second:
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
Same view in another colour theme (press ← / → to cycle through them):
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
Per-core view (`--show_cores`, or press `2` while running):
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
## Highlights
|
|
26
|
+
|
|
27
|
+
- **No sudo required.** `macpm` runs as a normal user process.
|
|
28
|
+
- CPU E/P core utilisation and frequency, plus an optional per-core view
|
|
29
|
+
- GPU utilisation and frequency
|
|
30
|
+
- CPU / GPU / ANE power, rolling average, peaks and throttle state
|
|
31
|
+
- RAM and swap usage
|
|
32
|
+
- CPU/GPU temperature and fan RPM panel (SMC, read-only, no root)
|
|
33
|
+
- Disk IOPS/throughput and network throughput
|
|
34
|
+
- Process view with per-process CPU, memory and GPU usage, sortable with `s`
|
|
35
|
+
- Familiar terminal layout, colours, charts and key bindings from macpm 0.x
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
Requirements: **Apple Silicon Mac**, **macOS 12+**, **Python 3.9+**.
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
python3 -m pip install --upgrade macpm
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then run:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
macpm
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
There is **no `sudo macpm`** since 2.0. Running it with `sudo` still works, but it
|
|
52
|
+
is unnecessary and no longer recommended.
|
|
53
|
+
|
|
54
|
+
Prefer a standalone binary with no Python installation? See
|
|
55
|
+
[Standalone binaries](#standalone-binaries).
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
macpm [--interval INTERVAL] [--color COLOR] [--avg AVG] [--show_cores [BOOL]] [--version]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| Option | Meaning |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `--interval SECONDS` | Sampling and display interval (default `1`) |
|
|
66
|
+
| `--color 1-8` | Display colour (default `2`) |
|
|
67
|
+
| `--avg SECONDS` | Averaging window for power values (default `30`) |
|
|
68
|
+
| `--show_cores [BOOL]` | Start in the per-core view |
|
|
69
|
+
| `--version` | Print the version |
|
|
70
|
+
|
|
71
|
+
Keys:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
q / ESC quit
|
|
75
|
+
← / → change colour
|
|
76
|
+
1 / 2 / 3 default / per-core / process view
|
|
77
|
+
s cycle the process sort column (process view)
|
|
78
|
+
↑ / ↓ scroll the process list (process view)
|
|
79
|
+
Space pause / resume the process list (process view)
|
|
80
|
+
Ctrl+R reset peaks
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Colour themes
|
|
84
|
+
|
|
85
|
+
Pick one with `--color N`, or press ← / → while macpm is running. The default
|
|
86
|
+
is `2` (green).
|
|
87
|
+
|
|
88
|
+
| | |
|
|
89
|
+
|---|---|
|
|
90
|
+
| **1 — red**<br> | **2 — green (default)**<br> |
|
|
91
|
+
| **3 — yellow**<br> | **4 — blue**<br> |
|
|
92
|
+
| **5 — magenta**<br> | **6 — cyan**<br> |
|
|
93
|
+
| **7 — white**<br> | **8 — grey**<br> |
|
|
94
|
+
|
|
95
|
+
## Why no sudo?
|
|
96
|
+
|
|
97
|
+
macpm 0.x called `sudo powermetrics`. In 2.0 the sampler reads the underlying
|
|
98
|
+
counters directly. The data is not secret; the old `powermetrics` CLI simply
|
|
99
|
+
requires root and Apple's private entitlements.
|
|
100
|
+
|
|
101
|
+
| Metric | Source |
|
|
102
|
+
|---|---|
|
|
103
|
+
| CPU E/P load and frequency | IOReport `CPU Stats` performance states |
|
|
104
|
+
| Per-core load | IOReport `CPU Core Performance States` |
|
|
105
|
+
| GPU load and frequency | IOReport `GPU Stats` / `GPU Performance States` |
|
|
106
|
+
| CPU / GPU / ANE power | IOReport `Energy Model` |
|
|
107
|
+
| RAM / swap | `psutil` |
|
|
108
|
+
| Disk / network | `psutil` counters |
|
|
109
|
+
| Per-process CPU / memory | `psutil`, plus `/bin/ps` for other users |
|
|
110
|
+
| Per-process GPU | `IOAccelerator` user clients in the IORegistry |
|
|
111
|
+
| CPU/GPU temperature, fan RPM | `AppleSMC` via the IOKit user client |
|
|
112
|
+
| Thermal throttle | `pmset -g therm` |
|
|
113
|
+
| SoC name / core counts | `sysctl` |
|
|
114
|
+
| GPU core count | `ioreg` `gpu-core-count` |
|
|
115
|
+
|
|
116
|
+
The DVFS frequency tables are parsed from the `pmgr` IORegistry node;
|
|
117
|
+
M1–M3 store Hz there, M4+ store kHz.
|
|
118
|
+
|
|
119
|
+
## Temperatures and fans
|
|
120
|
+
|
|
121
|
+
The default view has a **Temps & Fans** box next to the memory gauge. It shows
|
|
122
|
+
the hottest CPU and GPU sensor in °C and the current RPM of every fan, for
|
|
123
|
+
example:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
┌ Temps & Fans ──────────────────────────┐
|
|
127
|
+
│ CPU 52.4°C GPU 43.1°C │
|
|
128
|
+
│ Fan 1 2318 rpm Fan 2 2502 rpm │
|
|
129
|
+
└────────────────────────────────────────┘
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The values come from `AppleSMC` through the IOKit user client (read-only, no
|
|
133
|
+
root). SMC key names differ between chip generations, so the CPU/GPU sensor
|
|
134
|
+
groups are selected per chip family and a missing key is simply shown as `--`.
|
|
135
|
+
Fan **control** requires root and is not implemented.
|
|
136
|
+
|
|
137
|
+
## Process view
|
|
138
|
+
|
|
139
|
+
Press `3` for a macmon-style two-box layout. The top box is titled with the
|
|
140
|
+
SoC and core counts (as in views 1/2) and keeps the top-style CPU (E/P
|
|
141
|
+
percentages and frequencies), GPU (%, MHz), RAM/swap and
|
|
142
|
+
wired/active/inactive/free memory summary. The second box is the
|
|
143
|
+
process table with `PID`, `NAME`, `USER`, `CPU%`, `MEM` and `GPU%`; there is no
|
|
144
|
+
power column. The list is sorted by CPU usage by default; press `s` to cycle
|
|
145
|
+
through CPU → MEM → GPU → PID → NAME → USER, and `↑` / `↓` to scroll. The
|
|
146
|
+
header shows the current sort column and direction. Press `Space` to pause the
|
|
147
|
+
list while you scroll through it; the footer changes to `Space resume` and the
|
|
148
|
+
summary keeps updating. The process table refreshes every 2 seconds (or
|
|
149
|
+
`--interval`, if larger) to keep macpm's own CPU usage low; the summary above
|
|
150
|
+
it refreshes every interval. macpm's own process is listed as `macpm`.
|
|
151
|
+
|
|
152
|
+
Per-process CPU and memory come from `psutil`, with `/bin/ps` for processes
|
|
153
|
+
owned by other users (so system processes such as WindowServer appear too).
|
|
154
|
+
GPU usage is the GPU time of the process' `IOAccelerator` user clients;
|
|
155
|
+
processes without a readable GPU client show `0.0`.
|
|
156
|
+
|
|
157
|
+
## Compatibility
|
|
158
|
+
|
|
159
|
+
Tested on macOS 27.2 with an M3 Max. Behaviour depends more on the chip
|
|
160
|
+
generation than on the macOS version:
|
|
161
|
+
|
|
162
|
+
| Environment | Status |
|
|
163
|
+
|---|---|
|
|
164
|
+
| macOS 12–15, M1–M4 | Works |
|
|
165
|
+
| macOS 26, M1–M4 | Likely works |
|
|
166
|
+
| macOS 26, M5 / M5 Pro / Max | Partial: new CPU tier/channel names (`MCPU`/`SCPU`) and `acc-clusters` DVFS data are not fully handled |
|
|
167
|
+
| macOS 15/26, M1/M2 Ultra | Needs verification: multi-die complex channels may be `ECPU0/1` |
|
|
168
|
+
| macOS 27 | Works on the tested M3 Max; some 27 builds restrict unprivileged `Energy Model` refreshes |
|
|
169
|
+
| Intel Macs | Not supported; the Apple-Silicon IOReport groups are absent |
|
|
170
|
+
|
|
171
|
+
## Standalone binaries
|
|
172
|
+
|
|
173
|
+
Standalone unsigned/ad-hoc arm64 binary (`macpm`) can be built with
|
|
174
|
+
`packaging/build.sh` and attached to a GitHub release. It bundles Python and
|
|
175
|
+
all dependencies, so the target Mac needs no Python installation.
|
|
176
|
+
|
|
177
|
+
On first launch from a browser download, macOS Gatekeeper may ask you to
|
|
178
|
+
right-click → Open, or you can remove the quarantine flag:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
xattr -d com.apple.quarantine ./macpm ./macpm.command
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
See [packaging/README.txt](https://github.com/visualcjy/macpm/blob/main/packaging/README.txt) for details.
|
|
185
|
+
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
git clone https://github.com/visualcjy/macpm.git
|
|
190
|
+
cd macpm
|
|
191
|
+
python3 -m venv .venv
|
|
192
|
+
. .venv/bin/activate
|
|
193
|
+
python3 -m pip install -e .
|
|
194
|
+
python3 -m unittest discover -s tests -v
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Build source and wheel distributions:
|
|
198
|
+
|
|
199
|
+
```sh
|
|
200
|
+
python3 -m pip install build twine
|
|
201
|
+
python3 -m build
|
|
202
|
+
python3 -m twine check dist/*
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Build standalone arm64 binaries (build machine needs Python + PyInstaller +
|
|
206
|
+
runtime dependencies; the output has no Python dependency):
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
PYTHON=python3 packaging/build.sh
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Release steps are documented in [RELEASE.md](https://github.com/visualcjy/macpm/blob/main/RELEASE.md).
|
|
213
|
+
|
|
214
|
+
## Troubleshooting
|
|
215
|
+
|
|
216
|
+
- **`macpm: command not found`** — add your Python user-base `bin` directory to
|
|
217
|
+
`PATH`, or run `python3 -m macpm`.
|
|
218
|
+
- **Power readings freeze or show `n/a` on macOS 27** — some builds restrict
|
|
219
|
+
unprivileged `Energy Model` refreshes. CPU/GPU usage and frequency still
|
|
220
|
+
work; a counter that never reports is shown as `n/a` instead of `0.00W`.
|
|
221
|
+
Run `macpm-dump` to inspect the raw values.
|
|
222
|
+
- **M5/Ultra values look wrong** — CPU tier/channel mapping is not complete;
|
|
223
|
+
see the compatibility table.
|
|
224
|
+
- **The Temps & Fans box says `SMC unavailable`** — the AppleSMC user client
|
|
225
|
+
could not be opened on this macOS build; the rest of macpm still works.
|
|
226
|
+
- **A temperature shows `--`** — not every SMC key exists on every chip; the
|
|
227
|
+
reader only reports the keys that are present.
|
|
228
|
+
|
|
229
|
+
## Changelog
|
|
230
|
+
|
|
231
|
+
See [CHANGELOG.md](https://github.com/visualcjy/macpm/blob/main/CHANGELOG.md). The 2.0 release removes the dependency on
|
|
232
|
+
`sudo`, `powermetrics` and temporary files.
|
|
233
|
+
|
|
234
|
+
## Credits
|
|
235
|
+
|
|
236
|
+
- [asitop](https://github.com/tlkh/asitop) — original Python TUI this project
|
|
237
|
+
was forked from
|
|
238
|
+
- [macmon](https://github.com/vladkens/macmon) and
|
|
239
|
+
[Stats](https://github.com/exelban/stats) — IOReport/SMC reference
|
|
240
|
+
implementations
|
|
241
|
+
- The IOReport sample-delta and DVFS-table ideas follow those projects
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT. See [LICENSE](https://github.com/visualcjy/macpm/blob/main/LICENSE).
|