Removing the Focus-Mode Daemon

Commit 937c597 · digital_wellbeing/ · 2026-07-19

Background

digital_wellbeing/ is a folder of small personal-automation daemons and installers that fight the author's own bad habits: a compulsive-app-opening blocker, a LeechBlock installer, a pacman wrapper that adds friction to installing distracting software, and — until this change — a focus-mode daemon.

The idea behind focus-mode was simple: Steam (gaming) and web browsers compete for the same attention, so let only one of them run at a time. Concretely, focus_mode_daemon.py ran as a systemd user service that polled /proc every 2 seconds, and enforced a rule: whichever category — Steam or browsers — started first "wins", and the daemon pkills the other one the moment it shows up. A companion whitelist subcommand let the author temporarily allow browsers during a gaming session, for things like a two-factor-auth prompt that has to open in a browser.

This lived across four files: focus_mode_daemon.py (the state machine and CLI), _focus_mode_lib.py (process detection via /proc/*/stat, logging, and the actual pkill calls), install_focus_mode_daemon.sh (installs a systemd --user service), and a bare __init__.py whose only content was a one-line docstring naming the daemon.

Why remove it instead of fixing it? The installer's own comments reveal it: check_and_enable_services.sh — the script that audits and self-heals all the other daemons on this system — repairs a broken service by running its installer as sudo -u <user> bash install_focus_mode_daemon.sh install. But sudo -u changes the UID without granting a login session: XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS stay unset, so every systemctl --user call inside the installer died with "Failed to connect to user scope bus". The installer tried to route around this by deriving those paths from the effective UID — but by the time this change landed, the daemon was confirmed not installed and not running on the live system at all. A feature that silently never actually deployed is exactly what "unusable in its current state" means here.

Intuition

Before removal, the daemon's core was a three-state machine. Read it as: "no app category has claimed the screen yet, until one shows up — at which point the other gets killed on sight."

No mode
→
Steam appears
→
Gaming
(browsers killed)
No mode
→
Browser appears
→
Browsing
(Steam killed)

The one subtlety worth internalizing — because it's easy to misread — is what happened if both Steam and a browser were already running the moment the daemon started, with no mode active yet. The code didn't wait to see which one the user "meant" first: it directly entered gaming mode and killed the browsers. Steam wins ties.

Play with the old state machine

This logic is gone from the repo now, but it's small enough to simulate. Toggle which processes are "running", hit Tick to step the daemon's update() once, and watch the mode and log react exactly as the deleted code would have.

Mode: none
Waiting for first tick…

Try it: check both boxes, leave whitelist off, then hit Tick once from a cold start — gaming mode wins and the log shows a browser kill. Now reset, enter gaming mode with just Steam, turn on whitelist, then check the browser box and Tick — no kill this time, because the whitelist suppresses the enforcement while gaming mode is already active.

With the daemon deleted, none of this runs anymore. The system-level picture also gets simpler:

BeforeAfter
check_and_enable_services.sh --status row count 12 services, incl. focus_mode 11 services
install_core_system.sh secondary modules 8, incl. Focus-mode daemon 7
test_security_hardening.sh checks 27 tests, incl. 3 focus-mode tests 24 tests

Code

1. Delete the daemon itself

All four files under digital_wellbeing/ that made up the daemon are gone: the 320-line state machine, the 227-line process/kill library it imported, the 241-line systemd installer, and the one-line package docstring.

- focus_mode_daemon.py           (320 lines: FocusMode state machine + CLI)
- _focus_mode_lib.py             (227 lines: /proc scanning, pkill helpers)
- install_focus_mode_daemon.sh   (241 lines: systemd --user unit + install/uninstall/status)
- __init__.py                    (1 line: package docstring)

2. Stop offering to install it

install_core_system.sh's secondary-module menu drops item 8 outright — it was the last entry, so no renumbering was needed for the remaining seven.

-ask_install "Focus-mode daemon" \
-    bash "$LINUX_CONFIG/scripts/periodic_background/digital_wellbeing/install_focus_mode_daemon.sh" install
-

3. Stop auditing and self-healing it

check_and_enable_services.sh is the script that checks all 12 (now 11) personal services and repairs anything broken. Its entire check_focus_mode() function — the one whose repair path hit the sudo -u session-bus bug described above — is deleted, along with its variable, its slot in the summary table, and its call site. The remaining services in the printed list shift down by one number so item 8 (Thorium startup) doesn't leave a gap where 6 used to be.

-  6. Focus mode daemon    - Steam/Browser mutual exclusion (user service)
-  7. Compulsive blocker   - Limits messaging apps to one launch per hour
+  6. Compulsive blocker   - Limits messaging apps to one launch per hour
+  7. Thorium startup      - Auto-launch Thorium with Fitatu on boot
   ...
-	for service in ... hosts focus_mode compulsive_blocker ...; do
+	for service in ... hosts compulsive_blocker ...; do
   ...
-	check_hosts
-	check_focus_mode
-	check_compulsive_blocker
+	check_hosts
+	check_compulsive_blocker

4. Drop the test coverage, keep the numbering sane

test_security_hardening.sh loses its three focus-mode checks (daemon file exists, installer exists, service is active). The tests that followed — for an unrelated screen-locker component — get their comment numbers shifted down from 23–27 to 20–24, purely so the numbering stays sequential. test_result() tallies pass/fail/skip by counting calls, not by parsing these comments, so this renumbering is cosmetic, not functional.

-# Test 20: Focus mode daemon script exists
-if [[ -f "$focus_daemon" ]]; then ...
-# Test 21: Focus mode installer exists
-...
-# Test 22: Focus mode daemon is running (user service)
-...
-
-# Test 23: Screen locker exists
+# Test 20: Screen locker exists

5. Update the docs

CLAUDE.md's directory map and "Key scripts" list both drop their mentions of the daemon.

-│       ├── digital_wellbeing/      # Compulsive-opening blocker, focus daemon, LeechBlock
+│       ├── digital_wellbeing/      # Compulsive-opening blocker, LeechBlock
 ...
-- `scripts/periodic_background/digital_wellbeing/focus_mode_daemon.py` — Linux digital-wellbeing daemon

Left untouched on purpose: phone_focus_mode/ (a completely separate GPS-based Android app-restriction system that just happens to share the word "focus"), and the historical design docs (docs/SECURITY_HARDENING_ANALYSIS.md, docs/superpowers/evidence|contracts) that originally proposed and tracked this daemon — those stay as append-only history of what was tried.

Quiz

Five questions on the reasoning behind this change. Click an option to check it.

Score: 0 / 5