Skip to content

Instantly share code, notes, and snippets.

@jacobw
Created August 1, 2026 07:41
Show Gist options
  • Select an option

  • Save jacobw/62efb0b2928040e7b01331bcd59c0397 to your computer and use it in GitHub Desktop.

Select an option

Save jacobw/62efb0b2928040e7b01331bcd59c0397 to your computer and use it in GitHub Desktop.
Silencing macOS PowerChime on Tahoe (26.x): why the old fix stopped working — a reverse-engineering write-up

Silencing macOS PowerChime on Tahoe (26.x): why the old fix stopped working

TL;DR — The widely-documented fix is wrong on current macOS. ChimeOnNoHardware is the real off-switch, and it must be set to true, not false. Setting both keys to false (what every guide from 2015–2022 says) is actually a play-the-chime configuration.

# The fix that works on macOS 26.x:
defaults write com.apple.PowerChime ChimeOnAllHardware -bool false
defaults write com.apple.PowerChime ChimeOnNoHardware  -bool true      # ← true, not false
killall PowerChime   # drop the idle instance; next charger event re-reads prefs
# The classic fix, for contrast — does NOT silence the chime anymore:
defaults write com.apple.PowerChime ChimeOnAllHardware -bool false
defaults write com.apple.PowerChime ChimeOnNoHardware  -bool false     # this KEEPS it on

PowerChime is spawn-on-demand: launchd launches a fresh process on each AC-attach power event, it decides whether to chime, then exits. The decision above runs on every spawn, including the brief DarkWake spawns that happen when a charger is attached with the lid closed — so this covers the "charging overnight, lid shut" case too.

If the preference route ever fails, the fallback is to stop launchd from spawning the process at all:

launchctl disable gui/$(id -u)/com.apple.powerchime   # note: launchd label is lowercase
launchctl bootout  gui/$(id -u)/com.apple.powerchime

Verifying it worked

The process logs its decision on every launch. Trigger a real charger attach (unplug → replug), then:

log show --last 2m --predicate 'process == "PowerChime"' --info \
  | grep -iE "disabled|PLAYING CHIME"
  • Silenced correctly → PowerChime disabled - ChimeOnNoHardware default
  • Still chiming → PLAYING CHIME SOUND

Prior art — it's half-documented, and half-wrong

The working command is not new; ChimeOnNoHardware -bool true appears in a handful of guides. What's missing everywhere is why it works and why the more popular alternative does not. The internet carries two contradictory one-liners, usually presented with equal confidence and no explanation:

Variant Command Works on current macOS?
A defaults write com.apple.PowerChime ChimeOnNoHardware -bool true ✅ hits the exit(0) path
B defaults write com.apple.PowerChime ChimeOnAllHardware -bool false ❌ this is the false/false = chimes cell

Variant A — the correct one — is documented in, e.g., a gist that is literally just that one line, MakeUseOf, and AppleToolBox.

Variant B — the widely-copied trap — is the "classic" advice, e.g. this gist disables with ChimeOnAllHardware -bool false. It is also what you end up with if you read that both keys control the chime and set both to false: per the truth table above, false/false plays. This is the likely source of the recurring "it worked, then the chime randomly came back" reports — the config was never actually in the silencing state to begin with.

The contribution here is not the command; it's the disassembled gate that shows which variant is correct, and that the popular ChimeOnAllHardware -bool false / both-false advice is a no-op for silencing.


The full reverse-engineering breakdown

Target

/System/Library/CoreServices/PowerChime.app/Contents/MacOS/PowerChime

Universal binary (x86_64 + arm64e), a small AppKit agent (LSUIElement). It links libSMC, SkyLight, BatteryUIKit, IOKit, AudioToolbox/CoreAudio, and carries private entitlements for playing audio during notification-wake, asserting on lid close, and DarkWake control — i.e. it is explicitly allowed to chime while the machine is technically asleep with the lid shut.

Step 1 — strings: the old keys are still there

strings -a PowerChime | grep -iE "Chime|hardware|com\.apple"

