Skip to content
hostsctl — manage /etc/hosts from a YAML config: groups, zone files, remote blocklists, backups

hostsctl

One YAML config. Everything else in /etc/hosts stays exactly where you left it.
  1. Install it and create a config:

    Terminal window
    brew install jtprogru/tap/hostsctl
    hostsctl init
  2. Add an entry — it goes into the config, not into /etc/hosts yet:

    Terminal window
    hostsctl add 127.0.0.1 k8s.orb.local --comment orbstack
  3. Look before you write. diff needs no root and changes nothing:

    Terminal window
    hostsctl diff
  4. Apply it:

    Terminal window
    sudo hostsctl apply

The result in /etc/hosts:

127.0.0.1 localhost ← system lines, untouched
255.255.255.255 broadcasthost
# >>> hostsctl begin >>>
# generated by hostsctl 2026-08-11 17:15
# source: /Users/you/.config/hostsctl/config.yaml — edit that, not this block
# --- local — Local development ---
127.0.0.1 k8s.orb.local # orbstack
# <<< hostsctl end <<<

Your file stays your file

Entries are rendered into a block between markers. System lines, other tools’ blocks and hand edits are carried over byte for byte — verified by tests that run against a copy of a real /etc/hosts.

Groups you can switch off

A group is enabled or disabled as a whole. Turn a blocklist off for an afternoon, turn it back on, and nothing in the config was lost in between.

Config split across files

Keep everything in one config.yaml, or spread it over zone files — plain hosts syntax or YAML. Edits made through the CLI go back to the file the group came from.

Honest about failure

Atomic writes with fsync and rename, a snapshot before every write, a refusal to produce a file without 127.0.0.1 localhost, and an exit code for every way a run can go wrong.

New here? Read the two pages under Start here, then come back for whichever guide matches what you are trying to do.

hostsctl does not resolve names — /etc/hosts does, with all of its limits. Wildcards, ports and paths in a hostname do not work there, so hostsctl check rejects them instead of letting the system ignore them silently. For wildcard domains you want dnsmasq or /etc/resolver/.