macmon

vladkensMIT活跃维护

面向 Apple Silicon Mac 的实时系统监控工具,无需 sudo 即可查看 CPU、GPU 等硬件指标,提供 TUI 界面、JSON/Prometheus 指标服务和 Rust 库。

🦀🌡️ Real-time system monitor for Apple Silicon Macs. No sudo. TUI, JSON/Prometheus metrics server, and Rust library.

v0.11.0发布于 2026-11-06 18:41 UTC2,104star +7 / 7 天101fork同步于 2026-11-10 17:47 UTC

怎么上手

由 README 提炼,执行前请确认
brew install macmon
硬件要求按 README 说明

仅支持 Apple Silicon Mac,README 在 macOS 14 及以上测试通过,旧版本可能可用;在 macOS 虚拟机中功耗与频率读数为 0、温度为 null、风扇为空。README 未说明显存或 CPU 运行要求。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

免 sudo 读取 Apple Silicon 的 CPU/GPU/ANE 功耗与温度,带 TUI 和指标服务

面向 Apple Silicon Mac 的实时系统监控工具,无需 sudo 即可查看 CPU、GPU 等硬件指标,提供 TUI 界面、JSON/Prometheus 指标服务和 Rust 库。

核心能力

  • 无需 root 即可读取 powermetrics 同源实时数据
  • 提供 TUI 界面,显示历史曲线与进程级资源占用
  • pipe 子命令输出 JSON,便于脚本管道处理
  • serve 子命令暴露 /json 与 /metrics 供 Prometheus 抓取
  • 可作为 Rust 库集成,并内置 stress 压测子命令

容易踩的坑

