Trending-skills quien-whois-lookup
Use quien for interactive TUI and CLI/JSON domain, IP, DNS, mail, SSL/TLS, and tech stack lookups
install
source · Clone the upstream repo
git clone https://github.com/Aradotso/trending-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Aradotso/trending-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/quien-whois-lookup" ~/.claude/skills/aradotso-trending-skills-quien-whois-lookup && rm -rf "$T"
manifest:
skills/quien-whois-lookup/SKILL.mdsource content
quien — Better WHOIS Lookup Tool
Skill by ara.so — Daily 2026 Skills collection.
quien is a Go-based CLI/TUI tool that replaces whois with tabbed interactive views and JSON-scriptable subcommands for domain WHOIS/RDAP, DNS records, mail configuration (SPF, DMARC, DKIM, BIMI), SSL/TLS, HTTP headers, tech stack detection, and IP/ASN/BGP lookups.
Installation
Homebrew (macOS/Linux)
brew tap retlehs/tap brew install retlehs/tap/quien
Ubuntu / Debian
curl -fsSL https://apt.quien.dev/install.sh | sudo sh
Go
go install github.com/retlehs/quien@latest
Verify installation
quien --version
Optional — replace system whois:
# Add to ~/.bashrc or ~/.zshrc alias whois=quien
Core CLI Commands
Interactive TUI (default)
# Launch interactive prompt quien # Open TUI directly for a domain quien example.com # Open TUI for an IP address quien 8.8.8.8
JSON output (scriptable)
# Full JSON output for all tabs quien --json example.com # Individual subcommands (always output JSON) quien dns example.com quien mail example.com quien tls example.com quien http example.com quien stack example.com quien all example.com # all data in one JSON object
TUI Tab Overview
| Tab | Data shown |
|---|---|
| WHOIS | RDAP-first registration data, registrar, dates, nameservers |
| DNS | A, AAAA, MX, TXT, NS, CNAME, SOA records |
| MX, SPF, DMARC, DKIM, BIMI + VMC chain validation | |
| TLS | Certificate chain, validity, SANs, cipher info |
| HTTP | Response headers, redirects, status codes |
| Stack | WordPress plugins, JS/CSS frameworks, external services |
| IP | Reverse DNS, network info, abuse contacts, ASN via RDAP/BGP |
JSON Subcommand Examples
DNS records
quien dns github.com # Output: # { # "domain": "github.com", # "a": ["140.82.121.4"], # "aaaa": [], # "mx": [{"host": "aspmx.l.google.com", "priority": 1}], # "ns": ["dns1.p08.nsone.net", "dns2.p08.nsone.net"], # "txt": ["v=spf1 ip4:... ~all"], # ... # }
Mail configuration audit
quien mail example.com # Returns SPF record, DMARC policy, DKIM selectors found, # BIMI record, VMC certificate chain validation
TLS/SSL inspection
quien tls example.com # Returns certificate subject, issuer, validity dates, # SANs, chain depth, protocol version, cipher suite
HTTP headers
quien http example.com # Returns status code, redirect chain, all response headers # (Content-Security-Policy, HSTS, X-Frame-Options, etc.)
Tech stack detection
quien stack example.com # Parses HTML for: # - WordPress version + active plugins # - JavaScript frameworks (React, Vue, Angular, Next.js, etc.) # - CSS frameworks (Tailwind, Bootstrap, etc.) # - External services (analytics, CDNs, payment providers)
IP address lookup
quien 8.8.8.8 quien --json 8.8.8.8 # Returns: # - Reverse DNS (PTR record) # - RDAP network block info # - Abuse contact # - Origin ASN + prefix (RDAP with BGP fallback) # - PeeringDB enrichment: org, peering policy, IX/facility counts, # traffic profile, peering locations
All data at once
quien all example.com | jq '.dns.a' quien all example.com | jq '.mail.spf' quien all example.com | jq '.tls.valid_until'
Scripting Patterns
Pipe JSON into jq
# Get all A records quien dns example.com | jq '.a[]' # Check if DMARC policy is reject quien mail example.com | jq '.dmarc.policy == "reject"' # Get certificate expiry quien tls example.com | jq '.certificates[0].not_after' # List detected JS frameworks quien stack example.com | jq '.javascript_frameworks[]' # Get ASN number for an IP quien --json 1.1.1.1 | jq '.asn.number'
Shell script: bulk domain audit
#!/bin/bash domains=("example.com" "github.com" "golang.org") for domain in "${domains[@]}"; do echo "=== $domain ===" spf=$(quien mail "$domain" | jq -r '.spf.record // "MISSING"') dmarc=$(quien mail "$domain" | jq -r '.dmarc.policy // "MISSING"') tls_expiry=$(quien tls "$domain" | jq -r '.certificates[0].not_after // "N/A"') echo "SPF: $spf" echo "DMARC: $dmarc" echo "TLS expires: $tls_expiry" echo done
Shell script: check domain expiry
#!/bin/bash DOMAIN="${1:?Usage: $0 <domain>}" expiry=$(quien --json "$DOMAIN" | jq -r '.whois.expires // .rdap.expires // empty') if [ -z "$expiry" ]; then echo "Could not determine expiry for $DOMAIN" exit 1 fi echo "$DOMAIN expires: $expiry"
Go integration — run quien as subprocess
package main import ( "encoding/json" "fmt" "os/exec" ) type DNSResult struct { Domain string `json:"domain"` A []string `json:"a"` MX []struct { Host string `json:"host"` Priority int `json:"priority"` } `json:"mx"` TXT []string `json:"txt"` } func lookupDNS(domain string) (*DNSResult, error) { out, err := exec.Command("quien", "dns", domain).Output() if err != nil { return nil, fmt.Errorf("quien dns failed: %w", err) } var result DNSResult if err := json.Unmarshal(out, &result); err != nil { return nil, fmt.Errorf("parse error: %w", err) } return &result, nil } func main() { dns, err := lookupDNS("example.com") if err != nil { panic(err) } fmt.Printf("A records for %s: %v\n", dns.Domain, dns.A) for _, mx := range dns.MX { fmt.Printf("MX %d: %s\n", mx.Priority, mx.Host) } }
Go integration — full audit struct
package main import ( "encoding/json" "os/exec" ) type FullAudit struct { WHOIS struct { Registrar string `json:"registrar"` Created string `json:"created"` Expires string `json:"expires"` Updated string `json:"updated"` } `json:"whois"` DNS struct { A []string `json:"a"` NS []string `json:"ns"` TXT []string `json:"txt"` } `json:"dns"` Mail struct { SPF struct { Record string `json:"record"` Valid bool `json:"valid"` } `json:"spf"` DMARC struct { Record string `json:"record"` Policy string `json:"policy"` } `json:"dmarc"` } `json:"mail"` TLS struct { Certificates []struct { Subject string `json:"subject"` NotAfter string `json:"not_after"` } `json:"certificates"` } `json:"tls"` Stack struct { JavascriptFrameworks []string `json:"javascript_frameworks"` CSSFrameworks []string `json:"css_frameworks"` ExternalServices []string `json:"external_services"` } `json:"stack"` } func auditDomain(domain string) (*FullAudit, error) { out, err := exec.Command("quien", "all", domain).Output() if err != nil { return nil, err } var audit FullAudit return &audit, json.Unmarshal(out, &audit) }
Agent Skill Integration
Install quien as an agent skill so AI coding agents automatically use it for domain/IP lookups:
npx skills add retlehs/quien
Key Behaviors to Know
- RDAP-first: Uses RDAP protocol before falling back to raw WHOIS. Broader TLD coverage via IANA referral.
- Automatic retry: All network lookups use exponential backoff — transient failures are retried automatically.
- BGP fallback: If RDAP does not return ASN data for an IP, quien queries BGP routing tables for origin ASN/prefix.
- PeeringDB enrichment: ASN lookups are enriched with PeeringDB data (peering policy, IX presence, traffic profile).
- VMC validation: BIMI lookups validate the full VMC certificate chain, not just the record presence.
- Tech stack from HTML: Stack detection fetches and parses the actual HTML of the target, not just HTTP headers.
Troubleshooting
quien: command not found
# If installed via go install, ensure GOPATH/bin is in PATH export PATH="$PATH:$(go env GOPATH)/bin"
TUI doesn't render correctly
# Ensure your terminal supports true color and UTF-8 echo $TERM # should be xterm-256color or similar echo $LANG # should include UTF-8
Rate limiting / lookup failures
- RDAP and WHOIS servers may rate-limit. quien retries with backoff automatically.
- For bulk scripting, add
between calls to avoid hitting rate limits.sleep 1
No DKIM results
- DKIM requires knowing the selector. quien probes common selectors (google, default, mail, etc.) but custom selectors won't be discovered automatically.
IP lookup shows no ASN
- Some IP blocks are not in RDAP. quien falls back to BGP; if both fail, the block may be unrouted or private.
JSON output is empty / malformed
# Confirm the subcommand syntax — subcommands always output JSON quien dns example.com # correct quien --json dns example.com # incorrect - --json is for top-level only