Skip to content

krabhi1/focus

Repository files navigation

Focus

Focus is a productivity tool designed to keep your computer usage intentional. It helps you stay on track and manage your time effectively, ensuring every session at your desk has a clear purpose rather than drifting into aimless browsing.

The system operates via a background daemon (focusd) that handles time tracking, while a simple CLI (focus) provides the interface for managing your work.

Project site: focus.krabhi.me

Current runtime model:

  • internal/app/runtime.go orchestrates runtime flow, deadlines, and side effects.
  • internal/domain owns phase transitions (idle, active, break, pending_cooldown, cooldown).
  • internal/scheduler owns deadline execution.
  • internal/storage owns config, presets, history, and socket helpers.

Rules

  • Intentional Use: Focus gives you a 2-minute grace period to use your computer without an active task. Beyond that, the system will warn you before locking the screen or putting the computer to sleep.
  • One Thing at a Time: Only one task can be active at once. When a task finishes, the daemon enforces a cooldown before you can start the next one. Cooldown scales by task length.
  • Work Modes:
    • short (15 min): No in-task break.
    • medium (30 min): No in-task break.
    • long (60 min): Break starts at 25 minutes for 5 minutes.
    • deep (90 min): Break starts at 45 minutes for 10 minutes.
  • Post-Task Action:
    • long tasks lock the screen at cooldown start by default.
    • deep tasks suspend the machine at cooldown start by default.
    • Override with task.long_end_action or task.deep_end_action if you want the opposite behavior.
  • Break Enforcement (long/deep only):
    • You get a reminder 2 minutes before the break starts.
    • At break start, Focus locks the screen using the best available session/backend command.
    • If the screen is unlocked during break or cooldown, Focus warns once and relocks after the configured relock_delay.
  • Post-Task Cooldown: Cooldown starts only after task completion (not during the in-task break).
  • Sleep/Wake Tracking: Focus pauses active task timers when the machine sleeps and resumes them on wake.
  • Heads-up Notifications: You’ll receive a notification 5 minutes before a task ends, giving you time to wrap up your work gracefully.
  • Status Visibility: focus status shows cooldown state, active task remaining time, and break-specific details including relock countdown when applicable.

State Machine

flowchart TB
    Idle(["Idle"])
    Active(["Active"])
    Break(["Break"])
    Cooldown(["Cooldown"])
    Lock["Lock screen"]

    Idle -- focus start --> Active
    Active -- long/deep break time --> Break
    Break -- break ends --> Active

    Active -- task completes --> Cooldown
    Cooldown -- cooldown ends --> Idle

    Active -- cancel in grace period --> Idle

    Idle -- no task for 2m --> Lock
    Break -- unlock during break --> Lock
    Cooldown -- unlock during cooldown --> Lock
Loading

Idle means no task is running and no cooldown is active. Break only applies to long and deep tasks. If the user unlocks during break or cooldown, Focus relocks after relock_delay. Screen locking is an action, not a separate state.

System Requirements

For now this is only available in Linux. It depends on a systemd user session and the desktop tools below.

Runtime dependencies used by focusd:

  • loginctl or xdg-screensaver for screen lock
  • cinnamon-screensaver-command or gnome-screensaver-command for unlock, if your desktop exposes one
  • systemctl or loginctl for sleep/suspend on long and deep task cooldown start
  • notify-send for desktop notifications
  • paplay, pw-play, aplay, mpv, ffplay, cvlc, or mpg123 for task-ending sound (assets/task-ending.mp3)
  • focus-events helper binary (installed privately with focusd)

Environment-specific notes:

  • Lock and unlock are best-effort and depend on the desktop/session providing a supported command.
  • Sleep is best-effort and uses the first available suspend command for your session.
  • Sound playback is best-effort and uses the first available audio tool.
  • systemctl --user is needed only if you use the user service install path.

Runtime observability:

  • Set FOCUS_TRACE_FLOW=1 to log runtime flow actions and core events.

