Build Serene

YESreplaces $4/mosaves $48/yrback to the verdict

0%0 of 16 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A focus timer whose hard problems are keeping time correctly across sleep and restarts, changing system state in a way that is always reverted, and being honest that a desktop app cannot truly lock anybody out of anything.

estimated effort weekendthe files for this build are in the project pack

ShellTauri 2 with React and TypeScript, no network calls at allTimeSessions stored as instants and recomputed from the clock on every wakeBlockingA name resolution change applied with explicit elevation, recorded before it is madeSafetyA watchdog that reverts on exit, on crash and at next launchStorageSQLite for sessions and goals, everything local

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Builds the interface half of the application.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. installfree

    Why The privileged file operation, the watchdog and the wake notifications all live on this side.

    Get it rustup.rs, then the platform packages listed in the Tauri prerequisites. open ↗

    Verify cargo --version prints a version and a bare Tauri app runs

  3. have readyfree

    Why The revert paths are the whole safety argument and the only way to test them is to kill the process and pull the power while a block is applied.

    Get it A virtual machine with a snapshot taken before the first test.

    Verify A forced power cut with a block applied leaves the machine reachable after reboot

  4. decidefree

    Why The watchdog interval is the longest a crash can leave a block in place, and the maximum session length is the ceiling on any single mistake.

    Get it Write down both, and the manual revert command, before implementing the blocking.

    Verify Both are in settings and the command is in the README

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- sessions(id, goal, planned_start, planned_end, actual_start, actual_end, outcome, interruptions)
- blocklists(id, name, entries_json, active) · the hosts or domains a session blocks
- applied_changes(id, session_id, target_path, backup_path, applied_at, reverted_at, revert_method) · written before the change is made
- interruptions(id, session_id, at, kind, note) · recorded only as counts and kinds, never what you were doing
- day_plans(date, intentions_json) · what the day was meant to contain
- settings(key, value) · including the watchdog interval and the maximum session length
- The applied_changes row exists before the file is touched, so a crash between the two leaves a record that the next launch can act on.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DATA_DIRrequired~/.local/share/focus/focus.dbSessions, plans and interruption counts. Never leaves the machine.
HOSTS_FILE_PATHrequired/etc/hostsThe file that is modified. Backed up before every change.
BACKUP_DIRrequired~/.local/share/focus/backupsTimestamped copies of the original file, kept until verified reverted.
WATCHDOG_SECONDSrequired15The longest a crash can leave a block applied.
MAX_SESSION_MINUTESrequired120A ceiling on any single mistake, enforced regardless of what was entered.
UPDATE_CHECKSrequiredoffOff by default, asserted by the no-network test.

The build, in order

  1. A timer that is right after the laptop has been shut

    Session state is derived from instants, not from a running countdown.

    1. The clock is the source of truth; the interface only renders it.

      Files src/session/time.tssrc/session/time.test.ts

    2. The wake event is the one moment your assumptions are guaranteed stale.

      Files src-tauri/src/power.rs

    3. It happens more often than you think, and it should not grant extra time.

      Files src/session/anomaly.ts

    done when · tick each as it passes
    watch out
    • Counting down with an interval in the interface produces a session that pauses while the lid is shut and then resumes as if no time passed, so a twenty five minute session ends ninety minutes later and every statistic afterwards is fiction. Compute from stored instants every time, and treat a wake as a reason to recompute rather than to resume.
  2. Changing the machine, and always changing it back

    Every system change is recorded before it happens and reverted by three independent paths.

    1. A crash between the row and the write is recoverable; the reverse is not.

      Files src-tauri/src/blocking.rs

    2. Three paths, because the first two can both be killed.

      Files src-tauri/src/watchdog.rstests/revert.test.ts

    3. The timer still works; the speed bump does not.

      Files src/session/blocking.ts

    done when · tick each as it passes
    watch out
    • Reverting only on a clean quit means a crash, a forced restart or a battery dying leaves the block in place indefinitely, and the person cannot reach the sites they need with no idea why. Write the applied_changes row first, revert from the watchdog, from the next launch and from a documented manual command, and treat the row rather than the app's memory as the record.
  3. One goal per session, reachable from the keyboard

    Starting a session takes a keystroke and a sentence.

    1. Setup friction is the reason focus tools get abandoned.

      Files src/ui/StartSession.tsx

    2. Start, extend, end. Nothing else needs one.

      Files src-tauri/src/shortcuts.rs

    3. The fastest accessibility test there is.

      Files docs/keyboard-walkthrough.md

    done when · tick each as it passes
    watch out
    • Making the session setup a multi-step form with project, tag, estimate and category means the tool gets skipped on exactly the mornings it would have helped, because the setup costs more attention than the first ten minutes of work. One field, one shortcut, and defaults that come from last time.
  4. What happens when you try to break out

    Interruptions are counted honestly without recording what you were doing.

    1. The person already knows they got distracted.

      Files src/ui/BlockPage.tsx

    2. Enforced by the schema, not by remembering.

      Files src-tauri/migrations/002_interruptions.sql

    3. A recorded decision beats a session that fizzles out.

      Files src/session/end.ts

    done when · tick each as it passes
    watch out
    • Logging every blocked domain to build a report of your distractions creates a browsing history file that nobody asked for, sitting unencrypted beside a focus timer, and it is the first thing a person would be upset to find. Count the interruption, name the goal, and store nothing else.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more productivity utilities.