feat(launcher): built-in System commands (sleep, lock screen, restart, shut down, …)#497
Conversation
…n out, restart, shut down) Adds a Raycast-style System built-in feature: one-shot power/session actions surfaced as search commands, backed by a new `system_actions` Rust module with per-platform backends (mirroring the `power` module's backend-trait shape, incl. a fake backend for tests). - Windows: SetSuspendState / LockWorkStation / ExitWindowsEx with the SeShutdownPrivilege enable dance; Hibernate offered only when IsPwrHibernateAllowed(). - macOS: pmset sleepnow, CGSession -suspend, and System Events verbs via osascript (graceful Apple-menu semantics). - Linux: logind over D-Bus gated on the Can* probes (interactive=true so polkit may prompt); Session(auto).Lock with ScreenSaver fallback; log out = Session(auto).Terminate. The `system` built-in registers one dynamic command per action the machine actually supports (system_actions_supported), so Hibernate never shows where the OS has it disabled. Destructive actions confirm behind the quit-style focus lock. The Tauri commands are host-only — not mapped in the asyar:api:* table, so extensions cannot reach them. New moon / log-out SDK icons follow the calc-* precedent (Xoshbin#489). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MGJAx66y29o33szDvVYTBH
There was a problem hiding this comment.
Code Review
This pull request introduces a new built-in system feature that allows users to trigger system actions (sleep, hibernate, lock screen, log out, restart, and shut down) across Linux, macOS, and Windows. The feedback identifies critical compilation errors on Windows due to the use of the windows crate's BOOLEAN type instead of Rust's native bool. On macOS, the lock screen command relies on a deprecated CGSession path that was removed in macOS 11, which will cause runtime failures. Finally, it is recommended to change the Tauri commands to async fn to prevent blocking the main UI thread during synchronous OS operations.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
- macOS lock: CGSession was removed in macOS 11, so `CGSession -suspend` would fail on all modern machines. Use `pmset displaysleepnow` instead — no TCC consent; locks under the default "require password after display sleep" security setting (caveat documented in the module docs, along with the deliberately-avoided alternatives). - Command layer: make both tauri commands async so the blocking platform work (D-Bus calls, process spawns, SetSuspendState blocking until resume) runs on Tauri's thread pool instead of the main thread. The two BOOLEAN-vs-bool review comments are declined: windows 0.61.3 declares SetSuspendState/IsPwrHibernateAllowed with plain `bool`, and the code compiles and was manually exercised on Windows 11. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MGJAx66y29o33szDvVYTBH
|
Hey @dose-dot-dev since you are working on Windows, sounds like the commands are all working on windows. but on macos, I just tested some of the commands, some of them are working and some of them are not. since you are on Windows I will work on the macos platform side myself then merge it. |
|
Thanks @Xoshbin hopefully they are simple fixes on the macos side. Eventually I'll have a Mac with a configured dev environment I'll be able to catch some of these things on as well. |
…d offload system actions to blocking threads
|
this is merged! Thanks for the PR and getting these system commands set up. It's honestly really helpful having someone whose main platform is Windows contributing to the project, as it helps cover that side of things a lot. Also, congrats on the new Mac! Having a configured dev environment will definitely make testing the macOS side easier down the road. Enjoy the new setup! |
What
Adds a Raycast-style System built-in feature: one-shot power/session actions available from search —
Destructive actions (sign out / restart / shut down) show a danger confirm dialog first, using the same focus-lock idiom as the Quit feature. Sleep/hibernate/lock fire immediately, hiding the launcher window before the OS takes over.
Why
These are table-stakes launcher commands (Raycast ships them out of the box on both macOS and Windows) and Asyar currently has no equivalent target. Bonus:
raycast_importcurrently has to skip imported system-command hotkeys because there is nothing to map them to — with this landed, a follow-up could map them tocmd_system_dyn_*targets.How
Rust — new
system_actionsmodule, deliberately mirroring thepowermodule's shape (platform-neutral state + backend trait, per-platform backends,fakebackend for tests):SetSuspendState(sleep/hibernate),LockWorkStation,ExitWindowsEx(logoff/reboot/poweroff, noEWX_FORCE— apps keep their save prompts), with theSeShutdownPrivilegeenable dance where required. Hibernate is offered only whenIsPwrHibernateAllowed().pmset sleepnow;CGSession -suspendfor lock;osascript→ System Eventslog out/restart/shut down(same graceful semantics as the Apple menu; first use triggers the one-time Automation consent). No hibernate.zbusblocking, same transport aspower::linux) —Suspend/Hibernate/Reboot/PowerOffgated on theirCan*probes withinteractive = trueso polkit can prompt;Session(auto).Lockwith anorg.freedesktop.ScreenSaver.Lockfallback; log out =Session(auto).Terminate.Command surface (
system_actions_supported/system_action_run) is host-only: likequit_app, the commands are not mapped in theasyar:api:*permission table, so extension workers can't reach them through the broker. Exposing them to extensions would need a dedicated permission + consent wiring first — out of scope here.Frontend —
built-in-features/systemregisters one dynamic command per supported action (viareplaceDynamicCommandsBuiltin, allowlisted alongsidescripts/agents), so the search index only ever contains actions this machine can perform — e.g. Hibernate never appears where the OS has it disabled, and a non-systemd Linux box degrades to just Lock Screen.run()re-checkssupported()Rust-side, so it fails closed even if a stale row survives.Two new SDK icons (
moon,log-out) follow thecalc-*precedent from #489.Design notes / open questions
CGSession -suspend(lock) and the System Events verbs are the widely-used non-private-API routes, but if you preferSACLockScreenImmediateor different semantics, happy to adjust.Terminate— session-level, not the DE's graceful logout flow. It's behind the confirm dialog; alternative would be DE-specific commands (gnome-session-quitetc.), which felt worse.Verification
cargo test— 2864 passed (incl. the built-in manifest schema test over the new manifest and 9 new unit tests);cargo clippy --all-targets -- -D warningsandcargo fmtclean. (Run under WSL/Linux as with previous PRs —cargo teston Windows currently fails to load the test binary on cleanmain(STATUS_ENTRYPOINT_NOT_FOUND, reproduces aftercargo clean, app binary unaffected); I'll file that separately.)pnpm -r test:run— green (Windows), incl. 9 new tests covering registration order/filtering, per-platform naming, confirm/cancel flows, and unknown-id handling.powercfg /a; Lock Screen and Sleep end-to-end (launcher hides before the action fires); Sign Out / Restart / Shut Down danger confirm dialogs verified incl. the cancel path.🤖 Generated with Claude Code