Changelog
Follow updates made to eWiz.
- 0.18.6Oct 7, 2026
Updating eWiz now shows what's happening and comes back on its own
Updates run through Sparkle: "Check for Updates…" (and the Update banner) open a window that checks, shows what's new, downloads with a progress bar, installs, and relaunches the new version — instead of the app quietly quitting and sometimes not reappearing. Checks still happen on launch and daily. One more update goes the old way to get there: this release installs through the previous updater, and every one after it through Sparkle.
- 0.18.5Oct 7, 2026
No more Bluetooth permission prompt from the Automation tab
The tab's live state read your connected Bluetooth devices every few seconds, which made macOS ask for Bluetooth access on every update and relaunch eWiz when you allowed it. Bluetooth is now read only when a rule actually depends on it.
The AI-agent server no longer crashes when a session ends
Ending an agent session sent a signal that crashed
ewiz-mcpinstead of releasing its keep-awake. - 0.18.4Oct 7, 2026
The icon, the panel and the notifications now agree
They all read one shared account of what the battery is doing, so the menu bar can no longer show a full battery with a check mark while the panel says 49% and charging. The "charge complete" flash fires only when the battery actually reaches full or your limit after charging, never when "Don't charge" is switched on part-way, and it always ends after three seconds. "Charge limit reached" is only announced when the limit is actually reached.
- 0.18.3Oct 6, 2026
Updates install themselves
eWiz no longer stops at "won't replace itself automatically" and a browser download. Each release's download is now signed, and eWiz checks that signature before installing the update in place and relaunching. An update that doesn't match is refused, and falls back to the download as before.
This takes effect from this version on: the update to it still goes through the download once.
- 0.18.2Oct 6, 2026
AI Agents, in Settings
eWiz ships an MCP server that lets AI agents (Claude, Cursor and other MCP apps) keep the Mac awake through a long build, test run or download, on a timer that ends by itself. It now has a home in Settings › Automation › AI Agents:
- One switch to let agents use it at all, and a second for keeping the Mac running with the lid closed. Agents asking while it's off are told so, and where to turn it on.
- Connect adds eWiz to Claude Desktop or Cursor in one click, keeping everything else in their settings. Claude Code gets a ready-to-paste command, and any other MCP app a config block.
- Live status shows which agent is keeping the Mac awake, for what, and for how long.
- 0.18.1Oct 6, 2026
A new icon for eWiz
A lightning bolt that doubles as a wizard's hat, in the Dock, Finder, Settings › About and the license window. About and the license window now show the app's real icon instead of a separate battery drawing, so the two can't drift apart.
- 0.18.0Oct 6, 2026
Battlify is now eWiz
Always Active can now switch itself on and off instead of only being held by hand
Always Active hours (Settings → Schedule) hold the Mac awake on a weekly timetable — for example weekdays from 9 AM for 9 hours. While at least one window is enabled, the switch means "hold during these hours": inside a window the lid-closed hold applies, outside it the Mac sleeps normally, with no need to remember to turn it off. Windows may wrap past midnight, so an overnight window belongs to the day it starts on. With no windows set the switch behaves exactly as before.
Turn off automatically (Settings → Charging, under Always Active) sets a deadline — 30 minutes to 8 hours, or "don't turn off". The deadline lives in the root daemon's config, so it still fires while the Mac is asleep or eWiz isn't running, and it clears the switch rather than leaving an on toggle that no longer holds anything.
The Always Active section shows which hours are set and whether it is HOLDING or WAITING right now, and the clamshell display saver follows the same verdict — it no longer forces the internal display off outside a scheduled window.
Caffeine no longer holds the screen awake on battery
Caffeine held a
PreventUserIdleDisplaySleepassertion — the same onecaffeinate -dtakes — for as long as it was on, whatever the power source. Left on and unplugged, that kept the display lit on an idle Mac (and, because macOS won't system-sleep while the display is on, kept the whole machine up): several watts, or percents of charge per hour, from a feature meant to keep work running.On battery Caffeine now downgrades the hold to system-only — the same work keeps running, but the screen is allowed to sleep — and restores the full hold when you plug back in. The session itself never ends, and any timer keeps running; only the reach of the hold changes. The replacement assertion is taken before the old one is released, so there's no window for the display to sleep during the swap.
Two new options in Settings → Sleep & Power → Caffeine:
- End it when I unplug — stop the session outright on battery, for a Mac that should lose no charge at all while left alone.
- Keep the screen on when on battery — the old behaviour, for when the screen genuinely has to stay lit.
The card also shows what Caffeine is holding right now, and until when.
The charge limit stays on
A request that stalled the helper's control socket used to block every other one, and the health check then tore the socket down and dropped whatever the app had queued. Requests are now served in order with a short read bound, and the check asks a question the daemon answers without its lock. The app no longer pushes placeholder settings before its first answer from the helper (which could switch the limit off), and edits are merged with the helper's current config instead of overwriting it with a copy up to 30 seconds old.
No more surprise password prompt
One missed answer from the helper no longer reads as "not installed"; the app asks again and only reinstalls after two misses.
A menu-bar icon that tells the truth
A bold bolt while current flows, a pause mark while charging is held or paused, nothing on battery or when full, and a check when a charge finishes, in every icon style (Pixel gets pixel-art marks). The mark springs in when the state changes and drops away on unplug. The panel says "Draining to 80%" above the limit rather than "Holding at 80%".
Low-battery shake
The icon trembles at 20%, and every 20 seconds under 10%. Settings → General → Menu Bar, with a Preview button.
Steadier panel
Lid mode no longer inserts a row above the tiles, and the line under them always takes one line, so pressing a tile never moves the layout.
AI agents can keep the Mac awake
A bundled MCP server lets an agent hold the Mac awake for a long task, optionally with the lid closed, on a lease that ends on its own.
Cleaner sounds
Every theme now plays at matched loudness, without clicks, and the off-key cues resolve.
License and support
The license window opens centred, asks before removing a license, and links to support. Settings → About gains Contact Support, Report a Bug and Copy Diagnostics, each filled in with what support needs.
Pick the plug-in animation from the menu, not three windows deep in Settings
Quick Actions gains an Animation button: switch it on or off, choose the style, and play it on the spot to see what it looks like without unplugging anything.
Bring your own animation
A new Custom style plays a numbered image sequence from
~/Library/Application Support/eWiz/ChargeAnimation— export frames from Rive, Lottie or After Effects and drop them in; Settings has a button that creates and reveals the folder and tells you how many frames it found. Frames are read in filename order, capped at 120, cached until the folder changes, and scaled to fit while preserving aspect, so a square export isn't stretched across a 16:10 display. With no frames present it plays the dot grid rather than flashing an empty screen. No third-party runtime, no binary format to parse: an image sequence is the one export every motion tool agrees on.The charging animation runs at twice the frame rate
A six-step sweep at two frames a second reads as a slideshow however well it's eased; the tick is 250ms now, so a sweep takes about 1.5s instead of 3. It still only runs while plugged in with animation switched on, and stops the moment nothing needs it.
Two more shortcuts: rest / wake the Mac (⌃⌥⌘R) and cycle the menu-bar icon style (⌃⌥⌘I). The rest shortcut shows its banner before the screen goes dark — a confirmation nobody can see is not a confirmation.
Fans: monitoring, temperatures, and control where the hardware allows it
Settings › Sleep & Power now lists every fan the way a fan utility should — name (Left side / Right side, as the hardware's own tools name them), its minimum, current and maximum rpm with the live figure emphasised, and what is driving it — followed by a Temperatures card. Sensors are discovered by walking the SMC's own key table rather than a hardcoded list, because the keys differ per model and a fixed list is wrong on every Mac it wasn't written for.
Fan control is offered only where the SMC accepts it. Some Macs read every fan key and refuse every write — an M3 Pro on macOS 26 refuses all of them — which is not knowable in advance, so eWiz tries once, remembers the answer, and says plainly that the machine won't allow it rather than pretending. Where writes are accepted, Custom holds each fan at a percentage of its own min…max range (a percentage rather than an rpm figure, because two fans in one machine needn't share a range), 0% is each fan's minimum rather than off, control returns to macOS above a temperature guard, and the daemon restores auto when it stops.
Fans reading 0 rpm on a cool Apple silicon Mac is normal, and the UI says so: they stop entirely until there is heat to move.
Buying, licenses and support move to ewiz.app
Buy opens ewiz.app/buy, the license window links to ewiz.app/license for a lost key or a new Mac, Visit the Website and Donate go to ewiz.app, and Contact Support writes to hello@ewiz.app. Every license already sold keeps working, and keys issued for eWiz are accepted too.
Four more menu-bar battery styles, and a charging icon that actually shows charging
Upright, Ring, Meter and Dot join Rounded, Bars, Classic, Minimal and Pixel. Upright is a standing battery filling from the bottom; Ring is a circular gauge whose arc tracks the charge; Meter is a five-step signal-style scale; Dot is a circle filling like liquid, for a menu bar that should stay quiet. The five horizontal styles still share one drawing box so switching between them can't shift the menu-bar layout; the upright and round styles are narrower by nature, which is a choice made once rather than something that moves while you work. The picker is a grid now — nine tiles in one row would each be too narrow to tell apart.
While charging, the fill rises from your real level towards full and restarts, instead of the level disappearing behind a lone pulsing bolt. The bolt sits in a transparent halo knocked out of the fill, so it stays legible from a sliver to full rather than dissolving into it — and because the halo is alpha, it survives macOS's template tinting in both light and dark menu bars. With the animation toggle off the icon draws your true level with a steady bolt, so a static icon is never a lie. Ring gets a travelling leading segment; Meter sweeps its steps.
Menu-bar text options, a Power Adapter card, and CSV export for history
- Menu bar display is now a choice of Icon only / Percentage / Time remaining / Percentage & time instead of a percentage on-off switch. Time remaining shows time to full while charging and time to empty on battery, and falls back to the percentage whenever macOS has no estimate. Existing preferences migrate (percentage off → Icon only).
- Power Adapter card in Battery Details: adapter name, negotiated wattage, supply voltage/current, manufacturer, model, and serial. When the adapter advertises more power than the Mac negotiated, it says so — that gap is almost always the cable.
- Export history as CSV from the History window: samples, daily summary, or lid sessions, for the range currently on screen.
The menu panel, rebuilt to look like it belongs in the menu bar
320pt wide with 16pt margins, the geometry the system's own panels use. Rules stop at the text margin rather than cutting the panel into bands, row labels sit at the system size, and the surface is one flat opaque fill: the
NSVisualEffectViewit used to have sampled whatever window was behind it, so the same menu read as near-black over the desktop and as washed grey over an editor, and every fill inside it drifted with the background it was a percentage of.Three defects went with it. The save-mode picker is drawn here now instead of being an
NSSegmentedControl, which arrived as first responder wearing a focus ring no system panel draws and sized every segment to its own label. The panel's window is sized to its content, becauseMenuBarExtra(.window)grows its window with the content and never shrinks it back — the leftover strip was bare, see-through window above the panel. And the window's opaque square backing is cleared, so the rounded corners stop having dark right angles tucked behind them.Sounds you can choose
Five voicings of the same three cues: Warm, Glass (a bell's inharmonic partials, not an octave stack), Pluck, Blip and Tick, which is transients only for anyone who wants to be told without being sung to. The picker plays as you change it.
A long close now costs nothing, and a short one still opens instantly
Apple silicon has no
standbydelay:hibernatemodeis either 3 (memory powered, instant lid, ~0.1%/h) or 25 (memory down, nothing to lose, 15–30s to come back). So the delay is implemented instead of configured — on the way into a closed-lid sleep on battery the daemon books its own wake, and if the Mac is still shut when that wake lands, memory goes off and it re-sleeps into hibernation. Tunable under Sealed Sleep, 20 minutes by default.A Lid tile in the quick actions, in place of Sleep: one press holds caffeine, Always Active and the battery permission together, which is the set anyone working with the lid shut turns on by hand. Sleep is still on its shortcut.
Fixed: "prevent idle sleep" was ANDed with the charge limit being on, so Extreme Performance — which asks for no idle sleep and deliberately turns the limit off — could never hold the assertion, and a Mac left on a long render idled out from under it.
The plug-in animation is off in this build and marked as coming in the next one. It plays over whatever you're doing, so it ships when it's right.
Animations were silently doing nothing if Reduce Motion was on
Every animation in the app — the charging icon, the charge-complete flash, the plug-in overlay — was gated behind macOS's Reduce Motion, so on a Mac with it enabled, turning "animate the charging icon" on had no visible effect whatsoever. Reduce Motion is still respected by default, but Settings → Sleep & Power now offers Animate anyway, shown only when Reduce Motion is actually on, and every animation reads the same resolved answer instead of each one checking for itself.
The animations were also linear, and linear reads as mechanical
Nothing physical moves at constant velocity. Progress now runs through real easing curves (
cubic-bezier(0.23, 1, 0.32, 1)and friends, solved the same way a browser solvescubic-bezier()), and the timings came down to where a state change belongs:- The charging fill sweeps in 6 steps rather than 8, front-loaded by the ease-out, so it surges and settles instead of crawling. The menu-bar tick can't safely go faster — each one relayouts the status item — so a shorter cycle is what buys the speed.
- Connect and disconnect morph in ~220ms (was 630ms and linear), which puts them in the same band as a dropdown. Ease-out, never ease-in: withholding motion at the start is what makes a short animation still feel slow.
- The overlay's dot wave has a narrow front (0.3 of the cycle, was 0.6) — at the old width most of the screen lit at once and it read as "dots everywhere" rather than a ripple crossing it.
The menu-bar glyph now reacts to power changes
Plug in and the bolt grows out of a flat spark; unplug and it collapses back into one, both by real shape interpolation.
Six more shortcuts: brightness up and down (⌃⌥⌘] and ⌃⌥⌘[), battery saver (⌃⌥⌘E), don't-charge (⌃⌥⌘H), and Wi-Fi and Bluetooth toggles — the last two ship deliberately unbound, since cutting Wi-Fi by a mistyped chord is not a surprise worth shipping.
Don't charge while plugged in
A switch that runs the Mac off the adapter and leaves the battery exactly where it is — no charging, whatever the level and whatever the limit says. It sits above the limit, schedules and ready-by top-ups deliberately: it's the switch you reach for when the battery should be left alone, and being second-guessed by another setting would defeat it. Only an explicit pause overrides it. On Macs with a MagSafe light, the light holds amber while it's on, so the state is visible without opening anything. Available in the menu, in Settings → Charging, and on ⌃⌥⌘H.
Plug-in feedback (experimental)
Two opt-in bits of feedback for the moment the adapter connects:
- Trackpad taps — two on connect, one on unplug, three when the charge limit is reached. It needs a Force Touch trackpad, and does nothing with the lid shut (the trackpad is asleep with it); there's no API to detect the hardware, so Settings says so rather than pretending to gate it.
- A charging animation over the screen for about a second: Dot Grid (a grid of dots ripples out from the port, each dot jittering as the wave passes), Rings (rings push out with the charge level in the middle), or Glow (a soft light rising off the bottom edge). The window is click-through, sits on the screen the pointer is on, and is torn down afterwards rather than kept around. Duration is capped at 2 seconds — it covers the screen, so it has to be over before it becomes something to wait out — and Reduce Motion replaces the motion with the level fading in place.
Morphing glyphs
The charging bolt now breathes between a slim and a fat bolt, and the charge-complete flash grows that bolt into a checkmark, both via real shape interpolation (
PathMorph: outlines resampled by arc length, closed rings rotated into least-travel alignment) rather than cross-fading two glyphs over each other. Covered by eight unit tests.Removed fan control and Endurance mode
Fan control is gone. Apple silicon refuses SMC fan writes — it returns success and leaves the key reading what it was, which is why the feature spent three releases learning to detect its own failure. On the hardware it did work on, it was a fan-speed utility bolted to a battery app.
The one part that stays is the part that can't safely be deleted: forced fan mode lives in the SMC and outlives the build that set it, across quit, log-out and restart. The helper now hands every forced fan back to macOS once, at startup, and never touches them again. A Mac left pinned by an older build fixes itself the first time this version runs.
Endurance is gone too. It dimmed the screen, turned on Low Power Mode, trimmed background wake and switched Bluetooth off — overlapping Super Saver on three of four levers, and driven by a drain meter whose reading depended more on what you were doing than on whether the mode was on.
Existing configs load unchanged; the settings both features wrote are ignored and dropped on the next save.
Battlify is now eWiz
New name, same app: settings, license key, history and the charge limit all carry over by themselves.
On first launch eWiz copies Battlify's settings across, and its helper takes over from Battlify's, moving the config, charge history and limit ownership with it. A copy of Battlify that updates itself installs eWiz in place, and eWiz then renames its own bundle. Homebrew users move across with
brew upgrade. Licenses sold as Battlify keep working.macOS treats eWiz as a new app, so it asks once more for notifications and the helper, and Launch at Login needs switching on again.
Add a "Give your Mac a rest" reminder
When your Mac has been running for over a week, eWiz gently suggests an occasional restart — which clears out memory and helps it run cooler — with a one-tap Restart… (or Later to snooze). The wording sharpens when the battery is running warm. It shows as a dismissible banner in the menu and, if notifications are on, a notification. Toggle it under Settings › Notifications ("Suggest an occasional restart").
Rest the Mac without closing the lid
Closing the lid is the usual way to make a Mac stop spending power — screen and keyboard backlight out, the machine quiesced. This does the same thing with the lid open, and puts back exactly what it changed when you return.
- Rest Now in the menu's Quick Actions and in Settings → Sleep & Power.
- Automatically when you're away, after 5–120 minutes with no keyboard, mouse or trackpad activity anywhere in the session (not just in eWiz). It never rests while an external display is connected — that usually means someone is looking at something.
- Optionally Low Power Mode while resting, snapshotted first and restored on wake, so it puts back what you had rather than imposing a default.
- Optionally Wi-Fi and Bluetooth off, off by default: losing the network mid-download or mid-call costs more than the power it saves. Only radios eWiz switched off are switched back on.
- Optionally sleep outright after a further delay, for leaving it overnight lid-up.
Any input at all ends it. Fans are left alone and the Settings copy says why: Apple silicon refuses SMC fan writes, and the fans wind down by themselves once the Mac is genuinely idle — which is the thing resting it achieves.
Sealed Sleep — close the lid and the charge stops moving
A closed Mac isn't off. Memory stays powered for as long as the lid is shut, and macOS wakes the machine on a timer for maintenance, for the network, and to answer Find My. Each wake is seconds. Over a weekend they add up to a number nobody expects.
There is one lever that removes the trickle rather than trimming it: powering memory down and writing it to disk. Sealed Sleep pulls that lever (
hibernatemode 25,standby 1) and then switches off everything that would hold the Mac up before it can get there — Power Nap, wake-for-network, TCP keep-alive, terminal sessions — plus Wi-Fi and Bluetooth as the lid actually closes.What's new beyond the settings themselves:
- A checklist instead of a promise. Nine named causes of closed-lid drain, each shown as sealed or still costing power. Two aren't eWiz's call and say so: Find My can't reach a sealed Mac, and a keep-awake you turned on deliberately stays on until you release it.
- Verified writes.
pmsetexits 0 for keys a Mac silently ignores, so everything is read back and anything refused is named rather than quietly counted as success. - Measured, not projected. The charge is read at close and again at open, so the panel reports what the last closed-lid stretch actually cost, per hour and per night.
- Reversible. Every displaced setting is snapshotted on the way in and written back on the way out, including the two radio preferences the app owns.
- Held against everything that used to undo it. A save mode switch, or a Mac that drifted after a macOS update, no longer silently unseals it.
The cost is stated where the switch is, because it applies to every sleep and not just the long ones: opening the lid takes fifteen to thirty seconds while memory is read back from disk.
Replaces the Deep sleep picker and Super Save when lid closed — three controls aimed at one outcome, none of them sufficient alone. Anyone who had chosen Deep sleep keeps it: that setting migrates to Sealed Sleep on first launch.
Fixed: the charge limit could be crossed while the Mac slept, charging to full
Enforcement is a tick loop in the root daemon, and that loop is frozen for the whole time the Mac is asleep — so whatever the SMC was last told is what stands. Sleep while charging below the limit and macOS carries on charging, unsupervised, to 100%.
Cutting charging on the way into sleep was the protection, but it had two holes. It was gated behind the "Stop charging before sleep" option, which is off by default, so a limit set by itself wasn't protected at all. And the request came from the app, over the control socket, which means it only happened while the app was running — quit eWiz, log out, or have it crash, and the protection vanished with no sign that it had.
The daemon now registers for sleep and wake notifications itself, on its own thread and run loop, so the cut happens whether or not anything is running in user space. It applies whenever a charge limit is enforced, not only when the option is ticked: the limit exists to keep the battery off full, and there is no way to stop at it while frozen. Charge still creeps towards the limit across the maintenance wakes macOS takes anyway — the tick runs during those and re-enables charging while below the resume threshold — and enforcement is re-evaluated the moment the Mac powers back on instead of waiting out the tick interval. The app's own pre-sleep request stays, so older app builds keep working; both paths are idempotent.
Fixed: the app could hang on a helper that looked perfectly healthy
launchd reported the job running, the binary and plist were in place, the process was alive — and every request the app made got "connection refused", so the app blocked forever with nothing to show for it.
The cause was an install race one step further along than the installer guards for: two daemons overlap briefly, the second removes the first's socket and binds its own, then the second goes away. The survivor is still listening on a socket that no longer has a name. Every health signal says fine; nothing can reach it.
Socket, bind and listen failures are now fatal — a helper with no control channel is worse than none, because launchd keeps it and stops trying, whereas exiting gets it restarted with a clean bind. The enforcement loop also checks that the socket path still refers to the socket it bound, and exits if it doesn't, which is the only way that state is visible from inside the process. Startup logs the path it's serving, so diagnosing this is now one line of log.
The dot-grid charging animation read as a boomerang: three fronts launched diagonally out of the port, one after another, which looked like something swinging out and back rather than a battery charging.
It's a dot-matrix charge meter now, closer to what a Nothing phone shows. The whole matrix stays faintly lit for the duration — before, only the moving band was drawn, so there was no grid to move through, just a stripe crossing the screen, which made the motion the subject instead of the charge. Dots below your actual charge level are lit brighter, so the animation says how full the battery is, and the level appears in monospace in the middle. The highlight rises once, from the bottom edge to the fill line, and stops: charging goes up, and anything that repeats or reverses reads as a loading spinner.
Shortcuts added by an update never reached anyone who had already launched the app
Saved bindings were loaded exactly as stored, so every action introduced after a user's first launch arrived unbound — it appeared in Settings › Shortcuts with "Not set" beside it and nothing ever shipped it. Defaults are now applied to actions this install has never seen, tracked by id, so a shortcut you deliberately cleared stays cleared and nothing gets re-seeded on every launch. In practice that means don't-charge (⌃⌥⌘H), brightness (⌃⌥⌘] / ⌃⌥⌘[), battery saver (⌃⌥⌘E), rest/wake (⌃⌥⌘R) and cycle icon style (⌃⌥⌘I) turn up bound on the next launch, and a combination already assigned to something else is left alone.
Resting now ends within a couple of seconds of you touching the Mac
It was checked on the same 60-second timer used to notice you'd gone away, so the display woke on the keypress while Low Power Mode and the radios stayed held for up to a minute — the Mac felt throttled after you'd come back to it. While resting, the check runs every two seconds instead, with a four-second grace window at the start so the keystroke that began resting doesn't immediately end it.
Defensive: two actions sharing one shortcut are repaired on load
Assigning through the recorder moves a taken combination rather than duplicating it, so this shouldn't happen — but if a saved file ever holds the same chord twice, Carbon registers exactly one of them and the other silently never fires, with nothing in the UI to hint at it. The first action in the canonical order keeps the chord and the rest are cleared, because an action that plainly has no shortcut can be fixed in Settings while one that looks bound and does nothing cannot even be diagnosed.
Shortcuts without ⌃ or ⌥ are now flagged
A global ⌘D or ⇧⌘D is grabbed before every other app sees it, so binding one quietly breaks Duplicate, Send and whatever else that chord means in the app you're using. Settings › Shortcuts says so next to the binding rather than refusing it — it's a legitimate choice, just one worth making on purpose.
Shortcut banners now show the icon of the action that fired — a bolt for force discharge, a coffee cup for keep awake, a gauge for save mode — instead of the app icon, which looked identical whatever you pressed. The glyph comes from the same catalogue key each row shows in Settings › Shortcuts, so the two can't drift apart. Pro-gated actions show a lock, and a missing helper or unsupported hardware shows an alert. Messages without a glyph still fall back to the app icon, in the same tile, so nothing shifts.
Shortcut pills read as a keyboard shortcut again.
⌃⌥⌘Pwas set solid in a monospaced face at 12pt, which collapsed the modifiers into one dense mark; each glyph now gets real space, with a slightly wider gap before the key name. - 0.17.0Aug 3, 2026
Global keyboard shortcuts, with a full remapping UI in Settings › Shortcuts
- 15 bindable actions: toggle the charge limit, raise/lower it in 5% steps, pause/resume charging, cycle save mode, Low Power Mode, force discharge, Caffeine, Always Active, dim/restore the display, display off, sleep now, and open the Settings/Details/History windows.
- Remap anything: click a shortcut, type the new combination. Assigning a combination that's already taken moves it and tells you which action lost it. ⌫ removes a binding, ⎋ cancels, and Reset to Defaults restores the shipped set.
- Defaults on ⌃⌥⌘ (⌃⌥⌘C for Caffeine, ⌃⌥⌘L for Low Power Mode, ⌃⌥⌘B for the charge limit, …). Sleep, force discharge, display-off, and the Details/History windows ship unbound so nothing disruptive is one stray keystroke away.
- Needs no Accessibility permission. Shortcuts are claimed through
RegisterEventHotKey, so the window server delivers only the specific combinations Battlify registers — the app never sees anything else you type. - A brief on-screen HUD confirms what fired, since toggling something invisible like Low Power Mode is otherwise indistinguishable from a shortcut that isn't working. Combinations another app already owns are flagged as "in use" in Settings rather than failing silently, and the menu tooltips now show each action's shortcut.
Stop the two settings that let a closed Mac stay awake in a bag
"Super Save when lid closed" already cut the radios, Low Power Mode, Power Nap, wake-on-network and TCP keep-alive — and restored each one exactly as it was on wake. It missed the only two settings that decide whether the Mac sleeps at all:
- Wake when a nearby device is close (
proximitywake) — an iPhone or Watch nearby wakes the Mac. In a bag that isn't one wake, it's a wake every time your phone stirs, all night. - Stay awake for terminal sessions (
ttyskeepawake) — an open terminal or SSH session blocks sleep outright. Lid shut, in a bag, fully awake and warm.
Both are now switched off by Super Save on lid close, snapshotted first and put back verbatim on wake. Both also appear as their own rows in Sleep & Power › Wake while closed, so you can control them independently of lid close.
Turning radios off saves milliwatts; these two decide whether the machine sleeps in the first place. If your Mac has been coming out of your bag hot and empty, this is almost certainly why.
For the largest remaining win, set Sleep & Power › Deep — powering memory down (
hibernatemode 25) does more for a Mac left closed for hours than every radio toggle combined. - 0.16.0Jul 30, 2026
Deep sleep
New Deep sleep setting (Sleep & Power) for Macs that stay closed for days
macOS normally keeps memory powered while the Mac sleeps so it wakes the instant you open the lid, writing a disk image only as a safety net. Deep sleep powers memory down and restores it from disk instead, which saves the small trickle that keeping memory alive costs over a long sleep. The trade is the wake: opening the lid takes several seconds while memory is read back, instead of being instant — so it's off by default and stays off when you upgrade.
On Apple silicon
hibernatemodeis the only lever that exists for this; thestandbydelayknobs Intel Macs had aren't available, so there's nothing else to tune. Writing it needs root, so the root helper applies it — and reports back if pmset refuses.The menu-bar glyph no longer animates while charging unless you ask it to
The animation ticked twice a second, and every tick re-rendered the status item. A status-item relayout is expensive: measured on an M3 Pro, it cost about a tenth of a core continuously, for as long as the Mac was plugged in. Turning it off drops the app to 0% CPU at idle. That is not a trade a battery app should make on your behalf, so it is now a setting in General — off by default, with a static charging bolt instead. The brief flash when charging completes still runs; it lasts about three seconds rather than the whole charge.
The helper stops working while your Mac sleeps
It used to run its enforcement loop every 10 seconds regardless. With the lid shut on battery the only moment that loop can run is inside one of the maintenance wakes macOS schedules roughly hourly — and everything it did there (reading its config off disk, walking IOKit for the battery, probing the SMC) was pure cost, holding the chip awake in exactly the window that should end as fast as possible. Measured dark wakes ran 6–45 seconds, so a 10-second loop fired three or four times inside one.
There was also nothing for it to decide: the charge limit and the heat cap only act while current is flowing in. So it now drops to a 60-second loop once the lid is closed on battery, which leaves a typical maintenance wake seeing at most one pass. Measured cost after the change: 0.03% CPU.
Anything that genuinely has to react with the lid shut keeps the fast loop — Always Active's task gating, a discharge run, a schedule boundary, a ready-by top-up, a calibration, or a pause that has to expire on time.
- 0.15.0Jul 27, 2026
Automation rules: apply a charging or power setting while something is true of your Mac
A rule combines any of twelve conditions — external display connected, USB or Bluetooth device connected, an app running (or running and frontmost), battery charging or above a level, power adapter connected, a specific IP address or subnet, a Wi-Fi network, a VPN, headphones/other audio output in use, a drive or volume mounted, or CPU usage above a threshold. Match all or any of them, and invert any single condition.
While a rule holds it can switch save mode, set or lift the charge limit, hold charging, keep the Mac awake, turn on Low Power Mode, or dial charge power down. When it stops holding, the previous setting comes back — unless you changed that setting yourself in the meantime, in which case your choice stands.
The new Automation tab in Settings shows a live readout of every condition Battlify can see, so a rule can be filled in with the real name of the dock, drive, or network in front of you, and the menu lists any rule that's currently holding a setting.
Cut the menu-bar app's idle CPU by roughly 17× (0.73% → 0.04% on an idle Mac)
The status item re-lays out on every published change, so republishing values that hadn't actually moved was costing continuous SwiftUI layout work in the background. The battery poll was the main offender: the temperature sensor jitters by hundredths of a degree, so every poll looked like a change. It now rounds to the precision actually displayed and publishes only real changes, skips reading live wattage entirely when no window is showing it, and does two follow-up reads per power event instead of four. The lid/display poll and the automation rule engine got the same treatment.
Settings tabs no longer overflow the window
Each tab claimed a fixed 76pt minimum plus padding, so a sixth tab pushed the row past the width of the window — the gaps went uneven and the last tab was clipped by the window edge. Tabs now share the bar equally, with margins at both ends, and the stray focus ring on the selected tab is gone.
- 0.13.0Jul 22, 2026
Endurance battery-saver
New
- Endurance battery-saver mode (in Settings → Sleep & Power) — dims the screen, turns on Low Power Mode, and trims background wake & Bluetooth to cut drain (targets ~25%), with a live measured drain meter to prove the savings. Auto-activates on battery; restores everything when off. Apple Silicon + Intel, macOS 12–15.
- Keep-awake process picker — pick apps/processes from a list of what's running.
- Sleep when the task finishes — sleep the Mac automatically once a monitored task ends.
Fixes
- Charge limit now survives shutdown & restart — the battery no longer charges past your limit while the Mac is off but plugged in.
- Charge Power below 100% no longer stalls below the limit; heat cap no longer silently disabled on a failed temp read; legacy SMC partial-write overshoot fixed.
- Endurance no longer flips back on after you turn it off while on battery (a manual off sticks until you next plug in/unplug).
- 0.12.0Jul 18, 2026
New icons and rest reminders
Give the UI a premium refresh with HugeIcons
A lightweight HugeIcons renderer (real stroke icons from
@hugeicons/core-free-icons, drawn as SwiftUI shapes — no runtime dependency) now powers the menu popover and the Settings window (tab bar + About). Also shortened the "Display Off" Quick Action to "Off". - 0.11.0Jul 18, 2026
Caffeine mode
Add Keep Awake (Caffeine) mode — a one-tap "never off, never sleeps" toggle
A new tile in the menu's Quick Actions keeps the display from turning off and the Mac from idle-sleeping, the same thing
caffeinate -ddoes.- Works on battery and wall power (unlike the AC-gated "Always Active" keep-awake).
- Needs no root and no helper daemon — it's a user-space
PreventUserIdleDisplaySleeppower assertion held by the app, so it works even before the helper is installed. - Tap to hold indefinitely, or press-and-hold the tile for a timed session (30 min / 1 / 2 / 5 hours) that auto-releases.
- Closing the lid still sleeps the Mac, and the assertion is released the instant Battlify quits — so it can never leave the Mac stuck awake.
Also bootstraps the project's first automated tests: a
BattlifyKitTestssuite (swift-testing) covering the Caffeine state machine, timer expiry/cancellation, and a system-level integration test that asserts the real IOKit power assertion is registered and cleared — plus toggle benchmarks. Run with./scripts/test.sh; a new CI workflow runs them on every push/PR.Animated menu-bar battery icons
- New "Pixel" icon style: a chunky 8-bit battery with notched corners. While charging, its fill sweeps from the current level up to full, one column at a time — like a classic handheld.
- Every other style's charging bolt now gently pulses while charging.
- When charging completes — the battery reaches 100% or lands at your charge limit — the icon flashes green a few times (or blinks monochrome when icon coloring is off), then settles.
- Micro-details: animations respect the system Reduce Motion setting, never run while discharging (a battery saver shouldn't spend cycles on battery), and the driving timer only exists while an animation is actually visible.
Fix Always Active leaving the internal display and keyboard backlight on with the lid closed
Keeping the Mac awake with the lid shut skips macOS's normal clamshell display-off, and the previous one-shot display sleep didn't hold. Battlify now re-issues a forced display sleep while the lid is shut and Always Active is holding — so the panel and keyboard backlight go dark and stay dark — and it never runs when an external display is attached, so a docked monitor is untouched.
Relicense under the PolyForm Noncommercial License 1.0.0
You may use, modify, and contribute to Battlify freely for noncommercial purposes; selling it or using it commercially (paid products, hosted services, enterprise support) is not permitted. All commercial rights are reserved by the author.
Performance: cut needless background wakeups
Live-watts polling now runs only while the popover or Details window is open (instead of every 5 seconds for the app's whole life), the daemon caches its
pmsetreads longer so periodic status polls stop forking processes, and status refreshes only publish state that actually changed. Lower energy impact with no change in behaviour.Fix the helper installer failing intermittently on reinstall/auto-update
The install scripts unloaded the LaunchDaemon (
launchctl bootout) and immediately reloaded it (launchctl bootstrap).bootoutis asynchronous, so bootstrapping before the old job finished tearing down races and fails withBootstrap failed: 5: Input/output error— and because the scripts run underset -e, that aborted the install and made the app report "Install cancelled or failed." This bit the common path now that the app auto-reinstalls the helper whenever it's out of date.- Wait for the old daemon instance to fully unload before bootstrapping, then retry bootstrap while the label frees up (and treat an already-loaded service as success, kickstarting it onto the new binary).
launchctl enablethe service before bootstrap, so a service left disabled by a prior failed install can still load.- Strip the quarantine flag from the installed helper binary, so the (not-yet- notarized) daemon isn't killed by Gatekeeper right after install.
Applies to both the app-bundled installer and
scripts/install-helper.sh.Make the app relaunch reliably after an in-app update
The post-update relaunch fired a single
openand assumed it worked. It now re-registers the swapped bundle, waits briefly for Launch Services to settle, then relaunches withopen -nand verifies the process actually came up — retrying a few times (checking first, so it never spawns a duplicate) and falling back to a launch by bundle id. If the app still isn't visible it logs a warning instead of silently giving up. - 0.10.1Jul 14, 2026
Notification icon fix
Fix the missing app icon in notifications
macOS Notification Center resolves the app icon through a compiled asset catalog (
Assets.carreferenced byCFBundleIconName), which the bundle didn't include — so notification banners showed a blank placeholder even though Finder and the Dock looked fine. The build now compiles an asset catalog withactool(and only setsCFBundleIconNamewhen that catalog is actually present, so it never points at a missing target).scripts/make-icon.shalso emits the catalog source from the SVG master. - 0.10.0Jul 14, 2026
New app icon
A dark, premium "graphite" mark: a near-black squircle with a machined bevel and a brushed-metal battery whose three charge bars glow green. Ships as
AppIcon.icnsin the bundle (referenced viaCFBundleIconFile), with the vector master atbranding/battlify-icon.svgand ascripts/make-icon.shto regenerate the iconset.Fix save mode / charge settings resetting on their own
- Lid-close deep save ("Super save on lid close") no longer re-applies a whole save mode on wake. It now restores only what it actually changed — Low Power Mode and the sleep/wake toggles — so your custom charge limit and heat settings survive a lid close/open cycle, and the mode can no longer silently reset to Off when it couldn't be read at sleep.
- Switch mode by Wi-Fi network no longer re-applies the mode that's already active (on launch or reconnect), which previously overwrote custom charge-limit/heat tweaks made within that mode.
- 0.9.3Jul 5, 2026
Keep-awake on battery
Always Active: optional "Also keep awake on battery"
"Always Active" still defaults to AC-power-only (it releases when you unplug), but a new opt-in sub-toggle in Settings lets it keep the Mac awake with the lid closed on battery too. Off by default because a closed, unventilated Mac kept awake on battery drains fast and can run hot — the temperature guardrail still applies as a safety net, and the display/keyboard backlight still switch off to save power.
- 0.9.2Jul 5, 2026
Themes and a force-discharge fix
Fix force-discharge ("Discharge to limit" / recharge range) not draining the battery
Cutting the power adapter to run off the battery makes macOS report the power source as "Battery Power", so the daemon read itself as unplugged on the very next tick, restored the adapter, and oscillated the adapter on/off every ~10s — the battery barely drained and the charge indicators flickered.
- The daemon now gates discharge on physical adapter presence (the raw SMC
AC-Wkey, which stays true through a force-discharge, falling back to IOKit'sExternalConnected) instead of the providing-source flag. Discharge now runs continuously until it reaches the limit (or the cable is genuinely unplugged). - Same fix applied to the MagSafe status LED (no longer flips to "Auto" mid-discharge), the prevent-idle-sleep assertion (no longer drops and lets the Mac sleep before draining finishes), and keep-awake.
- Bumps the helper build version so an already-installed daemon auto-updates.
- The daemon now gates discharge on physical adapter presence (the raw SMC
- 0.9.0Jul 4, 2026
Charge history
- History view with charging and battery sessions
- Daily summary and high-charge time tracking
- 0.8.4Jul 1, 2026
Build the released binary on macOS 26 (was macOS 15)
A binary built against the macOS 15 SDK silently failed to launch (exited immediately) on macOS 26 due to a Swift concurrency runtime mismatch — even though the same source runs fine when built on macOS 26. No code change; this rebuilds the release on the matching SDK.
- 0.8.3Jul 1, 2026
Fixed another launch/enable crash
Two more
MainActor.assumeIsolatedcalls (the lid sleep/wake callbacks) could trap on macOS 26 when the callback wasn't on the main actor's executor — the same isolation-assertion crash. All such calls now hop safely withTask { @MainActor }.Notifications now guide you instead of doing nothing
Turning notifications on requests permission if it's undetermined, and if it's denied it opens an alert pointing to System Settings › Notifications rather than silently failing.
Restored the smooth, rounded menu
Removed a custom background layer that made the popover look flat/square in the production build; it's back to the native translucent rounded style.
- 0.8.2Jul 1, 2026
Fixed a crash on launch (the app opened then immediately quit) on macOS 26
A notification/observer callback used
MainActor.assumeIsolated, which the macOS 26 Swift runtime turns into a hard trap when the callback isn't on the main actor's executor. Those callbacks now hop to the main actor safely withTask { @MainActor }. - 0.8.1Jul 1, 2026
First public release
Fixed the self-updater failing to reopen / relaunch after an update
The update script now runs fully detached from the app (so quitting to swap the bundle can't kill it mid-update), refreshes Launch Services so the new bundle isn't shadowed by a stale registration, clears quarantine, and retries the relaunch. It also logs each step for diagnosis.
Homebrew install —
brew tap broisnischal/battlify-releases https://github.com/broisnischal/battlify-releasesthenbrew install --cask battlify. The cask clears the download quarantine on install so the app launches without a Gatekeeper warning, and it tracks each release automatically. - Next
On the roadmap
- Scheduled charge limits by time of day
- Deeper health insights: cycle counts and capacity over time
- Localization, starting with the most-requested languages
Plans, not promises. Ideas are welcome on GitHub.