# 8.75:1 hysteresis puts fan stop at 27°C

mac-tool-kit's 7.8°C hysteresis band splits 8.75:1, placing the fan stop at 27.0°C — a temperature inference or DSP sessions never return to mid-session.

Canonical page: https://makerportal.ai/blog/biquadia-github-1349261167
Author: Joshua Hrisko, Principal Engineer — MakerPortal
Published: 2026-08-29
Section: Correction / Metal & the Neural Engine · 6 min read
Tags: biquadia, metal-ane, ios-craft

---

The hysteresis band in mac-tool-kit's closed-loop controller is 7.8°C total but split 8.75:1 between the spin-down guard and the ramp-up threshold — not the symmetric anti-hunting window the README implies. At the documented palm rest target of 34°C, that asymmetry places the fan stop condition at a derived 27.0°C, a value any sustained inference or DSP session holds the chassis above indefinitely.

## Stated figures and their conditions

The README reports three monitoring profiles, two thermal thresholds, a cost figure, and a collection of AI session telemetry claims. Conditions are sparse throughout.

| Claim | Stated value | Conditions the README attaches |
|---|---|---|
| Real-time (1s) CPU overhead | ~2–4% | None: hardware, process count, container count unstated |
| Balanced (3s) CPU overhead | ~0.5–1% | None: same conditions unstated |
| Eco fan-only CPU overhead | <0.05% | Process scans and Docker CLI suspended; thermal loop retained |
| Fan ramp-up threshold | ≥ Target + 0.8°C | Closed-loop mode; active sensor unspecified |
| Fan spin-down threshold | < Target − 7.0°C | Closed-loop mode; active sensor unspecified |
| Palm Rest Balanced Cooling target | ≤ 34°C | Palm Rest & Battery sensor explicitly named |
| Manual RPM range | 1,200–6,200 RPM | SMC root helper required |
| Prompt Cache Read cost reduction | 90% | Parenthetical descriptor; source not attributed in README |

The README states compatibility with Apple Silicon and macOS SMC root helper protocol but does not specify which Apple Silicon generations expose a controllable fan via SMC.

## Analysis

**Hysteresis geometry and the 34°C case**

The README describes the control logic as an "industrial -7°C thermal hysteresis anti-hunting algorithm." Define $T$ as the user-selected target temperature. The README gives two explicit thresholds:

$$
\Delta H = (T + 0.8) - (T - 7.0) = 7.8\,°\text{C}
$$

The ratio of the spin-down guard to the ramp-up threshold:

$$
r = \frac{7.0}{0.8} = 8.75
$$

For the palm rest comfort scenario the README describes explicitly, with $T = 34\,°\text{C}$:

$$
T_{\text{off}} = 34 - 7.0 = 27.0\,°\text{C}
$$

A 27.0°C chassis surface under active compute is effectively idle — not a temperature a running system touches mid-session. The README correctly frames this asymmetry as preventing rapid start-stop cycling, and for short thermal spikes that framing holds: a brief compilation burst, a single LLM turn. For sustained workloads the chassis simply never returns to $T_{\text{off}}$ between tasks. The fan runs continuously, cycling suppression has no practical effect within the session, and the hysteresis governs only the delay before the single stop event at session end.

A symmetric 3.9°C guard on each side of target would preserve the same 7.8°C total separation while placing the stop condition at 30.1°C rather than 27.0°C — meaningfully more reachable during light pauses in a development session. "Anti-hunting" is technically accurate, but 8.75:1 exceeds what hunting suppression actually requires by a wide margin.

**CPU overhead and process-scan cost attribution**

The three overhead figures allow a bounded cost decomposition. Taking the midpoints of the stated ranges — 3% for Real-time, 0.75% for Balanced — and treating the <0.05% Eco ceiling as a proxy for the thermal-loop-only cost:

$$
\text{Process scan contribution at 3s} \approx 0.75\% - 0.05\% = 0.70\%
$$

$$
\text{Process scan contribution at 1s} \approx 3\% - 0.05\% = 2.95\%
$$

The cost ratio across the 3× interval change:

$$
\frac{2.95\%}{0.70\%} \approx 4.2\times
$$

A 3× interval extension yields roughly 4.2× CPU reduction in the process-scan component. That is mildly super-linear relative to the interval ratio, consistent with Docker CLI polling being a fork-exec path: per-invocation startup cost is amortized over fewer calls at 3s, producing a slightly larger-than-proportional saving. The thermal regulation loop itself contributes less than 0.05% across all three modes — less than one-fifteenth of the Balanced profile's total.

