A fast CLI for checking website and domain health.
Status: Go rewrite complete (v0.16.1)
Quick Start
site-health example.com site-health --verbose example.com site-health --mail example.com site-health --whois example.com site-health --skip-mail example.com site-health --mail-checks spf example.com site-health --skip-redirect example.com site-health --format json example.com site-health --doctor site-health --init-config site-health web site-health web --port 8081
Features
Zero external dependencies — stdlib only:
- Domain registration expiry
- Registrar lookup
- Optional verbose output for troubleshooting
- DNS resolution (A, AAAA, CNAME)
- TCP connectivity (80/443)
- HTTP/HTTPS availability
- Redirect and canonical host validation
- SSL certificate validation
- Response time measurement
- HTML content validation
- Common server/PHP/WordPress error detection
- Parked domain detection
- Final summary with failure and warning counts
- MX record lookup, including Null MX recognition
- SPF TXT record validation
- DMARC TXT record validation
- Mail checks skippable in site mode with
--skip-mail - Individual mail checks selectable with
--mail-checksand--skip-mail-checks - WHOIS-only mode with
--whoisfor domain registration checks without HTTP probes - Optional
/llms.txtavailability check (skippable with--skip-llms-txt) - Canonical redirect check skippable with
--skip-redirect - Machine-readable JSON output for automation and monitoring
- Config file and environment variables for default flags
- Self-diagnostic
--doctormode for the binary and local environment - Local web UI for project-based checks and session history (
site-health web)
Usage
Run the full website/domain health check. By default, output is a concise dashboard:
Example:
Site Health Check
Domain: example.com
Expected Hosts: example.com
SITE HEALTH
───────────
● example.com
DNS OK
HTTPS OK
SSL 81 days
Domain Reg 757 days (14 Sep 2028)
Redirect OK
Response 184 ms
Mail OK
Status: HEALTHY
When a forwarded or explicit canonical URL matters, the dashboard includes it:
Site Health Check
Domain: example.com
Expected Hosts: example.org
SITE HEALTH
───────────
● example.com
DNS OK
HTTPS OK
SSL 81 days
Domain Reg 757 days (14 Sep 2028)
Redirect OK
Response 184 ms
Mail OK
Status: HEALTHY
Show detailed troubleshooting diagnostics instead of the dashboard:
site-health --verbose example.com
Run only mail-related DNS checks:
site-health --mail example.com
Mail mode checks only:
- MX
- SPF
- DMARC
Example:
MAIL HEALTH
───────────
● example.com
MX OK
SPF OK
DMARC WARN
Status: WARNING
Show detailed mail diagnostics:
site-health --mail --verbose example.com
Run only WHOIS / domain-registration checks:
site-health --whois example.com
WHOIS mode checks only:
- Domain registration expiry
- Registrar
Example:
WHOIS / Domain Registration
─────────────────────────
● example.com
Domain Reg 350 days (13 Aug 2027)
Registrar RESERVED-Internet Assigned Numbers Authority
Status: HEALTHY
Show detailed WHOIS diagnostics:
site-health --whois --verbose example.com
Run only selected mail checks:
site-health --mail-checks spf example.com site-health --mail-checks mx,dmarc example.com site-health --mail --mail-checks spf example.com
Skip selected mail checks:
site-health --skip-mail-checks spf example.com site-health --mail --skip-mail-checks spf example.com
The supported mail check names are mx, spf, and dmarc. --mail-checks and --skip-mail-checks filter the mail portion of the current run. Use them with --mail for mail-only output, or without --mail for a full site health run with filtered mail checks. Use --skip-mail when you want a full site health run without mail checks.
Skip mail-related DNS checks in a full site health run:
site-health --skip-mail example.com
This skips MX, SPF, and DMARC checks when mail health is outside the monitoring scope. For domains you control that deliberately do not send or receive mail, explicit no-mail DNS policy is still preferred: Null MX, SPF -all, and DMARC p=reject.
Skip the optional /llms.txt check:
site-health --skip-llms-txt example.com
Skip the canonical redirect check when the site intentionally serves the same content from multiple URL variants (for example, both https://example.com and https://www.example.com):
site-health --skip-redirect example.com
This keeps HTTPS, response-time, and SSL checks running, but does not enforce a single canonical URL. Use it for domains where redirecting every variant to one URL is not desired.
Forwarded domains are detected automatically when the final URL is unambiguous:
To strictly require a specific final host, provide it explicitly:
site-health --expected-hosts example.org example.com
When a site intentionally serves the same content from multiple hosts (for example, both https://example.com and https://www.example.com), pass them as a comma-separated list. The singular --expected-host is also accepted as an alias:
site-health --expected-hosts example.com,www.example.com example.com
Output a machine-readable JSON document instead of the dashboard (useful for scripts, CI, and monitoring). --verbose output is suppressed in JSON mode; the same exit codes apply (0 healthy, 1 issues found):
site-health --format json example.com
Example:
{
"tool": "site-health",
"version": "0.16.1",
"domain": "example.com",
"mode": "site",
"expected_hosts": ["example.com"],
"forwarding": {
"auto_detected": false,
"ambiguous": false,
"candidates": []
},
"checks": {
"dns": { "status": "OK", "a": ["104.20.23.154"], "aaaa": [] },
"https": { "status": "OK" },
"ssl": { "status": "OK", "days_remaining": 81, "subject": "CN=example.com" },
"redirect": { "status": "OK" },
"response": { "status": "OK", "ms": 184 },
"domain_registration": {
"status": "OK",
"registrar": "MarkMonitor Inc.",
"expires_at": "2028-09-14T04:00:00Z",
"days_remaining": 757
},
"mail": {
"status": "OK",
"mx": { "status": "OK", "records": ["0 ."] },
"spf": { "status": "OK", "records": ["v=spf1 -all"] },
"dmarc": { "status": "OK", "records": ["v=DMARC1;p=reject"] }
}
},
"issues": [],
"summary": { "failures": 0, "warnings": 0, "status": "HEALTHY" }
}In mail-only mode, the checks object contains just the mail block and the top-level mode is "mail". In WHOIS-only mode, the checks object contains just the domain_registration block and the top-level mode is "whois". When mail checks are skipped with --skip-mail, the mail block is omitted. When individual mail checks are skipped with --mail-checks or --skip-mail-checks, only the enabled mail subchecks appear under checks.mail.
Run self-diagnostics for the binary and local environment. --doctor does not require a domain and checks the install path, detected installation method, current and latest versions, system time, config file, DNS resolution, outbound HTTPS, WHOIS connectivity, and mail DNS capabilities:
Example:
site-health doctor
──────────────────
Binary path: /opt/homebrew/bin/site-health
Install method: Homebrew
Current version: 0.16.1
Latest version: 0.16.1 (up to date)
Environment
───────────
System time: OK 2026-08-27T12:34:56Z
Config file: OK not configured
/Users/alice/.config/site-health/config.json
DNS resolution: OK example.com → 93.184.216.34
Outbound HTTPS: OK https://detectportal.firefox.com/success.txt → 200 (success)
WHOIS lookup: OK whois.iana.org:43 reachable
Mail DNS (MX): OK 1 record(s)
Mail DNS (SPF): OK record found
Mail DNS (DMARC): OK record found
Status: HEALTHY
The latest-version check uses the GitHub Releases API. If the network is unavailable or the API rate-limit is exceeded, the check reports the error gracefully without failing the whole command.
Web UI
Run a local web interface for managing projects, domains, and check history in the browser:
The UI opens at http://localhost:8080 by default. Use --port to choose a different port:
site-health web --port 8081
Web UI features
- Projects: organize checks into separate projects, each with its own domain list and session history.
- Run checks: enter domains and run health checks with optional flags such as Skip redirect check.
- Results table: see the latest status for each domain plus a trend of the last 5 checks.
- Issue details: click any domain row to expand the issue list (FAIL, WARN, INFO).
- Session history: every run is saved as a session; clear history with Clear history.
Data is stored locally in the platform-specific user config directory (e.g. ~/.config/site-health/web on Linux or ~/Library/Application Support/site-health/web on macOS).
Configuration
Set default behavior in a config file so you do not have to repeat flags for every run. The default config path follows the XDG Base Directory Specification:
$XDG_CONFIG_HOME/site-health/config.jsonIf XDG_CONFIG_HOME is unset, it falls back to:
~/.config/site-health/config.jsonUse --config <path> to load a different file. A missing config file is silently ignored; a malformed file exits with an error.
Generate a starter config file with all supported settings:
site-health --init-config
This writes the sample file to the default config path. Use --config <path> to write it elsewhere. It will not overwrite an existing file.
Example config:
{
"verbose": false,
"skip_redirect": true,
"skip_mail": false,
"skip_llms_txt": false,
"whois": false,
"format": "json",
"expected_hosts": [],
"mail_checks": ["mx", "spf"],
"skip_mail_checks": []
}Supported settings:
| Setting | Type | Matching flag |
|---|---|---|
verbose |
boolean | --verbose |
skip_redirect |
boolean | --skip-redirect |
skip_mail |
boolean | --skip-mail |
skip_llms_txt |
boolean | --skip-llms-txt |
whois |
boolean | --whois |
format |
string | --format |
expected_hosts |
string[] | --expected-hosts |
mail_checks |
string[] | --mail-checks |
skip_mail_checks |
string[] | --skip-mail-checks |
The same options can be set via environment variables:
export SITE_HEALTH_FORMAT=json export SITE_HEALTH_SKIP_REDIRECT=true export SITE_HEALTH_EXPECTED_HOSTS=example.com,www.example.com export SITE_HEALTH_MAIL_CHECKS=mx,spf
Precedence, from highest to lowest:
- Explicit CLI flags
- Environment variables (
SITE_HEALTH_*) - Config file values
- Built-in defaults
When --verbose is enabled and a config file is loaded, the path is printed to stderr so it is clear where defaults are coming from.
Installation
Homebrew
Preferred installation method on macOS:
brew install atillalab/tap/site-health
Install with go install
go install github.com/atillalab/site-health@latest
Pre-built binary
Download the latest release for your platform from GitHub Releases.
Build from source
Clone the repository and build:
git clone https://github.com/atillalab/site-health.git cd site-health go build -o site-health .
The resulting binary has zero external dependencies.
Exit codes
0— healthy, no failures1— one or more checks failed2— usage error (missing domain, invalid flag, etc.)
Development
Run tests
Run tests with readable, per-test output:
Build
go build -o site-health .Vet
License
MIT