CLI output is colorized automatically in interactive terminals. Set NO_COLOR=1 or redirect output to disable colors.

Run

Build everything with:

make build

Run the daemon and client from the built binaries:

./dist/focusd
./dist/focus status
./dist/focus history

Useful Commands

  • focus status shows the current task, cooldown, or break state.
  • focus history --all shows every completed task in the persisted history file.
  • focus reload reloads daemon configuration from disk.
  • focus config <key> shows the current value and default.
  • focus config <key> <value> updates one config value and reloads the daemon.
  • focus config alert.repeat_count controls how many times the task-ending sound can play; 0 means no sound.
  • focus config task.long_end_action controls whether long tasks sleep or lock when cooldown starts.
  • focus config task.deep_end_action controls whether deep tasks sleep or lock when cooldown starts.
  • focus doctor prints dependency, socket, daemon IPC, and service health checks.
  • focus version prints the installed binary version.
  • focus update upgrades to the latest release.
  • focus update --version v0.1.4 upgrades to a specific release.
  • focus uninstall asks for confirmation three times before removing the installed binaries and user service.
  • systemctl --user status focusd.service checks whether the daemon service is running.

Avoid running go run cmd/focusd/main.go directly. Use the package path instead if you want to run from source:

go run ./cmd/focusd
go run ./cmd/focus status

Install (user systemd service)

Install latest release (GitHub):

curl -fsSL https://focus.krabhi.me/install.sh | sh

Install a specific version:

curl -fsSL https://focus.krabhi.me/install.sh | sh -s -- --version v0.1.0

Manual (recommended for audit): download install.sh, review it, then run it.

Install from local source checkout:

./scripts/install-local.sh

This installs:

  • focus to ~/.local/bin
  • focusd and focus-events to ~/.local/libexec/focus
  • sound assets to ~/.local/share/focus/assets
  • focusd.service to ~/.config/systemd/user/focusd.service

Manage service manually if needed:

systemctl --user daemon-reload
systemctl --user enable --now focusd.service
systemctl --user status focusd.service

Uninstall:

focus uninstall

For a custom install prefix:

focus uninstall --prefix /custom/prefix

Check installed version:

focus version

Update to the latest release:

focus update

Update to a specific release:

focus update --version v0.1.2

For custom installs:

focus update --prefix /custom/prefix

Note: release updates currently target linux/amd64, matching the published release assets.

Configuration

Focus can load runtime settings from JSON config.

Full reference:

Apply changes without restarting daemon:

focus reload

Optional install flags:

./scripts/install-local.sh --prefix /custom/prefix
./scripts/install-local.sh --no-build
./scripts/install-local.sh --no-systemd

For a source checkout, use:

./scripts/uninstall.sh

Current prebuilt release target: linux/amd64.

Manual Docs

Verify release publishing

After pushing a version tag, verify workflow + release assets:

make check-release VERSION=v0.1.0

For private repos, use a token with repo/actions read permissions:

GITHUB_TOKEN=your_token_here make check-release VERSION=v0.1.0

Release workflow

This repo has a tag-triggered GitHub Actions workflow at:

  • .github/workflows/release.yml

When a tag matching v* is pushed (example: v0.1.1), the workflow:

  1. Builds release artifacts via scripts/package-release.sh.
  2. Publishes a GitHub Release.
  3. Uploads focus_<tag>_linux_amd64.tar.gz.
  4. Uploads checksums_<tag>.txt.

Cut a release

git checkout main
git pull --ff-only
git tag v0.1.1
git push origin main
git push origin v0.1.1

Verify release

make check-release VERSION=v0.1.1

Verify installer against released tag

curl -fsSL https://focus.krabhi.me/install.sh | sh -s -- --version v0.1.1 --no-systemd

Notes

  • Current prebuilt target is linux/amd64.
  • If tag was pushed by mistake, delete it locally and remotely:
git tag -d v0.1.1
git push origin :refs/tags/v0.1.1

About

Focus is a productivity tool that helps you stay on track and use your computer time intentionally and purposefully.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors