Skip to main content

lockin

CI PyPI

Block distracting websites on Linux. No proxy, no browser extension, no MITM certificate.

lockin writes blocked domains to /etc/hosts and rejects QUIC/HTTP3 (UDP 443) via nftables or iptables for every destination on the machine. A systemd watchdog re-applies the block about once a minute.

Quick start

Linux with systemd. Run lockin as yourself. The tool calls sudo for /etc/hosts and firewall rules. Do not run sudo lockin.

uv tool install lockin-blocker
lockin start --for 2h
lockin status

Browsers close on start. Save your work first. Reopen them after start so they pick up DoH-disabled policies. Default mode is hardcore. lockin stop is refused. Use lockin unlock --now to end early, or lockin start --soft if you want lockin stop to work.

The command is lockin. The PyPI package is lockin-blocker.

Install

Python 3.11+, systemd, and nftables (or iptables).

uv tool install lockin-blocker          # recommended
pip install lockin-blocker
./install.sh                            # same as uv/pip from PyPI, not a local checkout
lockin update                           # upgrade the CLI package

From a git clone, use ./scripts/dev-install instead of install.sh.

Read CHANGELOG when you upgrade.

Existing users

The first lockin start or lockin list copies packaged rules.yaml to ~/.config/lockin/rules.yaml once. Later upgrades do not merge new defaults into that file. Edit your copy after reading the changelog.

If you have more than one rule and no default key, pass --rule every time, or add default: social, so lockin start --for 2h works.

Usage

lockin start --for 2h                     Start with the default rule
lockin start --rule social --for 30m      Named blocklist
lockin start --rule social,news --for 2h  Stack blocklists
lockin start --until 17:00                Block until a clock time
lockin start --soft --for 30m             Allow lockin stop
lockin status                             Remaining time (wall clock)
lockin status --json                      Machine-readable status
lockin extend 30                          Add 30 minutes
lockin unlock 30                          Early unlock after a cooldown (default 30)
lockin unlock --now                       End now
lockin stop                               End block (soft sessions only)
lockin list                               List rules
lockin doctor                             Installation health
lockin cleanup                            Strip leftovers (ends a live session)
lockin uninstall                          Remove system files
lockin update                             Upgrade the CLI package

Durations are 30m, 2h, 1h30m. Times are 17:00 or 9:30pm.

lockin status --json

When idle: {"active": false}.

When live:

Key Meaning
active true
rule_name Active rule(s), comma-joined if stacked
end ISO end time (wall clock)
remaining_seconds Seconds until end
hosts "active" or "missing"
hosts_count Domains in /etc/hosts
firewall "active", "inactive", or "unknown"
block_type Legacy "blacklist". Every rule is a blocklist.

Expiry and teardown

lockin status is wall clock. Hosts, firewall, and policies come down on the next watchdog tick (about 60s after end), not at the exact second. After a reboot, QUIC can work until the first tick.

lockin update upgrades the CLI only. The copy under /usr/local/lib/lockin/pkg refreshes on the next lockin start.

Notifications

Expiry, soft stop, and unlock --now try notify-send. If it is missing, the block still ends.

Rules

Edit ~/.config/lockin/rules.yaml. Every rule is a blocklist. Listed hostnames go into /etc/hosts. lockin expands a few common subdomains and aliases. No globs. No allowlist. A legacy whitelists: key is still loaded as blocklists.

default: social

blacklists:
  social:
    - twitter.com
    - reddit.com

Firewall backends

nftables is the one lockin status can verify. iptables still rejects UDP 443, but firewall in status JSON stays "unknown" because probe only lists the nft table.

Browser policies

lockin writes enterprise policies that turn off DNS-over-HTTPS. Snap and Flatpak Firefox often ignore /etc/firefox/policies. Use distro Firefox, or close and reopen after policies land. Browsers are killed on start and at expiry. You reopen them.

Troubleshooting

Hosts missing during a live block. Wait about a minute for the watchdog. lockin cleanup ends the session.

Sites still blocked after expiry. Wait for the next tick, then lockin cleanup if leftovers remain.

lockin stop refused. Hardcore mode. Use lockin unlock --now or wait.

lockin doctor fails. Fix the failed checks. Use lockin cleanup for leftovers when no session should be running.

Uninstall

lockin uninstall
uv tool uninstall lockin-blocker

License

MIT

Release files for lockin-blocker 2026.8.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lockin-blocker 2026.8.2
File Size Uploaded
lockin_blocker-2026.8.2.tar.gz 34.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lockin-blocker 2026.8.2
File Interpreter ABI Platform
lockin_blocker-2026.8.2-py3-none-any.whl Python 3 none any Details

Total release size: 59.7 kB

Release files / lockin_blocker-2026.8.2.tar.gz

Download URL lockin_blocker-2026.8.2.tar.gz
Size 34.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f55601a7d30fd8957e35567b96d123197a73d86a24c67e15a95a861ca8152eb8
BLAKE2b-256 checksum
How to use checksums
515e5f8a330c11cfe54f3d484d1b5539cad2d130861e5e294fcbde193d101676
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / lockin_blocker-2026.8.2-py3-none-any.whl

Download URL lockin_blocker-2026.8.2-py3-none-any.whl
Size 25.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af30c7f4a4748c68d08f16259aa67ea10379d66fa873199f697065509c1d2c80
BLAKE2b-256 checksum
How to use checksums
1f898e289cb2d8d7013a39b18986e1569ced49ff3115b77741b302f38a3d5a86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

2026.8.2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page