Oxiwake keeps your machine awake where the OS allows it — and tells you when it cannot.
Oxiwake (ow) is a cross-platform "keep awake" CLI/daemon. It holds a wake lock
open for as long as you ask, and reports honestly when the OS will not let
it. Think caffeinate / systemd-inhibit / PowerToys Awake — but
cross-platform, with a daemon you can toggle on and off and a doctor that
tells you exactly what is and isn't guaranteed.
ow # print state (off / on + which backend)
ow on # start the keep-awake daemon
ow off # stop it
ow toggle # flip it
ow status # print current lock state
ow doctor # probe the environment and every backend, with honest caveatsOxiwake does not hard-code distro names. It detects capabilities and picks
the strongest mechanism available. See docs/setup.md for the
full backend & design rationale.
Linux (priority order):
systemd-logindD-Bus inhibitor — main backend- XDG Desktop Portal inhibit
- GNOME SessionManager
- KDE PowerDevil / Solid
org.freedesktop.ScreenSaver(idle-only)- X11 XScreenSaver / DPMS (feature
linux-x11) - Wayland idle-inhibit (feature
linux-wayland)
Windows:
PowerCreateRequest+PowerSetRequestSetThreadExecutionStatefallback
ow on cannot just acquire a lock and exit. On Linux, systemd-logind
returns a file descriptor and the inhibitor is released the moment that FD
closes; on Windows, PowerSetRequest is held on a handle that should be cleared
when done. So ow on spawns a small detached daemon that keeps the FD/handle
alive; ow off tells that daemon to stop, which drops the guard and releases
the lock. The lock's lifetime is tied to the guard's lifetime (RAII) — this is
the core, leak-safe design.
State lives in:
Linux: $XDG_RUNTIME_DIR/oxiwake/{state.json, oxiwake.sock, pending.{pid}.json, oxiwake.lock}
Windows: %LOCALAPPDATA%\Freeoxide\Oxiwake\{state.json, oxiwake.sock, pending.{pid}.json, oxiwake.lock}
state.json is the persistent lock snapshot; pending.{pid}.json is the
per-invocation (pid-keyed) request hand-off from CLI to daemon; oxiwake.lock
is the singleton advisory lock (flock on Linux, LockFileEx on Windows) the
daemon holds for its whole lifetime so two racing ow on invocations can never
both reach OS-lock acquisition. All of these live in a tmpfs and are wiped on
logout/reboot, which is fine for transient lock state.
Usage: ow [OPTIONS] [COMMAND]
Commands:
on Start the keep-awake daemon (idempotent: a no-op if already running)
off Stop the keep-awake daemon (idempotent: a no-op if not running)
toggle Start the daemon if off, stop it if on
status Print the current lock state
doctor Probe the environment and every compiled-in backend, and print a report
help Print this message or the help of the given subcommand(s)
Options:
-j, --json Emit machine-readable JSON (status, doctor)
-v, --verbose... Increase verbosity (repeat for more detail)
-h, --help Print help
-V, --version Print version
on / toggle flags: --display (also keep the display on), --aggressive-lid
(add handle-lid-switch; usually needs privilege), --reason <text>.
doctor prints each backend's supported (compiled in) and available
(reachable right now) status, plus guarantees — the things that backend
cannot promise. For example:
- systemd-logind:
blockonshutdown/sleep/handle-*typically needs a PolicyKit privilege;idleis the one routinely allowed unprivileged. - Windows: on Modern Standby / battery, system/execution requests can be terminated ~5 minutes after the sleep timeout, and user-initiated sleep (power button, lid, Sleep menu) clears requests.
If ow on cannot take the lock (e.g. the OS refuses), it reports the real
reason rather than hanging.
Oxiwake is at v0.1.0. There is no crates.io package yet (a publish is
planned), so the primary path today is build from source, covered in
Building below. If you have a Rust toolchain, the quickest one-off
install is from git:
cargo install --git https://github.com/freeoxide/wakePrebuilt binaries for each release are the intended future path and will be attached to GitHub Releases once available. Until then, build from source.
cargo build --release # the binary is target/release/ow
cargo test # unit + the in-process daemon-lifecycle test
cargo clippy --all-targets # zero warningsDefault Linux build includes all D-Bus backends. X11/Wayland are opt-in:
cargo build --features linux-x11
cargo build --features linux-waylandThe Windows backend + named-pipe transport can be type-checked without a Windows toolchain:
rustup target add x86_64-pc-windows-gnu
cargo check --target x86_64-pc-windows-gnu(Final linking needs a mingw-w64 toolchain; cargo check exercises the full
windows-sys type-check without it.)
src/
model.rs WakeTarget / WakeMode / WakeRequest / WakeStatus / DoctorReport
+ the WakeBackend / WakeGuard traits (the shared contract)
error.rs OxiwakeError / Result
backend/ one module per backend (logind, portal, gnome, kde,
screensaver, x11, wayland, windows) + mod.rs registry
platform/ IPC transport: Unix socket (linux) / named pipe (windows)
ipc.rs the ClientMsg/DaemonReply protocol (newline-delimited JSON)
daemon.rs daemon lifecycle: acquire -> publish state -> serve -> release
paths.rs runtime dir + state/socket/pending path resolution
state.rs atomic LockState read/write
doctor.rs environment + per-backend probing
cli.rs/main.rs the `ow` CLI surface + dispatch
output.rs human + JSON formatting
tests/
model.rs model-helper unit tests
daemon_lifecycle.rs in-process RAII lifecycle test (acquire -> serve -> release)
docs/setup.md the backend & setup design
MIT.