How to Block Distracting Websites on Your Laptop
"What exactly did I do the last 30 minutes?"
I'm sure you've been there, asking that same question, staring blankly into your computer screen.
I've written about how I'm working to minimized distraction. For me, a big component of that is blocking distraction on the device I spend the most time: my laptop.
Here's what I'm looking to do:Automatically block distracting websites, but allow an easy way to temporarily unblock them. Example: I want to block Amazon by default, but sometimes I want to jump on and buy something quickly. I don't want to have to manage a schedule. Creating exceptions to schedules and then remembering to re-enable the schedule never works well. I don't want crappy software that is going to slow down my computer or cause weird networking issues. I want it to be hard, but not impossible, to disable. One or two clicks to disable is too easy. The Easy Way
For most folks, you'll want to use one of the couple apps out there that do this for you. Here are some that I've tried:RescueTime Focus Freedom Cold Turkey
Focus is the best option I've found. It's a simple and nicely designed app. Check it out!The Hard Way
If you like tinkering with your system setup, read on.
The pre-built applications always seemed to do strange things to the networking stack on my computer or hog lots of resources (GBs of memory in some cases). This is probably due to how much I customize my computer.
Also, I found that if I disabled my "blocking schedule" it didn't automatically re-enable. I would then find myself down the Twitter rabbit-hole with 20m wasted. That was a big issue for me.
Eventually, I got frustrated and built a solution which works surprisingly well:Maintain a simple file listing every host is distracting. Run a script every time the computer wakes up. I used sleepwatcher for this. The script consumes a list of distracting hosts and adds them to /etc/hosts with a reference to a non-existent server. After trying a couple of tools, a node package hostile worked best. 1. Build a List of Distracting Websites
First, create a simple text file. Back it up on Gist or somewhere where it won't be lost. Version tracking the file allows you to view a history of what websites are distracting over time.
I keep this file in my dotfiles repo. Here's what it looks like:facebook.com twitter.com smile.amazon.com
(yes, that's Amazon Smile since I have a browser extension to redirect me there)
Then you'll want to clean the file, add www variants of each host, and point them to 127.0.0.1:sed '/^$/d' ./distracting_websites.txt | sed $'s/\(.*\)/127.0.0.1 \\1\\\n127.0.0.1 www.\\1/' > ~/distracting_sites.txt
I put this script in the setup process of my dotfiles for easy ad-hoc execution (you'll want to continually update your distracting_websites.txt as new things distract you).2. Block all Distracting Websites with a Script
Below is a script that is run every time I wake my computer. Here's what it does:Updates /etc/hosts using hostile and the distracting_sites.txt file Clears system DNS cache Clears Safari cache, which seems to have its own DNS cache. Chrome does not. # asdf is a node version management tool I use. Your exact execution paths will probably be different /Users/mike/.asdf/installs/nodejs/12.14.1/bin/node \ /Users/mike/.asdf/installs/nodejs/12.14.1/.npm/bin/hostile \ load /Users/mike/distracting_sites.txt # clear system cache # https://apple.stackexchange.com/questions/303110/flush-cache-of-dns-on-macos-sierra-high-sierra/303119#303119 sudo killall -HUP mDNSResponder # clear safari cache osascript << EOF tell application "Safari" activate end tell tell application "System Events" tell process "Safari" tell menu bar 1 to tell menu bar item "Develop" to tell menu 1 to tell menu item "Empty Caches" to click end tell end tell EOF
You can test this script by running it with sudo:sudo /usr/local/sbin/sleepwatcher --verbose --wakeup .wakeup 3. Run Website Blocking Script When your Computer Wakes from Sleep
First, install sleepwatcher:brew install sleepwatcher
Then, you'll want to find the location of the plist file which starts up sleepwatcher as a daemon process:$ brew services Name Status User Plist sleepwatcher started root /Library/LaunchDaemons/homebrew.mxcl.sleepwatcher.plist
You'll want to edit this plist:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>homebrew.mxcl.sleepwatcher</string> <key>ProgramArguments</key> <array> <string>/usr/local/sbin/sleepwatcher</string> <string>-V</string> <string>-w /Users/mike/.wakeup</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/usr/local/var/log/sleepwatcher.log</string> <key>StandardErrorPath</key> <string>/usr/local/var/log/sleepwatcher.log</string> </dict> </plist>
Then, you'll want to ensure the process runs as root and the script you created is executable:chmod + /Users/mike/.wakeup brew services stop sleepwatcher sudo brew services start sleepwatcher
And... you're done! Depending on your OS configuration you may need to grant some permissions on first run.
Was this overkill? Definitely. Does it prevent me from wasting any time on distracting websites? Absolutely.