A simple, no-nonsense website blocker for macOS — with lockable focus sessions you can't quit early.
focus blocks sites at the OS level by editing /etc/hosts, so they're blocked in every browser at once. There's no extension to disable, no app to force-quit. When you start a locked session, a root background daemon re-applies the block every few seconds and survives reboots — so hand-editing your hosts file (or deleting the tool) won't get you back on Instagram until the timer runs out.
It comes in two flavors that share the same state:
focus— a small, dependency-free Bash CLI.focus-tui— a full-screen terminal UI (Python + Textual) with a live toggle list.
Both read the same roster (~/.focus-sites) and edit the same managed block in /etc/hosts, so you can mix and match freely.
Browser extensions are trivial to disable the moment you feel the itch. focus is different:
- Every browser, at once. Blocking happens at the DNS/hosts layer, below the browser.
- Commitment mode.
focus lock 90mstarts a session with no early unlock. A root-owned daemon re-applies the block every 5 seconds, reverts manual edits automatically, and survives reboots. You can extend a lock, never shorten it. - Clean. Everything lives inside a clearly-marked block in
/etc/hosts; the rest of your file is never touched.
git clone https://github.com/ponchodelosrios98/screen-block.git
cd screen-block
chmod +x focus focus-tuiOptionally put them on your PATH:
sudo cp focus /usr/local/bin/focus- macOS (uses
/etc/hosts+mDNSResponder). focus— Bash only, no dependencies.focus-tui—uv(the script declares its own deps and runs itself). Or run it with any Python ≥ 3.10 that hastextual>=0.80installed.
Editing /etc/hosts requires sudo; you'll be prompted for your password.
./focus block instagram.com twitter.com # block one or more sites
./focus unblock instagram.com # unblock specific sites
./focus on # re-block everything on your list
./focus off # unblock everything (break time)
./focus list # show what's currently blocked
./focus lock 90m # LOCK your list for a set time
./focus status # show lock state + time leftYour block list lives in ~/.focus-sites, so on/off remember it between sessions.
./focus lock 90m # lock for 90 minutes — no early unlock
./focus lock 2h # or 2 hours
./focus lock 1h30m # combined
./focus lock 45 # a bare number means minutesWhile a lock is active:
offandunblockare refused.- You can
blockmore sites (they get folded into the enforced set), but never remove them. focus lock <longer>extends the session; a shorter or equal duration is rejected.- When the timer expires, the daemon unblocks everything and removes itself.
Durations accept s, m, h, d (e.g. 90m, 2h, 1h30m), or a bare number for minutes.
./focus-tuiA live table of your sites, each individually ● blocked or ○ allowed. Toggling flips it in /etc/hosts immediately.
| Key | Action |
|---|---|
space |
toggle the selected site |
a |
add a site |
d |
delete a site |
l |
lock a focus session |
o |
block all |
f |
allow all |
r |
refresh |
q |
quit |
The TUI authenticates sudo once up front (a normal password prompt before the UI opens), then reuses the cached credential.
-
The block. Both tools rewrite a single region of
/etc/hostsdelimited by:# >>> focus block >>> 127.0.0.1 instagram.com 127.0.0.1 www.instagram.com # <<< focus block <<<Anything outside those markers is left untouched. After each change, the DNS cache is flushed (
dscacheutil -flushcache+killall -HUP mDNSResponder). -
The lock.
focus lockinstalls a root LaunchDaemon (com.focus.enforcer) plus a small enforcer script and a lock file under/Library/Application Support/focus/. The daemon loops every 5 seconds: while the lock file's expiry epoch is in the future it re-applies the block; once it expires it unblocks everything, removes the daemon, plist and lock file, and exits.KeepAlive+RunAtLoadmean it comes back after a reboot.
Because the enforcer, plist and lock file are root-owned, the tool can't casually clear them — that's the whole point.
Nothing is installed globally unless you copied focus to /usr/local/bin or ran a lock. To remove a stuck locked session (only possible with sudo, by design), wait for the timer — or, if you truly must:
sudo launchctl bootout system/com.focus.enforcer
sudo rm -f /Library/LaunchDaemons/com.focus.enforcer.plist \
/usr/local/libexec/focus-enforcer
sudo rm -rf "/Library/Application Support/focus"Then remove the managed block from /etc/hosts (everything between the two focus block markers).
MIT — do whatever you want. Contributions welcome.