**The "90% savings" attribution**

The README states "Prompt Cache Read (90% savings)" as a parenthetical when listing token types, without identifying the figure's source. It matches Anthropic's published pricing discount for cache-read tokens. MacDashboard reads token counts from Claude Code's usage logs and applies a cost formula; the discount is the LLM provider's, not the tool's. The README's presentation conflates display of savings with generation of savings. An engineer estimating ROI from workflow changes versus from adopting MacDashboard needs that distinction explicit.

**Connection to measured local inference loads**

The README lists Ollama and local LLM monitoring as a first-class use case. Our [M3 Ultra decode benchmarks](/blog/local-decode-bench-2026-08-26) measured sustained throughput at 9.8–139 tok/s across several models on the same Apple Silicon class the README targets. Those sessions are precisely the workloads most likely to trigger palm rest fan mode and then hold the chassis above $T_{\text{off}} = 27.0\,°\text{C}$ for the session's duration. The Real-time monitoring overhead of ~2–4% lands on top of inference compute, but the README states no conditions — no hardware, no inference load, no concurrent process count — so those figures cannot be directly summed with our measurements without assuming the configurations match.

<figure class="my-8 rounded-2xl border border-border bg-card-bg p-6" data-quantity-figure="comparison">
  <div class="flex items-center justify-between text-xs font-mono uppercase tracking-widest text-primary-cta">
    <span>Reported by PeterTing/mac-tool-kit</span>
    <span>RPM<span class="ml-2 sm:hidden">· scroll →</span></span>
  </div>
  <div class="mt-4 overflow-x-auto">
  <svg class="w-full min-w-[600px]" viewBox="0 0 600 124" role="img" aria-label="Figure: values as PeterTing/mac-tool-kit reports them, drawn from quantities extracted and quote-verified for this post. Bars are proportional within their shared unit; condition cells are exact values and are not scaled against one another. The studio has not re-measured them." xmlns="http://www.w3.org/2000/svg">
    <rect width="600" height="124" rx="12" fill="var(--mp-canvas, #0d0f12)"/>
    <text x="20" y="40" fill="var(--mp-text, #fff)" font-size="13" font-family="monospace">maximum fan RPM</text>
    <rect x="268" y="24" width="292" height="22" rx="4" fill="#1e40af" opacity="0.85"/>
    <text x="550" y="40" fill="#fff" font-size="12" font-family="monospace" text-anchor="end">6,200 RPM</text>
    <text x="20" y="86" fill="var(--mp-text, #fff)" font-size="13" font-family="monospace">minimum fan RPM</text>
    <rect x="268" y="70" width="57" height="22" rx="4" fill="#1d4ed8" opacity="0.85"/>
    <text x="335" y="86" fill="var(--mp-text, #fff)" font-size="12" font-family="monospace">1,200 RPM</text>
  </svg>
  </div>
  <div class="mt-5 border-t border-border/70 pt-4">
    <div class="flex items-center justify-between gap-3">
      <p class="text-[0.65rem] font-mono uppercase tracking-widest text-muted-text">Conditions around the comparison</p>
      <span class="shrink-0 font-mono text-[0.6rem] uppercase tracking-wider text-muted-text sm:hidden">scroll →</span>
    </div>
    <div class="mt-3 overflow-x-auto">
    <dl class="grid min-w-[600px] grid-cols-4 gap-px overflow-hidden rounded-xl border border-border bg-border">
      <div class="min-w-0 bg-card-bg p-4">
        <dd class="font-mono text-lg font-semibold text-primary-text">~2-4% CPU</dd>
        <dt class="mt-1.5 text-xs leading-5 text-muted-text">Real-time profile CPU</dt>
      </div>
      <div class="min-w-0 bg-card-bg p-4">
        <dd class="font-mono text-lg font-semibold text-primary-text">~0.5-1% CPU</dd>
        <dt class="mt-1.5 text-xs leading-5 text-muted-text">Balanced profile CPU</dt>
      </div>
      <div class="min-w-0 bg-card-bg p-4">
        <dd class="font-mono text-lg font-semibold text-primary-text">&lt; 0.05% CPU</dd>
        <dt class="mt-1.5 text-xs leading-5 text-muted-text">Eco Fan-Only CPU</dt>
      </div>
      <div class="min-w-0 bg-card-bg p-4">
        <dd class="font-mono text-lg font-semibold text-primary-text">8</dd>
        <dt class="mt-1.5 text-xs leading-5 text-muted-text">dedicated thermal sensors</dt>
      </div>
    </dl>
    </div>
  </div>
  <figcaption class="mt-3 text-xs leading-5 text-muted-text">Figure: values as PeterTing/mac-tool-kit reports them, drawn from quantities extracted and quote-verified for this post. Bars are proportional within their shared unit; condition cells are exact values and are not scaled against one another. The studio has not re-measured them.</figcaption>