macOS 27 起 CPU/ANE 功耗源需私有 entitlement,sudo 也无法恢复,部分配置下读数为 0 可能表示计数器不可用而非零功耗;serve 默认监听 9090 端口,需用 --host 127.0.0.1 才仅限本机;--install 安装 LaunchDaemon 需要 sudo,且与 --agent 的 LaunchAgent 同时只能存在一个。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.11.0
  1. v0.11.0最新正式版2026-11-06 · 2026-11-06 18:41 UTC

    Breaking Changes

    • macmon serve --install now installs a LaunchDaemon that starts at boot with nobody logged in, and needs sudo; it replaces your login agent if you have one. --install --agent installs the login agent as before, and --uninstall removes whichever is there (#121)
    • macmon serve now exits when it can't listen on its port, instead of running with no server (#121)
    • Spaces in the process filter now combine words: google chrome means both words, not that exact text (#122)
    • Added pressure_level and pressure_percent to MemMetrics in the Rust library, so code that builds this struct or matches it exhaustively needs updating (#120)

    Features

    • Added memory pressure: the RAM box graph shows it as Activity Monitor does, in green, yellow or red by level, with memory.pressure_percent and memory.pressure_level in JSON and Prometheus (#120)
    • Added queries to the process filter: cpu:, gpu:, power:, mem: and time: with a number, user: and path: with text, and ! before any word; a word with a bad value shows in red (#122)
    • Added dir: to the process filter, to find processes by working directory (#123)
    • Added app: to the process filter, to find an app with all its processes, such as Safari with its tabs (#124)
    • Added pausing the process list with Space and turning a filter off and on with f (#108, by @ratniel)

    Fixes

    • Fixed ram_power reading 0 on M1 Macs (#119)
    • Fixed rare ram_power spikes of hundreds of watts on macOS 27 (#125)

    Full Changelog: https://github.com/vladkens/macmon/compare/v0.10.0...v0.11.0

  2. v0.10.02026-10-14 · 2026-10-14 21:11 UTC
    查看更新说明

    Breaking Changes

    • Added cpu_tiers to SocInfo and Metrics and vm to SocInfo in the Rust library, so code that builds these structs or matches them exhaustively needs updating; the ecpu_* and pcpu_* fields are deprecated in favor of cpu_tiers (#85, #100)

    Features

    • Added support for the three CPU tiers of M6 Macs, with per-tier CPU metrics in JSON (cpu_tiers) and Prometheus (macmon_cpu_tier_*) (#85)
    • Added an info overlay (i) with the working directory, open files and sockets of the selected process, grouped by type and filterable (#95, #97)
    • Added killing the selected process with k, with Terminate and Force kill (#89)
    • Added revealing the selected process or file in Finder with e and copying its path with c (#95, #98)
    • Added several terms to the process filter, ! to exclude matches, and a total row for each term (#86)
    • Added a sortable CPU time column (TIME) to the process list (#104, #105)
    • Added a total power box with fan speed to the power row (#94, by @NicholasClooney)
    • Added scrollbars to the process list, the info overlay and the help (#98, #104)
    • Added support for running in a macOS virtual machine, where unavailable power and frequency readings are hidden; the soc JSON object gains vm (#99, #100)

    Fixes

    • Fixed processes of the nobody user missing from the process list (#104)
    • Fixed the base M5 Efficiency cores being labeled P instead of E (#85)
    • Fixed CPU core counts in macmon debug on macOS 27 (#85)

    Improvements

    • Reduced the TUI's own CPU usage by about half with the process list shown (#103)
    • Made key hints easier to read in both light and dark terminal themes (#92)
    • Updated the Grafana dashboard to plot per-tier CPU metrics; it needs this version's exporter (#85)

    Full Changelog: https://github.com/vladkens/macmon/compare/v0.9.0...v0.10.0

  3. v0.9.02026-10-07 · 2026-10-07 20:25 UTC
    查看更新说明

    Features

    • Restored power readings on supported Macs running macOS 27 without requiring sudo
    • Redesigned the TUI and added a sortable, filterable process list with CPU, GPU, memory, and power usage
    • Added stress ane for Neural Engine load testing and included ANE workloads in stress all
    • Added stress all --pulse [SECONDS] to alternate all workloads between busy and idle periods
    • Added find-clpc to diagnose CPU, GPU, and ANE power counters, with optional comparison against Apple's powermetrics

    Fixes

    • Fixed CPU and GPU frequency detection on M6 Macs (#79, by @johntdavies)

    Breaking Changes

    • Changed cpu_temp_avg and gpu_temp_avg in TempMetrics from f32 to Option<f32>; unavailable temperatures now appear as null in JSON instead of 0.0. Unavailable temperature metrics are omitted from Prometheus output (#81, by @omar16100)

    Full Changelog: https://github.com/vladkens/macmon/compare/v0.8.2...v0.9.0

  4. devDev buildpre-release2026-10-07 · 2026-10-07 18:15 UTC
    查看更新说明

    Latest build of main at 01cd7b23e12f9c9c20c9620947cd6961a526a8ac (2026-11-09 19:35 UTC).

  5. v0.8.22026-08-04 · 2026-08-04 16:28 UTC
    查看更新说明

    Fixes

    • Fixed a regression that caused missing per-core CPU metrics on M3 Ultra systems (#55)

    Full Changelog: https://github.com/vladkens/macmon/compare/v0.8.1...v0.8.2

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    macmon – Mac Monitor

    macmon is a sudoless performance monitor for Apple Silicon Macs. It reads real-time CPU / GPU / ANE power usage, temperatures, and memory stats through a private macOS API — the same data powermetrics exposes — without requiring root access.

    🌟 Features

    • 🚫 Runs without sudo
    • ⚡ Real-time CPU / GPU / ANE power usage
    • 📊 CPU frequency-scaled and active ratios per cluster
    • 💾 RAM / Swap usage and memory pressure
    • 📈 Historical charts with average and max values
    • 🌡️ Average CPU / GPU temperature
    • 📋 Process list with per-process CPU, memory, power and GPU usage
    • 🎨 Follows your terminal's color scheme
    • 🪟 Can be displayed in a small window
    • 🦀 Written in Rust

    📥 Installation

    Install macmon using brew:

    brew install macmon
    

    Install using MacPorts:

    sudo port install macmon
    

    Install using Cargo:

    cargo install macmon
    

    Install using Nix:

    nix-env -i macmon
    

    Tested on macOS 14 and later; older versions may work too.

    🚀 Usage

    Usage: macmon [OPTIONS] [COMMAND]
    
    Commands:
      pipe    Output metrics in JSON format
      serve   Serve metrics over HTTP
      debug   Print debug information
      stress  Generate load for testing metrics
      help    Print this message or the help of the given subcommand(s)
    
    Options:
      -i, --interval <INTERVAL>  Update interval in milliseconds [default: 1000]
      -h, --help                 Print help
      -V, --version              Print version
    

    Interactive mode

    Run macmon without a subcommand to open the terminal UI: the metric boxes on top and the process list below. Press ? in the app to see the keys.

    Press / to filter the process list: commas separate alternatives, spaces combine words, ! negates a word. For example chrome, !helper, node mem:500m !user:root or app:safari, which shows the Safari app with its helpers. A plain word looks in the name or pid. Keys take a number, above it or below it with <: cpu:, gpu:, power:, mem: (k, m, g) and time: (s, m, h, d); or text: user:, path:, dir: (the working directory), cmd: (the command line, of your own processes) and app: (the name of the .app the process or its responsible process runs from); or an exact local TCP or UDP port, of your own processes: port:3000. Enter keeps the filter, Esc clears it.

    Press Space to pause the process list: rows keep their order while values update, new processes wait until you resume, and the files list of i stops updating. Press f to turn the filter off and on without losing its text.

    JSON output

    You can use the pipe subcommand to output metrics in JSON format, which makes it suitable for piping into other tools or scripts. For example:

    macmon pipe | jq
    

    This command runs macmon in "pipe" mode and sends the output to jq for pretty-printing.

    You can also specify the number of samples to collect using the -s or --samples parameter (default: 0, which runs indefinitely), and set the update interval in milliseconds using the -i or --interval parameter (default: 1000 ms). For example:

    macmon pipe -s 10 -i 500 | jq
    

    This will collect 10 samples with an update interval of 500 milliseconds.

    HTTP server

    You can use the serve subcommand to expose metrics over HTTP. This is useful for integrating with monitoring systems like Prometheus and Grafana.

    macmon serve                   # default port 9090, interval 1000ms
    macmon serve --host 127.0.0.1  # listen on localhost only
    macmon serve -p 8080           # custom port
    macmon serve -i 500            # sampling interval 500ms
    macmon serve &                 # run in background
    

    Two endpoints are available:

    EndpointFormatDescription
    GET /jsonJSONCurrent metrics snapshot (same format as pipe --soc-info)
    GET /metricsPrometheusMetrics in Prometheus text format
    launchd service

    To start macmon serve at boot, with nobody logged in, and keep it running:

    sudo macmon serve --install                   # install and start (default port 9090)
    sudo macmon serve --port 8080 --install       # with custom port
    sudo macmon serve --host 127.0.0.1 --install  # listen on localhost only
    sudo macmon serve --uninstall                 # stop and remove
    

    --install needs sudo: it creates a LaunchDaemon at /Library/LaunchDaemons/com.macmon.plist that restarts on crash. The daemon runs as the user who called sudo, not as root, and with FileVault on it starts after the disk is unlocked following a restart. If that user has the agent below, the daemon replaces it.

    To start at login instead, without sudo:

    macmon serve --install --agent  # install and start (takes --host and --port too)
    macmon serve --uninstall        # stop and remove
    

    This creates a LaunchAgent at ~/Library/LaunchAgents/com.macmon.plist. Only one macmon service at a time: it's refused while the daemon is installed.

    Prometheus and Grafana

    The /metrics endpoint exposes metrics in Prometheus format. See examples/grafana for a local demo stack with Prometheus and Grafana.

    # HELP macmon_cpu_temp_celsius Average CPU temperature in Celsius
    # TYPE macmon_cpu_temp_celsius gauge
    macmon_cpu_temp_celsius{chip="Apple M3 Pro"} 47.3
    
    # HELP macmon_cpu_power_watts CPU power consumption in Watts
    # TYPE macmon_cpu_power_watts gauge
    macmon_cpu_power_watts{chip="Apple M3 Pro"} 8.42
    
    # HELP macmon_fan_speed_rpm Fan speed in revolutions per minute
    # TYPE macmon_fan_speed_rpm gauge
    macmon_fan_speed_rpm{chip="Apple M3 Pro",fan="fan0"} 1234
    
    # HELP macmon_cpu_scaled_ratio Combined frequency-scaled CPU ratio (0–1), weighted by core count
    # TYPE macmon_cpu_scaled_ratio gauge
    macmon_cpu_scaled_ratio{chip="Apple M3 Pro"} 0.037
    
    # HELP macmon_cpu_active_ratio Combined CPU active residency ratio (not frequency-scaled, 0–1), weighted by core count
    # TYPE macmon_cpu_active_ratio gauge
    macmon_cpu_active_ratio{chip="Apple M3 Pro"} 0.092
    
    # HELP macmon_cpu_tier_freq_mhz CPU tier frequency in MHz
    # TYPE macmon_cpu_tier_freq_mhz gauge
    macmon_cpu_tier_freq_mhz{chip="Apple M3 Pro",tier="E"} 1100
    macmon_cpu_tier_freq_mhz{chip="Apple M3 Pro",tier="P"} 1800
    
    # HELP macmon_cpu_tier_scaled_ratio CPU tier frequency-scaled ratio (0–1)
    # TYPE macmon_cpu_tier_scaled_ratio gauge
    macmon_cpu_tier_scaled_ratio{chip="Apple M3 Pro",tier="E"} 0.083
    macmon_cpu_tier_scaled_ratio{chip="Apple M3 Pro",tier="P"} 0.015
    
    # HELP macmon_cpu_tier_active_ratio CPU tier active residency ratio (not frequency-scaled, 0–1)
    # TYPE macmon_cpu_tier_active_ratio gauge
    macmon_cpu_tier_active_ratio{chip="Apple M3 Pro",tier="E"} 0.18
    macmon_cpu_tier_active_ratio{chip="Apple M3 Pro",tier="P"} 0.04
    

    macmon_ecpu_* and macmon_pcpu_* are still exported for the lowest and the highest tier. In a macOS VM the power and frequency gauges are left out.

    Stress testing

    Use macmon stress to generate load while checking metric behavior:

    macmon stress
    macmon stress pulse --duration 30
    macmon stress cpu --duration 30
    macmon stress cpu --workers 8 --duration 30
    macmon stress gpu --duration 30
    macmon stress all --duration 30
    

    The default pulse mode generates a predictable cyclic CPU load with a fixed 50% duty cycle on half of the logical CPUs. The cpu and gpu modes continuously load only the selected processor, while all loads both. The cpu and all modes use all logical CPUs unless --workers is specified; --workers has no effect in gpu mode.

    📊 Metrics

    Power sources and macOS 27

    macOS 27 broke the CPU/ANE power source that macmon previously used without root. The IOReport Energy Model counters can remain visible but stop updating: refreshing them now requires the private com.apple.private.pmgr.nrg.reporting entitlement. Apple's signed powermetrics has this entitlement and can keep using the named channels. Running macmon with sudo does not grant the same access.

    The working rootless workaround we found is to read hidden energy reports from the AppleCLPC driver through IOReport. These reports use opaque IDs instead of discoverable CPU/GPU/ANE channel names, so macmon has to identify the counters and verify their units. This leaves macmon maintaining undocumented mappings for data that Apple's own tool can still read directly.

    Both the CLI and the Rust library use known CLPC counters automatically, and Sampler::new() retains legacy fallbacks for older systems. New chips or driver versions may need additional mappings. On an unsupported configuration, zero CPU/ANE readings can mean unavailable counters rather than zero consumption. See docs/clpc-discovery.md for details.

    Output format

    The pipe command and the HTTP /json endpoint return the same metrics. Network, disk, uptime and battery are data only: there, in Prometheus and in macmon debug, not in the TUI. In a macOS VM ("vm": true in the soc object of pipe --soc-info and /json) power and frequencies read 0, temperatures null and fans are empty:

    {
      "timestamp": "2025-02-24T20:38:15.427569+00:00",
      "temp": {
        "cpu_temp_avg": 43.73614, // Celsius, null when no sensor has a valid reading
        "gpu_temp_avg": 36.95167, // Celsius, null when no sensor has a valid reading
      },
      "memory": {
        "ram_total": 25769803776, // Bytes
        "ram_usage": 20985479168, // Bytes
        "swap_total": 4294967296, // Bytes
        "swap_usage": 2602434560, // Bytes
        "pressure_level": 0, // Kernel memory pressure level: 0 normal, 1 warning, 2 critical, null when unavailable
        "pressure_percent": 25, // Memory pressure as in Activity Monitor (0–100), null when unavailable
      },
      "fans": [
        { "name": "fan0", "rpm": 999, "max_rpm": 4900 },
        { "name": "fan1", "rpm": 1200, "max_rpm": 5200 },
      ],
      "cpu_scaled_ratio": 0.036854, // Combined frequency-scaled CPU ratio (weighted by core count, 0–1)
      "cpu_active_ratio": 0.092, // Combined active residency ratio (not frequency-scaled, weighted by core count, 0–1)
      "cpu_tiers": [ // CPU core types from the lowest to the highest: E, P on M1–M4; E, S on M5; P, S on M5 Pro/Max; E, P, S on M6; _ when the core type is unknown, e.g. the single tier of a macOS VM
        {
          "label": "E",
          "freq_mhz": 1100, // Tier frequency
          "scaled_ratio": 0.082656614, // Frequency-scaled ratio (0–1)
          "active_ratio": 0.18, // Active residency (not frequency-scaled, 0–1)
          "cores": [
            { "die_id": 0, "core_id": 0, "freq_mhz": 1600, "scaled_ratio": 0.14, "active_ratio": 0.24 },
            { "die_id": 0, "core_id": 1, "freq_mhz": 1700, "scaled_ratio": 0.12, "active_ratio": 0.2 },
          ],
        },
        {
          "label": "P",
          "freq_mhz": 1800,
          "scaled_ratio": 0.015181795,
          "active_ratio": 0.04,
          "cores": [
            { "die_id": 0, "core_id": 0, "freq_mhz": 2100, "scaled_ratio": 0.05, "active_ratio": 0.08 },
            { "die_id": 0, "core_id": 1, "freq_mhz": 2200, "scaled_ratio": 0.07, "active_ratio": 0.06 },
          ],
        },
      ],
      // Deprecated, use cpu_tiers: ecpu_* is the lowest tier, pcpu_* the highest
      "ecpu_freq_mhz": 1100,
      "ecpu_scaled_ratio": 0.082656614,
      "ecpu_active_ratio": 0.18,
      "pcpu_freq_mhz": 1800,
      "pcpu_scaled_ratio": 0.015181795,
      "pcpu_active_ratio": 0.04,
      "ecpu_cores": [/* cores of the first tier */],
      "pcpu_cores": [/* cores of the last tier */],
      "gpu_freq_mhz": 461, // GPU frequency
      "gpu_scaled_ratio": 0.021497859, // Frequency-scaled ratio (0–1)
      "gpu_active_ratio": 0.09, // GPU active residency ratio (not frequency-scaled, 0–1)
      "cpu_power": 0.20486385, // Watts
      "gpu_power": 0.017451683, // Watts
      "ane_power": 0.0, // Watts
      "all_power": 0.22231553, // Watts
      "sys_power": 5.876533, // Watts
      "ram_power": 0.11635789, // Watts
      "gpu_ram_power": 0.0009615385, // GPU SRAM power, Watts
      "net_in": 148210, // Bytes per second received by the Ethernet and Wi-Fi interfaces, null without one
      "net_out": 20544, // Bytes per second sent by the Ethernet and Wi-Fi interfaces, null without one
      "disk_read": 1048576, // Bytes per second read from the disks, without disk images, null when unavailable
      "disk_write": 262144, // Bytes per second written to the disks, without disk images, null when unavailable
      "uptime": 273600, // Seconds since boot, null when unavailable
      "battery_percent": 87, // Battery charge (0–100), null without a battery
      "battery_charging": true, // null without a battery
      "battery_plugged": true, // External power connected, charging or not, null without a battery
    }
    

    Active and scaled ratios

    active_ratio is the share of the sampling interval during which the processor was doing any work. scaled_ratio is the same measure adjusted for operating frequency, showing the share of the processor's maximum possible capacity that was used.

    For interval $T$, $t_i$ is the time spent doing work at frequency $f_i$, and $f_\text{max}$ is the hardware maximum frequency for the CPU cluster or GPU. The product $T f_\text{max}$ is the theoretical maximum frequency-time the processor could deliver at full load without thermal or power throttling:

    R_\text{active} = \frac{\sum_i t_i}{T}
    \qquad
    R_\text{scaled} = \frac{\sum_i t_i f_i}{T f_\text{max}}
    

    CPU ratios are calculated per core and averaged across the cluster. A core that did no work contributes zero; combined CPU ratios average all cores from all clusters:

    R_\text{cluster} = \frac{1}{N_\text{cores}}\sum_j R_j
    

    Examples:

    • Full interval at half the maximum frequency → active = 1.0, scaled = 0.5.
    • Half the interval at the maximum frequency → active = 0.5, scaled = 0.5.
    • One of ten cores working at maximum frequency → cluster active = scaled = 0.1.

    📚 Library usage

    macmon can be used as a Rust library to collect Apple Silicon metrics in your own applications.

    Add it to your project:

    cargo add macmon --no-default-features
    

    The default app feature enables the macmon executable and its terminal UI dependencies. Disable default features when using macmon only as a library.

    Run the demo example from this repository:

    cargo run --example demo
    

    Then use the Sampler to collect metrics:

    use macmon::Sampler;
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        let mut sampler = Sampler::new()?;
    
        // collect metrics over a 1000ms window
        let metrics = sampler.get_metrics(1000)?;
    
        println!("CPU power:  {:.2} W", metrics.cpu_power);
        println!("GPU power:  {:.2} W", metrics.gpu_power);
        match metrics.temp.cpu_temp_avg {
            Some(value) => println!("CPU temp:   {value:.1} °C"),
            None => println!("CPU temp:   N/A"),
        }
        println!("RAM usage:  {} / {} bytes", metrics.memory.ram_usage, metrics.memory.ram_total);
        for tier in &metrics.cpu_tiers {
            println!("{}-CPU:      {} MHz  {:.1}%", tier.label, tier.freq_mhz, tier.scaled_ratio * 100.0);
        }
    
        Ok(())
    }
    

    get_metrics(duration_ms) blocks the calling thread while collecting one IOReport delta over the complete interval. For a UI, server, or async application, create the sampler inside a dedicated worker thread and send the completed metrics back through a channel:

    use std::{sync::mpsc, thread};
    
    use macmon::Sampler;
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        let (tx, rx) = mpsc::channel();
    
        thread::spawn(move || {
            let mut sampler = Sampler::new().expect("failed to create sampler");
    
            while let Ok(metrics) = sampler.get_metrics(1000) {
                if tx.send(metrics).is_err() {
                    break;
                }
            }
        });
    
        // Use recv() in a consumer thread or try_recv() in a non-blocking event loop.
        let metrics = rx.recv()?;
        println!("CPU power: {:.2} W", metrics.cpu_power);
    
        Ok(())
    }
    

    Creating Sampler inside the worker keeps its low-level macOS handles on that thread. In an async runtime, use its blocking-thread facility rather than calling get_metrics directly from an executor worker.

    ⚖️ Compared to htop and btop

    htop and btop are good general monitors, and htop is lighter. On Apple Silicon, without sudo, macmon shows more:

    • Real CPU and memory of other users' processes, such as WindowServer and root services. The kernel refuses them to htop and btop, which show 0; macmon reads them through the system's ps.
    • CPU, ANE and total power, frequencies of each CPU cluster, and memory pressure.
    • Power and GPU use per process.
    • A process filter with queries (mem:>1g, app:safari), open files and sockets of a process.

    Compared with htop 3.5.3 and btop 1.4.8 on macOS 27.

    🔍 See also

    🤝 Contributing

    Pull requests are welcome, including ones made with agents: point yours at agents.md.

    When reporting an issue, mention the version from macmon -V, and for a wrong or missing metric add the output of macmon debug.

    📝 License

    Distributed under the MIT License.