Skip to content

killerk3emstar/OpenDente

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenDente

Battery charge limiter for macOS. Menu bar app - pick a target level (e.g. 80%), the system stops charging when it gets there.

Open-source alternative to AlDente, GPL-3 licensed. Built to stay out of the way: 2-second SMC poll, no animated UI in the background, no telemetry.

Sailing mode Detailed view with full SMC and adapter info

Status

Beta. So far only tested on a single M4 MacBook on macOS Tahoe (26).

The SMC code paths target Apple Silicon broadly (M1 through M4) and macOS 14+, and there is detection for both the older (CH0B/CH0C) and newer (CHTE) charging-control key sets, but anything other than M4 + Tahoe is unverified at this point. If you run it on something else, an issue with the result would be very welcome.

The app writes to the SMC. It tries to fail safe (charging is restored on quit, on helper crash, and via watchdog), but you use it at your own risk. No warranty.

Compared to AlDente

Core charging features overlap with what AlDente puts behind its Pro tier: charge limit, sailing mode, heat protection, force discharge, MagSafe LED control, sleep handling.

What's different here:

  • Open source, GPL-3. No Pro tier, no paywalled features.
  • No telemetry, no analytics, no auto-update server. The app talks to your battery and nothing else.
  • Fixed 2-second polling and no animated power-flow visualization - AlDente's drain on the battery itself was the original motivation to write this.
  • Smaller in scope. No calibration mode, no auto-update, English-only UI, no fancy onboarding.

Apple's native charge limit (macOS 26.4)

In macOS 26.4, Apple shipped their own charge limit in System Settings → Battery (80% up to 100% in 5% steps). OpenDente works fine alongside it, system limit on or off.

The two are independent firmware gates - both have to be open for charging to happen, so the effective ceiling is whichever is lower. There is no fight loop and no override cycle: set the system to 90% and OpenDente to 80%, you get 80%. Turn the system limit off, OpenDente still works on its own.

OpenDente also detects when it's the system limit (rather than its own write) that's blocking charging, via NotChargingReason bit 24, and labels it in the popover so it's clear which gate is holding the line.

Features

  • Charge limit, 50–100%
  • Sailing mode - let the battery drain to a lower threshold before topping up, instead of trickle-charging at the cap
  • Force discharge while plugged in
  • Heat protection - pause charging above a configurable temperature
  • Sleep handling - stop charging during sleep; optionally inhibit sleep until the limit is reached
  • MagSafe LED reflects actual charging state
  • Per-event native notifications

What it shows

Even if you don't care about charge limiting itself, the popover surfaces a fair amount of data read directly from the SMC and IORegistry that's otherwise awkward to get at:

  • Real-time adapter power, system power draw, and battery charge/discharge wattage
  • Battery temperature, cycle count, design and current capacity, health percentage
  • Adapter info: manufacturer, model, serial, rated wattage, voltage, current
  • Decoded NotChargingReason when something pauses charging - so you can tell whether it's heat, sleep, the system limit, or OpenDente itself

If you've ever wanted to see exactly how many watts your charger is delivering vs. how much your machine is actually pulling, that view is there.

Requirements

  • macOS 14 (Sonoma) or newer
  • Apple Silicon Mac
  • Admin password once, to install the privileged helper

How it works

Battery state is read via IOKit (no privileges needed). Charging is controlled by writing SMC keys, which requires root, so the app ships a small XPC daemon (com.opendente.helper) installed via SMAppService. Main app handles UI and reads; the helper handles writes.

The relevant SMC keys differ between Apple Silicon generations:

  • M1, M2, M3: CH0B, CH0C to gate charging; CH0I to force discharge
  • Newer chips (≈2023+, macOS Sequoia and Tahoe): CHTE, CHIE

OpenDente probes both at startup and uses whichever set responds.

On Apple Silicon, charging is binary - there is no firmware-level "stop at 80%". Maintaining a target level requires the app to actively flip the charge gate as the battery crosses the threshold.

Build

The Xcode project is generated by XcodeGen:

brew install xcodegen
xcodegen generate
open OpenDente.xcodeproj

DEVELOPMENT_TEAM in project.yml is set to my own team ID - change it to yours before building.

Tests

xcodebuild -project OpenDente.xcodeproj -scheme OpenDente test

Unit tests cover the charging state machine, SMC value decoding (sp78/sp96 fixed-point), display logic, polling, and notification gating.

Layout

OpenDente/         main app (SwiftUI menu bar)
OpenDenteHelper/   privileged XPC helper tool
Shared/            XPC protocol + shared constants
OpenDenteTests/    unit tests
project.yml        XcodeGen config

Acknowledgements

This project leans on prior reverse-engineering work, in particular:

License

GPL-3.0. See LICENSE.

About

Battery charge limiter for macOS. Open-source alternative to AlDente.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages