Skip to content

drmowinckels/entracte

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

189 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Entracte logo - proscenium arch in a teal-to-rose gradient

Entracte

Pronounced "ahn-TRAHKT" (French entracte, IPA /ɑ̃.tʁakt/) — not "en-tract".
🔊 Hear it on the docs site

A cross-platform break reminder app for macOS, Windows, and Linux —
named after the theatre interval between acts.

Inspired by [Stretchly](https://hovancik.net/stretchly/)

Checks codecov Latest release License: Apache 2.0 Platforms: macOS, Windows, Linux Built with Tauri 2 Written with Claude


A micro break overlay: countdown ring at 10 seconds, with Postpone and Skip buttons

What it does

Entracte lives in your menu bar / tray and nudges you to take breaks. It tries hard not to interrupt:

  • Three break kinds — short Micro breaks (eye/posture, ~20s), Long breaks (multi-minute), and a Sleep prompt during a configurable bedtime window.
  • Skip when you shouldn't be interrupted — pauses for system Do Not Disturb, an active camera (you're in a meeting), idle time (you already stepped away), or hours outside your work window.
  • Pause from the tray — 15m / 30m / 1h / 2h / 4h / until tomorrow 6am / indefinitely. The tray icon shows pause bars while paused, so the state is visible at a glance.
  • Multi-monitor aware — show breaks on every display, just the primary, or only the monitor your cursor is on, with no Space-hopping fullscreen.
  • Windowed break mode — optionally shrink the overlay to 80% of the monitor (centered) so the rest of your desktop stays reachable while the reminder is up.
  • Pre-break heads-up — optional notification a configurable number of seconds before each break.
  • Daily screen-time budget — opt-in wind-down nudge when you cross a daily active-time budget (default 8 hours), with a configurable snooze interval.
  • Tray countdown — optional MM:SS countdown next to the menu-bar icon, configurable to track the next short, long, or soonest break (macOS and Linux).
  • Notification-only mode — per break kind, swap the overlay for a gentle system notification when you'd rather not be interrupted by a full-screen dim. Note that engagement metrics (completion, skip, postpone) aren't recorded for break types in notification mode, since there's no overlay to act on.
  • Move with you — export a full local backup (settings, profiles, break history, screen-time, pause state, manual supporter token if you have one) to JSON and import it on another machine. Atomic stage-then-commit on import; partial-failure rollback restores your previous state.

Themes

The overlay is always dark — it has to dim everything else — but the accent and background tone follow your choice.

Dark theme overlay Midnight theme overlay Forest theme overlay Sunset theme overlay Rose theme overlay

Stats

Entracte keeps a local history of breaks taken, dismissed, and suppressed, with a time-of-day breakdown and a 12-week heatmap. Export to CSV, export/import a full local backup bundle, or clear at any time.

Stats summary: breaks taken, dismissal rate, time paused, and reasons breaks were suppressed Stats charts: time-of-day distribution and 12-week heatmap

Install

macOS — via Homebrew (the cask lives in this repo, so tap from URL):

brew tap drmowinckels/entracte https://github.com/drmowinckels/entracte
brew install --cask drmowinckels/entracte/entracte

Linux / Windows — download the .deb, .rpm, .AppImage, .msi, or .exe from the Releases page (pick the latest tag; pre-releases — the 0.0.X beta line — don't surface under releases/latest).

Windows users: the .msi / .exe aren't code-signed yet — SignPath Foundation turned down our first application on visibility grounds (the project is too new). SmartScreen will warn you when you run the installer; click More info → Run anyway to proceed. See the install guide for how you can help us get there — stars, forks, mentions, and contributions all count.

Command line

The same entracte binary doubles as a small CLI for scripting / hotkey wiring. Action commands forward to the running tray app:

entracte pause 30m                 # pause for 30 minutes
entracte trigger long              # fire a long break now
entracte --profile=Focus --colour=midnight   # switch profile + theme in one call
entracte status                    # JSON: pause state + active profile
entracte log                       # tail the entracte log
entracte help                      # full reference

Full command reference, IPC details, and tips in docs/guide/cli.md.

Free and open

Entracte is free, cross-platform, and open source under Apache 2.0. Every scheduling, suppression, profile, hooks, stats, accessibility, and CLI feature is available to everyone.

A Supporter pack is available as a way to back development. It unlocks personalisation extras — custom overlay colour, theme rotation, editable break hints, custom CSS, and custom sounds — through a one-off purchase. The unlock check lives in plain source: it's an honour-system thank-you, not a DRM scheme. Nothing in the scheduling, suppression, profile, hooks, stats, accessibility, or CLI surface is gated.

Stack

  • React 19 + TypeScript + Vite frontend.
  • Rust + Tauri 2 + Tokio backend.
  • Per-OS native hooks for Do Not Disturb, camera-in-use, and idle detection.

Architecture

The scheduler is the brain: a Tokio tick loop in src-tauri/src/scheduler/ that consults native hooks, applies pause/suppress rules, and decides when (and how) to surface a break. The tray, CLI, and settings UI all push into the same scheduler; the overlay and stats are downstream of its decisions.

flowchart LR
    subgraph UI["User surface"]
        Tray["Tray icon + menu"]
        CLI["entracte CLI"]
        SettingsUI["Settings UI<br/>(React)"]
        Overlay["Break overlay<br/>(React)"]
        SysNotification["System notification"]
    end

    subgraph Backend["Rust / Tauri backend"]
        IPC["ipc.rs<br/>CLI ↔ app bridge"]
        Scheduler["scheduler/<br/>tick loop"]
        Hooks["Native hooks<br/>DnD · camera · idle · session lock"]
    end

    subgraph Stores["On-disk state"]
        Config[("settings.json<br/>profiles + settings")]
        Stats[("events.jsonl<br/>break history")]
        Pause[("pause.json")]
    end

    CLI -->|subcommands| IPC
    Tray -->|menu actions| Scheduler
    IPC --> Scheduler
    SettingsUI <-->|tauri invoke| Scheduler
    Hooks -->|suppress signals| Scheduler
    Scheduler -->|fires break| Overlay
    Scheduler -->|notify-only mode| SysNotification
    Scheduler <--> Config
    Scheduler --> Stats
    Scheduler <--> Pause
Loading

Platform support matrix, scheduler internals, and OS-specific quirks are documented in .github/AGENTS.md.

Development

npm install
npm run tauri dev     # full app, hot reload on TS + Rust
npm test              # vitest, frontend unit tests
npm run audit:a11y    # build + headless Chromium + axe-core on every tab × light/dark
cargo test --manifest-path src-tauri/Cargo.toml --lib

The a11y audit (scripts/audit-a11y.mjs) builds dist/, serves it via vite preview, drives Chromium through Puppeteer with a tiny __TAURI_INTERNALS__ shim so the React tree renders normally, then runs axe-core on every tab in both prefers-color-scheme modes. It runs on every CI build via .github/workflows/ci.yml and exits non-zero on any WCAG 2.1 AA violation.

Platform support matrix, scheduler internals, and OS-specific quirks are documented in .github/AGENTS.md.

Updates

Updates ship via tauri-plugin-updater against GitHub Releases. The About tab calls check_for_update, which delegates to the plugin: it fetches the signed latest.json manifest at releases/latest/download/latest.json, verifies the bundled signature against the public key pinned in tauri.conf.json, and reports whether a newer version is announced. macOS (Apple-signed + Tauri-signed), Linux AppImages (Tauri-signed), and Windows .msi (Tauri-signed) are all in latest.json. The check is manual — clicking Check for updates opens the release page in your browser; no automatic check on app start, no silent download_and_install. .deb / .rpm users update through their system package manager and are deliberately outside the updater flow.

Beta caveat. releases/latest only resolves to stable releases. While we're on the 0.0.X beta line (no stable yet), the in-app Check for updates returns no update available even when a newer beta has shipped. Beta-to-beta upgrades are manual — watch the Releases page or brew upgrade --cask entracte if you installed via the tap. Once 0.1.0 ships and is published as a non-prerelease, the in-app check starts working for everyone.

Windows specifically: until SignPath Foundation approves the project, the .msi is unsigned-via-Authenticode and SmartScreen warns every install. The About tab calls this out next to the "Open release page" link so users know to click More info → Run anyway.

Updater signing key. The pinned public key in src-tauri/tauri.conf.json (plugins.updater.pubkey) is the trust root every installed copy uses to verify the latest.json manifest. Its matching private key lives in two GitHub repo secrets — TAURI_SIGNING_PRIVATE_KEY (base64 contents of the key file) and TAURI_SIGNING_PRIVATE_KEY_PASSWORD (passphrase) — both wired into the build-unix job in .github/workflows/release.yml. The release workflow signs each macOS .app.tar.gz with that key and composes the latest.json manifest from both arches in the publish-updater-manifest job; a pre-flight verify-updater-pubkey job refuses any tag whose pubkey is still the bring-up placeholder.

Rotating the key breaks auto-update for every installed copy on the old pubkey — they can't validate signatures from the new one and silently fall behind. Rotate only when you have a path to manual reinstall for affected users (e.g. a security incident). To rotate: tauri signer generate -w ~/.tauri/entracte.key, paste the new public key into tauri.conf.json, update both TAURI_SIGNING_* GitHub secrets, ship a release that users must install manually, then any later release will auto-update normally.

Contributing

Bug reports, ideas, and patches are all welcome. Start with CONTRIBUTING.md for the setup, test, and PR workflow. Participation is governed by the Code of Conduct, which — among the usual things — requires a real human reviewer in the loop on every contribution.

Status

Functional and usable day-to-day on macOS. Windows and Linux build and run; some detection features (Linux DnD, Wayland idle) are still gapped — see AGENTS.md.

Settings persist to a JSON file in the OS app-config dir:

  • macOS~/Library/Application Support/io.drmowinckels.entracte/
  • Windows%APPDATA%\io.drmowinckels.entracte\
  • Linux~/.config/io.drmowinckels.entracte/