A Go CLI for inspecting domain registration, DNS records, HTTP responses, and TLS certificates and protocol support.
- Domain Information - Query RDAP/WHOIS data for domain registration details
- TLS Certificate Inspection - Retrieve and analyze TLS certificate chains
- TLS Protocol and Cipher Probing - Check TLS 1.0–1.3 support and Go-supported TLS 1.0–1.2 cipher suites
- HTTP Response Analysis - Inspect status, repeated headers, redirects, and optional request timings
- DNS Lookups - Query common record types with custom IPv4 or IPv6 nameservers and TCP fallback
- Multiple Output Formats - Text and JSON output support
- Structured Logging - Built-in verbose mode for debugging
HTTP and TLS inspection skip certificate verification. Read Security and scan limitations before interpreting results.
The current source requires Go 1.26.0 or later, as specified in go.mod. Requirements for tagged releases may differ.
git clone https://github.com/flavioheleno/watchr.git
cd watchr
make build
./bin/watchr --helpThe binary is available in ./bin/watchr. Use that path directly, or place the binary on your PATH to run the watchr examples below. Without Make, build with:
go build -o ./bin/watchr ./cmd/watchrgo install github.com/flavioheleno/watchr/cmd/watchr@main@main installs the development branch. Older tags, including v1.0.3, declare the module as watchr rather than github.com/flavioheleno/watchr; @latest fails when it selects one of those tags. Use @main or build from source until a tag with the corrected module path is published, then use @latest for the latest tagged release.
Ensure GOBIN (or $(go env GOPATH)/bin when GOBIN is unset) is on your PATH.
The release workflow builds Linux binaries for amd64, arm64, ARMv7, and ARMv6, compresses them with UPX, and attaches them to GitHub Releases.
# Get domain registration information
watchr domain example.com
# Inspect TLS certificate chain
watchr tls example.com
# Fetch HTTP response details
watchr http https://example.com
# Query DNS records
watchr dns example.com
# Show help for a command
watchr tls --helpEach lookup command accepts exactly one positional argument. Use a domain name for domain and dns, a URL including http:// or https:// for http, and a hostname or IP address without a scheme or port for tls.
-f, --format- Output format:textorjson(default: text)-t, --timeout- Positive request timeout in seconds (default: 10)-v, --verbose- Enable verbose logging-h, --help- Show command help
Unsupported formats, nonpositive timeouts, and timeout values that overflow Go's duration range are rejected before network requests begin.
Results go to standard output; structured logs and errors go to standard error. JSON can therefore be redirected without mixing in log messages:
watchr domain -f json example.com > domain.jsonwatchr domain example.com
watchr domain --format json --verbose example.comQueries RDAP first, using IANA bootstrap discovery to locate the registration server. If RDAP fails, the command falls back to WHOIS. Cancellation stops the command without starting a WHOIS fallback.
-T, --type- Record type, defaultA; acceptsA,AAAA,MX,NS,CNAME,TXT,SOA,SRV,PTR, andCAA, case-insensitively-s, --server- Nameserver hostname or IP address, optionally with a port; default port is53
watchr dns --type MX example.com
watchr dns --type TXT --server 8.8.8.8 example.com
# Query a DNS server listening locally on a custom port
watchr dns --server 127.0.0.1:5353 example.com
watchr dns --server '[::1]:5353' --type AAAA example.com
# PTR queries require a reverse-DNS name, not a bare IP address
watchr dns --type PTR 1.0.0.127.in-addr.arpaBare IPv6 server addresses use port 53; bracket IPv6 addresses when supplying a custom port. Without --server, watchr uses the first nameserver in /etc/resolv.conf. If that configuration cannot be read or contains no servers, it warns and falls back to 8.8.8.8; use --server to avoid that public fallback.
Queries start over UDP and retry truncated replies over TCP within the same timeout. Non-success DNS response codes, including NXDOMAIN, SERVFAIL, and REFUSED, are errors. A successful response with no answers is not an error. TXT chunks within each record are joined into one value.
-L, --follow-redirects- Follow redirects; disabled by default--timings- Include DNS lookup, TCP connection, TLS handshake, server processing, content transfer, and total timings
watchr http https://example.com
watchr http --follow-redirects --timings https://example.com
watchr http -f json -L --timings https://example.com > response.jsonUses GET and reads and discards the response body; it does not print page content. Without --follow-redirects, a redirect's status and headers are returned directly. With redirects enabled, the result includes the final URL and redirect chain; the tenth redirect attempt is rejected.
The reported duration includes reading the response body. Timing phases may be zero when a phase does not occur, and their sum need not equal total duration.
-p, --port- TCP port, default443--scan-protocols- Probe TLS 1.0, 1.1, 1.2, and 1.3 support--scan-ciphers- Probe protocols and enumerate Go-supported TLS 1.0–1.2 cipher suites--full-scan- Run protocol and cipher probing with deprecated-protocol warnings
watchr tls --timeout 30 example.com
watchr tls --port 8443 example.com
watchr tls --scan-protocols example.com
watchr tls --scan-ciphers example.com
watchr tls --full-scan --format json example.com > tls-scan.jsonWithout scan flags, the command reports the negotiated protocol and cipher plus the server-supplied certificate chain, including subjects, issuers, validity dates, public-key algorithms and sizes, and DNS names. Scan flags select scan output instead of certificate output. Currently, --scan-ciphers and --full-scan perform the same protocol, cipher, and warning checks.
--timeout is not a single deadline for every command:
- HTTP requests share a timeout across redirects and reading the body.
- DNS queries share a timeout across UDP and any TCP retry.
- TLS certificate retrieval bounds the connection and handshake together; scans apply the timeout to each probe.
- Domain lookups can involve multiple RDAP requests and a WHOIS fallback with separately timed network operations.
Consequently, a scan or domain lookup can take longer than the configured timeout. Ctrl+C (SIGINT) and SIGTERM cancel the active command.
The CLI exits with 0 when the command succeeds and 1 on an error. HTTP 4xx/5xx responses and TLS warnings alone do not produce a nonzero exit status; inspect the returned status and scan results in scripts.
watchr completion bash --help
watchr completion zsh --help
watchr completion fish --help
watchr completion powershell --helpUse the selected shell's help output for generation and installation instructions.
Use --format json for indented JSON. watchr's own multiword field names use camelCase; parsed WHOIS data retains the parser library's snake_case names. Duration fields such as HTTP duration, DNS queryTime, and every HTTP timings value are integer nanoseconds; certificate and RDAP event dates use RFC 3339 timestamps.
HTTP headers maps each header name to an array of values, even when only one value exists. Repeated Set-Cookie values are preserved independently. Text output prints each header value on its own line. For example, an illustrative HTTP result is:
{
"url": "https://example.com",
"statusCode": 200,
"status": "200 OK",
"headers": {
"Content-Type": ["text/html"],
"Set-Cookie": ["session=abc; HttpOnly", "theme=dark"]
},
"contentLength": 1256,
"duration": 120000000
}HTTP contentLength is a number when known, otherwise "chunked" or "unknown". timings, HTTPS TLS details, and redirectChain appear only when applicable.
RDAP results contain registration fields directly. WHOIS fallback results use a different shape: source: "WHOIS" with raw and parsed when parsing succeeds, or source: "WHOIS" with data when it does not. Scripts should account for both sources.
TLS scan output includes supportedVersions and scanLimitations. Cipher scans also include cipherSuites for TLS 1.0–1.2 when supported; TLS 1.3 is not included in that map. If TLS 1.3 succeeds, its single negotiated cipher is reported separately as negotiatedTLS13Cipher. Optional fields such as vulnerabilities, preferredVersion, and preferredCipher are omitted when empty.
- HTTPS requests made by
watchr http, TLS certificate inspection, and TLS scan probes skip certificate chain and hostname verification. This permits inspecting self-signed or expired certificates, but a successful command does not establish server identity or certificate trust. Expiry warnings are informational. - Protocol and cipher probes are limited to the Go toolchain's
crypto/tlscapabilities, including Go-supported insecure cipher suites for older protocol versions. A failed handshake does not prove that a server lacks support for every possible client configuration. - TLS 1.3 cipher suites cannot be individually configured for enumeration by this scanner. The reported TLS 1.3 cipher is one negotiated result, not an exhaustive list.
preferredVersionis the highest successfully probed version;preferredCipheris a cipher negotiated in a successful probe, not an exhaustive ranking of server preferences.- Scan warnings flag TLS 1.0/1.1 support and the absence of TLS 1.2/1.3. They are not a comprehensive vulnerability audit, and an empty warning list does not prove that a server is secure.
Only scan systems you are authorized to test.
- Go 1.26.0 or later
- Make (optional, for using Makefile commands)
- golangci-lint on
PATHformake lintandmake check; use a release that supports your Go toolchain
# Build the application into ./bin/watchr
make build
# Run tests (without the race detector)
make test
# Run race-enabled tests and generate coverage.out and coverage.html
make test-cover
# Format code, run vet, lint, and tests
make check
# Download or tidy and verify dependencies
make deps
make tidyChecks without Make, including the race detector:
go fmt ./...
go vet ./...
golangci-lint run ./...
go test -race ./...
go build -o ./bin/watchr ./cmd/watchrmake check uses ordinary tests; run go test -race ./... as well to match CI's race-detector coverage.
watchr/
├── cmd/
│ └── watchr/ # CLI entry point and signal cancellation
├── internal/
│ ├── cmd/ # Cobra commands and CLI tests
│ ├── dns/ # DNS client and types
│ ├── http/ # HTTP client, timing capture, and types
│ ├── output/ # Text and JSON formatters
│ ├── rdap/ # RDAP client and types
│ ├── tls/ # Certificate client and protocol/cipher scanner
│ └── whois/ # WHOIS client
├── .github/ # PR/release workflows and Dependabot configuration
├── bin/ # Local build output (ignored by Git)
├── AGENTS.md # Development guidance for agents
├── Makefile # Build automation
└── go.mod # Go module definition
# Run all tests
go test -race ./...
# Run tests with coverage
go test -race -cover ./...
# Run specific package tests
go test -race ./internal/dnsTests use local HTTP/TLS/DNS/WHOIS fixtures and mocked registration queries, not public network services. They require permission to bind loopback sockets. Dependencies must already be downloaded for offline runs.
This project follows Test-Driven Development (TDD):
- Write failing test first
- Implement minimal code to pass
- Refactor as needed
- Run
make checkandgo test -race ./...before committing
See AGENTS.md for detailed development guidelines.
Pull requests run formatting checks, go vet, golangci-lint, race-enabled tests, and a build. The Go version comes from go.mod.
Pushing a tag matching v*.*.* triggers the release workflow: build the four Linux targets with CGO disabled, compress them with UPX, and upload them to a GitHub release. Workflow actions are pinned to commit SHAs. Dependabot checks Go modules and GitHub Actions weekly.
- cobra - CLI framework
- whois - WHOIS client
- whois-parser - WHOIS data parser
- dns - DNS library
- rdap - RDAP client
Exact direct and indirect dependency versions are recorded in go.mod, with checksums in go.sum.
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Run race-enabled tests (
go test -race ./...) - Run code quality checks (
make check) - Make focused commits describing one logical change each
- Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with Go and powered by excellent open-source libraries from the Go community.