Both legacy keys are still present in the binary, alongside the log lines that reveal the control flow:

ChimeOnAllHardware
ChimeOnNoHardware
PowerChime enabled by ChimeOnAllHardware default
PowerChime: chime enabled by hardware: %hhd
PowerChime disabled - ChimeOnNoHardware default: %hhd

Notably, the string com.apple.PowerChime appears nowhere in the binary (only as the bundle identifier in Info.plist). There is no secret alternate preferences domain — the keys are read from the process's own NSUserDefaults, whose search list is the com.apple.PowerChime domain. So the domain everyone writes to was correct all along; only the value was wrong.

Step 2 — locating the gate

The preference symbols in use:

nm -u PowerChime | grep -iE "Preferences|UserDefaults"
# _CFPreferencesGetAppBooleanValue, _CFPreferencesCopyAppValue, ... (chimeAttach animation prefs)

There are two distinct preference groups:

  • com.apple.chimeAttach.* (lightDisplay, numIterations, iterationDelay) — read via CFPreferencesGetAppBooleanValue/GetAppIntegerValue in readChimeAttachPrefs. These control the visual display-flash animation, not whether sound plays. Easy to mistake for the gate; it isn't.
  • ChimeOnAllHardware / ChimeOnNoHardware — read via [[NSUserDefaults standardUserDefaults] boolForKey:…] inside main. This is the sound gate.

Cross-referencing the key strings back to their use sites lands both reads in one function (main, 0x100008678 in the arm64e slice).

Step 3 — the disassembly

Resolving the selector references confirms the two reads are boolForKey:@"ChimeOnAllHardware" and boolForKey:@"ChimeOnNoHardware" on [NSUserDefaults standardUserDefaults]. The control flow (annotated):

; allHW = [defaults boolForKey:@"ChimeOnAllHardware"]     -> w23
; noHW  = [defaults boolForKey:@"ChimeOnNoHardware"]      -> w21

tbz  w23, #0, Lelse          ; if (allHW == false) goto Lelse
    ; log "PowerChime enabled by ChimeOnAllHardware default"
    b    Lrun                 ; -> NSApplicationMain  (CHIME PLAYS)

Lelse:
    ; log "PowerChime: chime enabled by hardware: %hhd"
    cbnz w21, Ldisabled       ; if (noHW == true) goto Ldisabled
    ; fallthrough:
Lrun:
    ... b NSApplicationMain   ; (CHIME PLAYS)

Ldisabled:
    ; log "PowerChime disabled - ChimeOnNoHardware default: %hhd"
    xpc_set_event_stream_handler("com.apple.notifyd.matching", ...)
    exit(0)                   ; bails before ever playing  (NO CHIME)

Equivalent source:

BOOL allHW = [defaults boolForKey:@"ChimeOnAllHardware"];
BOOL noHW  = [defaults boolForKey:@"ChimeOnNoHardware"];

if (allHW) {
    NSApplicationMain(...);        // chimes
} else if (noHW) {
    exit(0);                       // does NOT chime
} else {
    NSApplicationMain(...);        // chimes
}

Step 4 — the truth table

ChimeOnAllHardware ChimeOnNoHardware Result
true (any) 🔊 chimes
false false 🔊 chimes ← the "documented fix"
false true 🔇 exits before chiming

The classic advice — set both to false — is the exact cell that keeps the chime on. That is why the documented fix appears to do nothing: the keys are written correctly, a fresh process spawns and re-reads them, and the gate still resolves to "play." The only preference combination that reaches the exit(0) path is ChimeOnNoHardware = true.

A note on trying to test by running the binary

You cannot validate this by launching the binary directly. It is a restricted platform binary, so a manual launch is killed by the kernel with a Launch Constraint Violation (SIGKILL, CODESIGNING namespace) before main executes — the gate never runs and nothing is logged. The only end-to-end test is a real charger-attach event via launchd, observed through the unified log (see "Verifying it worked" above). The static analysis, however, is unambiguous, and the false/false = chimes result it predicts exactly matches the observed real-world symptom.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment