From 98fc6036ee817a92810e060c80d48aa6a936a1ab Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 15 Oct 2026 11:25:50 +0200 Subject: feat(status): quiet mode mutes the Claude and opencode sounds A new registry mode, status.quiet, with a row on the status page. Both tools will play their sounds through notify-sound, which asks statusctl and plays nothing while quiet is on, so their popups stay and only the sound goes. Presentation sets quiet and restores it afterwards, like dnd and nolock: a sound during a call or a game is what quiet is for. notify-sound ignores any argument it has no sound for, because the opencode notifier runs its command on every event, session_started and user_message included. Co-Authored-By: Claude Opus 5.5 --- desktop/modules/status/README.md | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'desktop/modules/status/README.md') diff --git a/desktop/modules/status/README.md b/desktop/modules/status/README.md index b25505f..d3d0cce 100644 --- a/desktop/modules/status/README.md +++ b/desktop/modules/status/README.md @@ -1,7 +1,7 @@ # status -Desktop modes as state: `dnd`, `presentation` and `nolock`, owned by the -`Status` singleton and stored as files under `$XDG_RUNTIME_DIR`. A fourth, +Desktop modes as state: `dnd`, `presentation`, `nolock` and `quiet`, owned by +the `Status` singleton and stored as files under `$XDG_RUNTIME_DIR`. A fifth, `status.gaming`, is written only by the shell's game detector; it is not a mode `statusctl` exposes. @@ -10,6 +10,7 @@ mode `statusctl` exposes. $XDG_RUNTIME_DIR/status.dnd $XDG_RUNTIME_DIR/status.presentation $XDG_RUNTIME_DIR/status.nolock + $XDG_RUNTIME_DIR/status.quiet $XDG_RUNTIME_DIR/status.gaming Each holds `0` or `1`; a missing file means off. That directory is tmpfs, so a @@ -43,10 +44,10 @@ and reasserted when it returns. `dnd` has none of its own. It is state the notification daemon reads. -`presentation` sets `dnd` and `nolock`, asserts a Wayland idle inhibitor, and -pauses breaktimer. Turning it off restores `dnd` and `nolock` to the values -they had before rather than clearing them, so hand-set DND or a hand-set -disable survives a presentation. +`presentation` sets `dnd`, `nolock` and `quiet`, asserts a Wayland idle +inhibitor, and pauses breaktimer. Turning it off restores the three to the +values they had before rather than clearing them, so hand-set DND or a +hand-set disable survives a presentation. `nolock` disables auto-lock by holding the idle inhibitor. That is the only thing that stops hypridle's `loginctl lock-session`, so the mode governs @@ -56,6 +57,20 @@ for a number of minutes, in which case the singleton's timer re-enables it. The timer is shell-lifetime: a restart during a timed disable leaves the lock off until it is toggled, the same class of limit as `dndBeforePresentation`. +`quiet` mutes the Claude and opencode sounds and leaves their popups alone. +The shell does nothing with it: both tools play through `notify-sound`, which +asks `statusctl quiet get` and plays nothing on a 1. `~/bin/notify-sound` is a +symlink to the repo copy, like `statusctl`. + + notify-sound claude Claude Code's Notification hook + notify-sound opencode-notifier's command hook + +The opencode notifier runs its command for every event, `session_started` and +`user_message` included, so an argument with no sound plays nothing; only +`permission`, `complete`, `error` and `question` do. The notifier's own sounds +are off in `opencode-notifier.json`, and it rereads that file on every event, +so neither change needs an opencode restart. + breaktimer is paused and resumed by verb, never by writing its state file. See Breaktimer below, which is also the read direction. @@ -140,10 +155,16 @@ still allowed, since the manual half is worth setting for when the game exits. The watch therefore follows `status.gaming` as well as its own file, and emits only on a real change so an unchanged rewrite draws nothing. -## The check +## The checks ./test-statusctl.sh + ./test-notify-sound.sh Points `XDG_RUNTIME_DIR` at a temporary directory, so it never touches live modes. Covers the file format, the atomic write, the toggle, the unknown-mode error, both the activated report and the absent-file off report. + +`test-notify-sound.sh` puts a fake `paplay` first on `PATH` and a temporary +`XDG_RUNTIME_DIR` under it, so it plays nothing and leaves the live mode +alone. It covers the file per argument, silence for an event with no sound, +and silence while `quiet` is on. -- cgit v1.2.3