</figure>

## What cannot be concluded

The CPU overhead figures carry no hardware baseline, no stated process count, and no container count. The README does not state whether ~2–4% is single-core saturation or aggregate utilization across the CPU complex, and does not confirm the Real-time and Balanced measurements were taken on the same configuration. At the lower bounds of the stated ranges (2% Real-time, 0.5% Balanced), the process-scan ratio becomes 1.95%/0.45% ≈ 4.3×, close to the midpoint result directionally but not numerically equivalent. The qualitative conclusion — process scanning dominates over the thermal loop — holds across the full stated range. The exact multiplier does not.

## What this means for Biquadia

Biquadia runs real-time DSP and neural audio enhancement on Apple Silicon, sustaining elevated temperature across the SoC Package, GPU cluster, and ANE sensors throughout a session. Two direct implications follow.

First, MacDashboard's Real-time profile at ~2–4% CPU is background cost with no stated thread isolation from audio render threads. The README documents no scheduling class or P-core affinity for its monitoring timers. For audio work where buffer underruns are audible, mean CPU percentage matters less than whether monitoring callbacks land on the same cores as the audio graph. Balanced or Eco is the safer default during active Biquadia sessions.

Second, $T_{\text{off}} = 27.0\,°\text{C}$ means that once a combined Biquadia-plus-inference session triggers the fan, it runs for the session's duration. Thermally appropriate — not a defect — but it means the anti-hunting benefit the README advertises is active only at session boundaries. Engineers combining Biquadia with the local LLM pipelines that [Wax hybrid recall](/blog/biquadia-github-1138007869) and [Minna's on-device inference](/blog/notiary-hackernews-49362669) assume should verify that Eco mode — which retains thermal regulation at <0.05% CPU while suspending all process monitoring — is sufficient for their fan control requirements before adopting Real-time monitoring during production audio sessions.

---

*Method: this note was drafted by us.anthropic.claude-sonnet-4-6 from two sources — the published README of [PeterTing/mac-tool-kit](https://github.com/PeterTing/mac-tool-kit) and this studio's own published measurements, linked above. Before publication an automated gate re-checked every extracted claim against the source document (25 claim(s) and 14 quantity(ies) verified) and every claim-shaped number in the draft against that evidence (11 derived from it, 18 row(s) supplied from our own tables). The studio has not re-run PeterTing/mac-tool-kit's benchmarks; figures attributed to it are its own.*

## Questions this note answers

### Does the 7°C spin-down guard reduce fan cycling during local LLM inference?

For short spikes — a single compile or one LLM turn — yes: the guard prevents the fan from stopping immediately after the excursion. For sustained inference at the throughput rates in our [decode benchmarks](/blog/local-decode-bench-2026-08-26), the chassis does not return to 27.0°C between turns, so the fan runs continuously and the cycling suppression produces no practical effect mid-session.

### Is the "90% savings" something MacDashboard produces or something it reports?

The README does not identify the figure's origin, but it matches Anthropic's cache-read pricing discount. MacDashboard reads usage log data and computes cost from token counts; it does not negotiate or generate the discount. The distinction matters when evaluating whether adopting MacDashboard reduces cost or only increases cost visibility.

### What does a 10-test suite cover for a tool spanning this many subsystems?

The README states "10/10 tests" run via `make test`, with no description of what those tests exercise. A tool covering process tree traversal, Docker CLI integration, SMC fan writes, thermal sensor reads, and token cost parsing across multiple AI tools represents many independent failure surfaces. Ten tests is a count, not a coverage claim, and the README makes no coverage claim.

### Does fan control work on fanless Apple Silicon configurations?

The README states compatibility with "macOS SMC root helper protocol" and gives an RPM range of 1,200–6,200, implying at least one controllable fan is required. Fanless Apple Silicon configurations are not addressed. Thermal monitoring and process dashboard features may function regardless, but fan speed override requires a fan the SMC can address; the README does not distinguish these cases.
