README.md

FocusD #

Deep focus media control for Linux. Block distractions, track time, build habits.

Features #

  • Mode-based blocking: Switch between work, reading, learning, writing, gaming, and offline modes
  • Three-layer protection: DNS (hosts file), network (iptables), and process-level blocking
  • Browser extension: Manifest V3 extension with real-time status, mode selector, and blocked domains list
  • Schedule automation: Time-based mode switching with day-of-week support
  • Pomodoro timer: Configurable work/break cycles
  • Time tracking: Log time spent in each mode
  • Desktop notifications: Alerts for mode changes
  • Weekly media curation: Curate 5 videos/articles per week with Cal Newport's Friday review
  • Dream app sync: Sync timeblocks to blocks.adjarnor.dev

Installation #

Build from source #

# Requires Zig 0.17+
git clone <repo-url> focusd
cd focusd
zig build -Doptimize=ReleaseSafe

Install #

# Copy binary
cp zig-out/bin/focusd ~/.local/bin/

# Install browser extension
# 1. Open chrome://extensions/
# 2. Enable Developer mode
# 3. Click "Load unpacked"
# 4. Select the extension/ directory

Enable systemd service (optional) #

systemctl --user daemon-reload
systemctl --user enable focusd.service
systemctl --user start focusd.service

Quick Start #

# Start daemon (requires root for blocking)
sudo focusd daemon &

# Enter work mode
focusd mode work

# Check status
focusd status

# Exit mode
focusd mode exit

CLI Commands #

Command Description
focusd mode <name> Enter a mode (work, reading, learning, writing, gaming, offline)
focusd mode exit Exit current mode
focusd mode list List available modes
focusd status Show current status and blocked domains
focusd schedule list Show today's schedule
focusd schedule add <time> <mode> Add schedule entry
focusd schedule export <date> Export to Waybar schedule.yaml
focusd media list Show weekly media plan
focusd media add <type> <title> [options] Add media to weekly plan
focusd media done <index> Mark media as consumed
focusd media plan Show Friday weekly review guide
focusd media stats Show consumption statistics
focusd pomodoro start Start pomodoro timer
focusd pomodoro status Show pomodoro status
focusd sync push [date] Sync timeblocks to blocks.adjarnor.dev
focusd sync pull [date] Pull timeblocks from blocks.adjarnor.dev
focusd sync status Show sync status
focusd config show Show configuration
focusd config set <key> <value> Set config value

Browser Extension #

The extension communicates with the daemon via HTTP (port 8082) and provides:

  • Real-time status: Daemon connection, current mode, timer
  • Mode selector: Click to switch modes instantly
  • Blocked domains list: See all currently blocked sites
  • Blocking toggle: Enable/disable extension blocking

Weekly Media Curation #

Curate your media consumption with Cal Newport's Friday review method:

# Add videos to your weekly plan
focusd media add video "Zig Deep Dive" "https://youtube.com/watch?v=..." ThePrimeagen 45
focusd media add video "Software Engineering at Google" "https://..." CaseyMuratori 60

# Add articles and newsletters
focusd media add article "Deep Work Guide" "https://calnewport.com/..." "Cal Newport"
focusd media add newsletter "The Pragmatic Engineer"

# View your weekly plan
focusd media list

# Mark items as consumed
focusd media done 0

# Check your progress
focusd media stats

# Friday weekly review
focusd media plan

Media is saved to ~/.config/focusd/media.yaml and persists across daemon restarts.

Dream App Sync #

Sync your FocusD schedule to blocks.adjarnor.dev for visual timeblock planning:

# Push today's schedule to dream app
focusd sync push

# Push specific date
focusd sync push 2026-06-07

# Pull timeblocks from dream app
focusd sync pull 2026-06-07

# Check sync status
focusd sync status

The daemon automatically syncs your schedule to the dream app on startup.

Configuration #

Config file: ~/.config/focusd/config.toml

hostnames_file = "/etc/hosts"
pomodoro_work_minutes = 25
pomodoro_break_minutes = 5
pomodoro_sessions_before_long = 4
pomodoro_long_break_minutes = 15

Domain Blocklists #

Located in config/blocking/:

  • social_media.txt - Facebook, Twitter, Instagram, Reddit, TikTok, etc.
  • entertainment.txt - YouTube, Netflix, Twitch, Discord, Spotify, etc.
  • news.txt - CNN, BBC, NYT, Washington Post, etc.
  • productivity.txt - Combined list of productivity killers
  • communication.txt - Slack, Discord, Telegram, WhatsApp, etc.
  • shopping.txt - Amazon, eBay, Etsy, Walmart, etc.

How It Works #

  1. Daemon runs as root, manages blocking state
  2. CLI communicates with daemon via Unix socket IPC
  3. Browser extension polls daemon HTTP API for status
  4. Blocking layers work together:
    • /etc/hosts redirects domains to localhost (DNS blocking)
    • iptables drops network packets (network blocking)
    • Process monitor kills blocked apps (app blocking)
    • Browser extension uses declarativeNetRequest (browser blocking)

Learning #

See LEARNING.md and docs/learn/ for deep-dive documentation on:

  • Zig memory management and allocators
  • Unix domain sockets and IPC
  • Linux signal handling
  • Non-blocking I/O with poll()
  • Threads and concurrency
  • TCP networking
  • File system operations
  • TOML parsing
  • Process management
  • Systemd services
  • Browser extension architecture (Manifest V3)
  • iptables network blocking

License #

MIT