caffeinate держит Mac бодрым ровно до закрытия крышки — дальше он всё равно засыпает,
потому что сон по крышке это отдельная настройка, спрятанная за sudo. SleepSwitch
переключает обе сразу, одной иконкой в строке меню.
Пригождается, когда надо закрыть ноутбук, но оставить работать сборку, закачку, рендер или SSH-сессию — без внешнего монитора, без заглушки в HDMI и без приоткрытой крышки.
- Не спит при закрытой крышке. Захлопнули — продолжает работать.
- Не спит по бездействию. Пока режим включён, таймер сна игнорируется.
- Не гасит экран, пока режим включён — отдельной настройки нет и думать не о чем.
- Пароль спрашивается один раз. Установщик ставит узкое правило
sudo, дальше переключение идёт без запросов. - Не высадит батарею. Режим сам выключается ниже выбранного заряда, а по желанию — сразу при отключении от сети.
- Даёт знать, что сработало. Тихий тон при закрытии крышки и другой при открытии.
- Ничего не остаётся висеть. Выход, принудительное завершение, падение системы — запрет сна снимется в любом случае.
- Обновляется с GitHub — проверяет раз в сутки, отдаёт установщик и никогда не подменяет бинарники втихаря.
- Русский и английский, и приложение, и установщик, по языку системы.
- Чистый Swift, без зависимостей, без фонового демона, без телеметрии.
- Universal binary, Apple Silicon и Intel.
Скачайте .pkg из последнего релиза
и откройте.
Note
Приложение не подписано сертификатом Apple, поэтому первый раз macOS откажется его
открывать. Начиная с macOS 15 Sequoia правая кнопка это больше не обходит: откройте
.pkg, дайте себя заблокировать, затем зайдите в Системные настройки →
Конфиденциальность и безопасность — там в разделе «Безопасность» появится кнопка
«Всё равно открыть». На macOS 14 и старше — правой кнопкой по файлу → «Открыть»
→ в диалоге ещё раз «Открыть». В любом случае один раз.
Установщик кладёт приложение в /Applications, запускает его и — если не снять галочку
на шаге «Настроить» — ставит правило sudo для переключения без пароля.
| Действие | Результат |
|---|---|
| Левый клик по иконке | Включить или выключить режим |
| Правый клик | Меню: автозапуск, вход в систему, обновления, правило sudo |
Иконка и есть индикатор:
| Значок | Что означает |
|---|---|
| 🌙 | Обычный режим — Mac засыпает как настроено |
| ☕️ | Режим включён — сон полностью запрещён |
| Частично — сон по бездействию запрещён, но крышка усыпит |
Два независимых слоя, потому что macOS считает это разными вещами:
| Слой | Что запрещает | Нужен root |
|---|---|---|
pmset -a disablesleep 1 |
Сон по крышке и вообще любой сон | Да |
Ассершен PreventUserIdleSystemSleep |
Сон по бездействию | Нет |
Ассершен PreventUserIdleDisplaySleep |
Гашение экрана | Нет |
Ассершены держит сам процесс, поэтому они исчезают вместе с ним — залипнуть не могут.
Настройка pmset живёт дольше процесса, поэтому приложение снимает её при выходе и по
SIGTERM, а при запуске показывает реальное положение дел, читая SleepDisabled прямо
из IOPMrootDomain. Отказы, до которых не доходит ни один обработчик, закрыты отдельно —
см. Если приложение умерло с включённым запретом.
pmset disablesleep требует root. Спрашивать пароль на каждое переключение невозможно,
поэтому установщик пишет /etc/sudoers.d/sleepswitch:
вы ALL=(root) NOPASSWD: /usr/bin/pmset -a disablesleep 0
вы ALL=(root) NOPASSWD: /usr/bin/pmset -a disablesleep 1Две команды, без шаблонов. sudo сверяет аргументы точно, так что правило даёт ровно
одну возможность — переключить настройку сна. pmset -a sleep 0 по-прежнему просит пароль.
Файл готовится, проверяется через visudo и ставится целиком под root во временной папке
с правами 0700 — подменить его между проверкой и установкой некому. Имя учётной записи
проверяется до подстановки в sudoers, и правило выдаётся только администратору.
Отказаться можно на шаге установки, потом через меню — или руками:
sudo rm /etc/sudoers.d/sleepswitchПри включённом режиме закрытие крышки играет приглушённый фарфоровый тон, открытие — тон повыше: достаточно, чтобы убедиться, что Mac не уснул, ничего не открывая для проверки. Выключается в меню, а при выключенном режиме не звучит вовсе — закрытие крышки тогда просто означает сон.
Тоны синтезируются во время сборки скриптом
Tools/make-sounds.swift, так что аудиофайлов в репозитории нет.
На Mac без крышки нет ни звуков, ни самой настройки.
IOKit-ассершены залипнуть не могут — они принадлежат процессу и исчезают вместе с ним.
С настройкой pmset иначе: она переживает SIGKILL, принудительное завершение и панику
ядра, а до обработчиков приложения ни один из этих случаев не доходит. Без присмотра это
означает Mac, который не засыпает, без иконки в строке меню, объясняющей почему, и без
предохранителя по батарее — он работал в том самом процессе, который только что умер.
Поэтому запрет сверяет launch-агент: при входе в систему и раз в минуту. Пока запрет принадлежит приложению, оно обновляет файл аренды; протухшая аренда означает, что приложение умерло, держа запрет, — агент его снимает. Аренды нет вовсе — значит запрет ставили не мы, например руками через терминал, и агент его не трогает.
Аренда пишется до того, как запрет взведён. Записанная после, она оставляла бы окно: падение между двумя вызовами дало бы запрет без аренды, а это агент читает как «ставили не мы» — единственное прочтение, которое не должно доставаться нашему же падению. Плата за такой порядок — аренда, которая недолго может существовать без запрета за ней; поэтому приложение убирает её сразу, как только выясняется, что запрета нет, а агент удаляет протухшую одинокую аренду. Именно протухшую: только что записанную и ещё не подкреплённую запретом из-под живого приложения никто не выдернет.
Работает от вашего имени, а не от root, и снимает запрет тем же узким правилом sudo,
которым пользуется приложение, — новых прав себе не выдаёт. Без этого правила тихо снять
запрет он тоже не сможет: ещё один довод в пользу того, что установщик ставит правило
по умолчанию.
Запрет сна делает лёгкой ровно одну ошибку: включить режим, закрыть крышку, убрать ноутбук в рюкзак — и он греется там, пока батарея не сядет в ноль. Поэтому режим сам выключается, когда заряд опускается до выбранного порога (по умолчанию 20%), а при желании — сразу при отключении от сети. Обе настройки лежат в меню, а уведомление сообщает, что именно сработало.
На Mac без встроенной батареи обе настройки просто не показываются — неработающий переключатель хуже его отсутствия. Проверка идёт по типу источника питания, а не по принципу «источник вообще есть»: подключённый к настольному Mac ИБП — тоже источник. А если уровень заряда почему-то не читается, не срабатывает ничего: выключить режим по причине, которую приложение не может назвать, хуже, чем не трогать его.
Раз в сутки приложение спрашивает у GitHub, нет ли релиза новее. Если есть — приходит системное уведомление с кнопками «Скачать» и «Пропустить эту версию»: модальное окно поверх вашей работы не появляется. А проверку, запущенную вручную из меню, приложение отвечает окном — вы её ждёте. Проверку можно выключить в меню: тогда в сеть ничего не уходит, пока вы сами не попросите.
Себя приложение не подменяет. Оно скачивает .pkg из релиза и открывает его системным
установщиком — обновление проходит ту же авторизацию, что и первая установка. Запросы
разрешены только по https и только на хосты GitHub, включая промежуточные редиректы;
всё остальное отклоняется.
Сон и блокировка экрана — разные настройки macOS, SleepSwitch трогает только сон. Если при открытии крышки Mac просит пароль, это блокировка: macOS намеренно требует пароль учётной записи, чтобы её изменить, и ни одно приложение не может выключить её молча.
sysadminctl -screenLock off -password - # выключить
sysadminctl -screenLock immediate -password - # вернуть
sysadminctl -screenLock status # проверитьВ меню есть пункт, открывающий нужную панель системных настроек.
./make-installer.sh # → dist/SleepSwitch-<версия>.pkg
./install.sh # или сразу в /Applications, без установщика
./Tools/run-tests.sh # тесты; с --network ходит на настоящий GitHubNote
После локальной сборки остаётся build/SleepSwitch.app, и Spotlight его индексирует —
в поиске приложение начинает двоиться рядом с установленной копией. Лечится
rm -rf build dist. Файл .metadata_never_index тут не помогает: для обычных
подпапок Spotlight его игнорирует.
Нужен только Xcode или Command Line Tools. Иконка рисуется кодом
Tools/make-icon.swift во время сборки — бинарных ассетов в
репозитории нет. Забытый перевод ломает сборку:
Tools/check-localization.sh сверяет ключи L("…") из
исходников со всеми Localizable.strings.
Релиз выпускается тегом:
git tag v1.0.1 && git push origin v1.0.1macOS 13 Ventura или новее. Apple Silicon и Intel. Интерфейс следует языку системы — русский или английский.
Для обновления удалять ничего не нужно. Откройте новый .pkg — установщик сам погасит
запущенную копию и заменит бандл. Настройки и правило sudo сохранятся.
Чтобы удалить совсем, выберите в меню «Удалить SleepSwitch…». Сначала снимется
запрет сна — пока правило sudo ещё на месте и это можно сделать тихо, — затем удалятся
приложение, правило, запись об установке и настройки, после чего программа закроется.
Один пароль, одно подтверждение.
Из склонированного репозитория можно запустить uninstall.sh или сделать
то же руками:
sudo pmset -a disablesleep 0 # сначала это — см. предупреждение ниже
sudo rm -rf /Applications/SleepSwitch.app
sudo rm -f /etc/sudoers.d/sleepswitch
sudo pkgutil --forget com.ganin.sleepswitch.app
defaults delete com.ganin.sleepswitchWarning
Снимите запрет сна до удаления приложения. Это системная настройка, она переживает процесс: если перетащить приложение в корзину при включённом режиме, Mac перестанет засыпать, а выключателя уже не будет. Достаточно заранее выключить режим в меню.
Просто перетащить в корзину можно, только если режим выключен и вас не смущает, что правило sudo и запись об установке останутся в системе.