diff --git a/CHANGELOG.md b/CHANGELOG.md index abb8127..841c0ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### Added +- `DomainHunt` skill with companions (`TldHacks`, `BrokerDetection`, `RegistrarGuide`, `BrandFamilyPairing`) — RDAP-based domain availability workflow, broker-listing detection, brand-family pairing strategy, registrar selection guidance +- `bin/check-domain` — bundled RDAP-based availability checker (bash + curl + python3), source: +- `DEV-0005 Forge Ecosystem Domain Identity` ADR capturing the decision to anchor on `forgeworld.ai` with `modforge.*` and `handforged.*` sub-brands - LICENSE (EUPL-1.2), CONTRIBUTING.md, CODEOWNERS, INSTALL.md - `.gitattributes`, `.gitleaks.toml`, `.gitleaksignore` - `.pre-commit-config.yaml` + `.githooks/pre-commit` with forge-cli validate.sh fallback diff --git a/bin/check-domain b/bin/check-domain new file mode 100755 index 0000000..9486938 --- /dev/null +++ b/bin/check-domain @@ -0,0 +1,199 @@ +#!/bin/bash +# check-domain — Batch domain availability via RDAP + +set -euo pipefail + +readonly BOOTSTRAP_URL="https://data.iana.org/rdap/dns.json" +readonly CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/check-domain" +readonly BOOTSTRAP_CACHE="$CACHE_DIR/rdap-bootstrap.json" +readonly MAPPING_CACHE="$CACHE_DIR/tld-rdap-map.txt" +readonly BOOTSTRAP_TTL_SECONDS=86400 +readonly CURL_TIMEOUT=12 + +usage() { + local prog + prog=$(basename "$0") + cat < [...] + $prog [options] -f + +Checks domain availability via RDAP queries against authoritative registries. + +Output per domain: + AVAIL Domain is not registered (RDAP 404) + TAKEN Domain is registered (RDAP 200) + HTTP-XXX Registry returned unexpected status + NO-RDAP No public RDAP endpoint known for this TLD + +Options: + -h, --help Show this help and exit + -q, --quiet Print only AVAIL results + -f, --file Read domains from file (one per line, # comments allowed) + +Examples: + $prog example.com example.dev + $prog forge.{ai,dev,io,build,tools} + $prog -q -f candidates.txt + +Cache: $CACHE_DIR (TTL ${BOOTSTRAP_TTL_SECONDS}s) +HELP +} + +file_mtime() { + stat -f %m "$1" 2>/dev/null || stat -c %Y "$1" 2>/dev/null +} + +cache_fresh() { + [ -f "$MAPPING_CACHE" ] || return 1 + local now mtime + now=$(date +%s) + mtime=$(file_mtime "$MAPPING_CACHE") + [ -n "$mtime" ] || return 1 + [ $((now - mtime)) -lt "$BOOTSTRAP_TTL_SECONDS" ] +} + +refresh_bootstrap() { + mkdir -p "$CACHE_DIR" + if ! curl -sf --max-time 15 "$BOOTSTRAP_URL" -o "$BOOTSTRAP_CACHE.tmp"; then + echo "warning: could not fetch IANA RDAP bootstrap from $BOOTSTRAP_URL" >&2 + rm -f "$BOOTSTRAP_CACHE.tmp" + return 1 + fi + mv "$BOOTSTRAP_CACHE.tmp" "$BOOTSTRAP_CACHE" + if ! python3 - "$BOOTSTRAP_CACHE" > "$MAPPING_CACHE.tmp" <<'PY' +import json, sys +with open(sys.argv[1]) as handle: + bootstrap = json.load(handle) +for service in bootstrap.get("services", []): + suffixes, endpoints = service[0], service[1] + if not endpoints: + continue + primary = endpoints[0] + for suffix in suffixes: + print(f"{suffix} {primary}") +PY + then + rm -f "$MAPPING_CACHE.tmp" + echo "error: failed to parse IANA RDAP bootstrap" >&2 + return 1 + fi + mv "$MAPPING_CACHE.tmp" "$MAPPING_CACHE" +} + +ensure_bootstrap() { + if cache_fresh; then + return 0 + fi + if refresh_bootstrap; then + return 0 + fi + [ -f "$MAPPING_CACHE" ] && return 0 + return 1 +} + +rdap_base_for_tld() { + awk -v tld="$1" '$1 == tld { print $2; exit }' "$MAPPING_CACHE" +} + +check_one() { + local domain=$1 quiet=$2 + local tld="${domain##*.}" + local base url code + base=$(rdap_base_for_tld "$tld") + if [ -z "$base" ]; then + [ "$quiet" -eq 0 ] && printf "%-30s NO-RDAP\n" "$domain" + return + fi + url="${base%/}/domain/$domain" + code=$(curl -s -o /dev/null -w "%{http_code}" --max-time "$CURL_TIMEOUT" "$url" 2>/dev/null || echo "000") + case "$code" in + 404) + printf "%-30s AVAIL\n" "$domain" + ;; + 200) + [ "$quiet" -eq 0 ] && printf "%-30s TAKEN\n" "$domain" + ;; + *) + [ "$quiet" -eq 0 ] && printf "%-30s HTTP-%s\n" "$domain" "$code" + ;; + esac +} + +read_domains_from_file() { + local file=$1 + [ -r "$file" ] || { echo "error: cannot read file: $file" >&2; exit 2; } + local line + while IFS= read -r line || [ -n "$line" ]; do + line="${line%%#*}" + line="${line//[[:space:]]/}" + [ -n "$line" ] && echo "$line" + done < "$file" +} + +main() { + local quiet=0 + local -a domains=() + while [ $# -gt 0 ]; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + -q|--quiet) + quiet=1 + shift + ;; + -f|--file) + shift + [ $# -eq 0 ] && { echo "error: -f requires a file argument" >&2; exit 2; } + while IFS= read -r d; do + domains+=("$d") + done < <(read_domains_from_file "$1") + shift + ;; + --) + shift + while [ $# -gt 0 ]; do + domains+=("$1") + shift + done + ;; + -*) + echo "error: unknown option: $1" >&2 + usage >&2 + exit 2 + ;; + *) + domains+=("$1") + shift + ;; + esac + done + + if [ ${#domains[@]} -eq 0 ]; then + usage >&2 + exit 2 + fi + + if ! command -v python3 >/dev/null 2>&1; then + echo "error: python3 is required (used to parse IANA RDAP bootstrap)" >&2 + exit 1 + fi + + if ! command -v curl >/dev/null 2>&1; then + echo "error: curl is required" >&2 + exit 1 + fi + + if ! ensure_bootstrap; then + echo "error: no RDAP bootstrap mapping available" >&2 + exit 1 + fi + + for d in "${domains[@]}"; do + check_one "$d" "$quiet" & + done + wait +} + +main "$@" diff --git a/docs/decisions/DEV-0005 Forge Ecosystem Domain Identity.md b/docs/decisions/DEV-0005 Forge Ecosystem Domain Identity.md new file mode 100644 index 0000000..f21f1f6 --- /dev/null +++ b/docs/decisions/DEV-0005 Forge Ecosystem Domain Identity.md @@ -0,0 +1,96 @@ +--- +title: Forge Ecosystem Domain Identity +description: Choose a brand-family of domains for the forge ecosystem (apex + sub-brands + thematic TLDs) without paying broker premiums or premium-tier traps +type: adr +category: governance +tags: + - governance + - branding + - domains +status: accepted +created: 2026-05-13 +updated: 2026-05-13 +author: "@N4M3Z" +project: forge-dev +related: [] +responsible: ["@N4M3Z"] +accountable: ["@N4M3Z"] +consulted: [] +informed: [] +upstream: [DomainHunt] +--- + +# Forge Ecosystem Domain Identity + +## Context and Problem Statement + +The forge ecosystem (CLI binary, library, ~30 published modules, public documentation) needs a coherent web-property identity. The natural apex `forge.ai` is held by a private 2017 GoDaddy registration with no live site — broker-acquirable but not at base price (typical short `.ai` resale ranges $5k-$50k). Every follow-on candidate explored — `forge.dev`, `forge.io`, `forge.app`, every `forgehq.ai` / `forgekit.ai` / `useforge.ai` modifier — is taken. The technically-available `forge.build` is priced as a premium-tier `.build` registration at $1,500. + +The ecosystem needs a pronounceable apex, room for product-line sub-brands, a multi-TLD family totalling under $200/yr, and a trademark posture compatible with public publishing. + +## Decision Drivers + +- Brand alignment with the ecosystem's purpose (module-building, agent forging, skill authoring) +- Available without paying broker premium ($5k-$50k typical for `.ai` shorts) +- Available without premium-tier TLD traps ($500+ for short names on `.build`, `.gold`, `.cars`) +- Coherent multi-property family supporting product-line differentiation +- No live trademark conflicts in the AI-tooling sector +- Affordable annual renewal across the bundle + +## Considered Options + +- **Acquire `forge.ai` from broker** — pay $5k-$50k+ for the canonical apex +- **Buy `forge.build`** — premium-tier `.build` at $1,500 first-year +- **Single-modifier `.ai`** (`forgehq.ai`, `forgekit.ai`, `useforge.ai`, `agentforge.ai`) — every variant probed, all taken +- **Latin or mythological alternative** — `caminus.dev` (literal Latin "forge"), `mulciber.ai` (Vulcan's epithet); both available +- **Foreign-language smithy/anvil** — `kovarna.ai` (Czech smithy), `bigorna.ai` (Portuguese anvil), `enclume.ai` (French anvil) +- **Compound on `.ai` with a thematic apex word** — `forgeworld.ai`, `modforge.ai`, `handforged.ai`; all available +- **TLD-hack apex** — `for.ge` was cleanest but held by a Georgian non-profit since 2011 + +## Decision Outcome + +Chosen: **a multi-property brand family centered on `forgeworld.ai` as the public apex, with `modforge.*` and `handforged.*` as sub-brand product lines.** + +`forgeworld.ai` is the marketing apex. The Forge World name resonates in two directions — as Games Workshop's specialist miniature studio and as the in-universe Adeptus Mechanicus planet class that houses imperial weapons forges. Both senses imply specialist craft and deliberate construction, which matches an AI tooling ecosystem that builds skills, agents, and modules with care. + +`modforge.ai` plus `modforge.dev` plus `modforge.world` carries the module-ecosystem sub-brand. "Mod-forge" directly describes what the forge ecosystem produces: composable modules of skills, agents, and rules. The Minecraft "ModForge" modding loader is a collision but in a fully separate audience. + +`handforged.ai` is reserved for hand-curated, premium-quality skill and agent libraries. "Hand-forged" reads artisanal and counterpoints `modforge` (which connotes batch production) with quality framing. + +Rejected: + +- **Broker acquisition of `forge.ai`** — the price-to-value ratio over `forgeworld.ai` does not justify the broker tax +- **`forge.build` at $1,500** — premium-tier trap; the same brand identity assembles coherently on standard-tier TLDs for under $200/yr total +- **Foreign-language alternatives** (caminus, mulciber, kovarna) — strong individually but lose audience clarity in the predominantly English AI-tooling discourse +- **`for.ge` TLD hack** — owned by an active Georgian non-profit (Union Press); low practical acquisition odds + +### Trademark posture + +"Forge World" is a registered trademark of Games Workshop Group plc, scoped to miniature wargaming and adjacent merchandise. Practical risk is low: Games Workshop has pursued trademark adjacency in its own sector (the [Space Marine](https://en.wikipedia.org/wiki/Space_Marine_trademark_dispute) dispute being the high-water mark) but has not pursued cross-sector uses of "Forge World" as a phrase. AI tooling is fully outside the trademark's covered sector. + +Acceptable risk; documented. + +### Acquisition plan + +| Domain | Registrar (preferred) | Approx price/yr | +| --------------------- | ------------------------------ | ---------------- | +| `forgeworld.ai` | Cloudflare or Porkbun | ~$80-100 | +| `modforge.ai` | Cloudflare or Porkbun | ~$80-100 | +| `modforge.dev` | Cloudflare | ~$15-20 | +| `modforge.world` | Porkbun or 101domain | ~$25-30 | +| `handforged.ai` | Cloudflare or Porkbun | ~$80-100 | + +Total annual: ~$280-350 across the family. + +## Consequences + +- [+] Coherent multi-domain brand family totalling under $350/yr — affordable defense and product-line space +- [+] Apex plus sub-brand structure supports product and persona differentiation without paying broker premiums +- [+] No broker tax, no premium-tier trap +- [+] Pronounceable, memorable across the family +- [+] Subdomain expansion on each apex (e.g. `ai.forgeworld.ai`, `docs.modforge.dev`) extends the family at zero additional registration cost +- [-] Mild Games Workshop trademark adjacency on `forgeworld.ai` (low practical risk given sector separation) +- [-] `modforge` collides with the Minecraft modding loader of the same name (different audience, low practical confusion) +- [-] Multi-domain family requires DNS discipline — pick a primary registrar and manage uniformly to avoid renewal drift + +Future TLDs in this family inherit the same pattern. Decisions to deviate (broker acquisitions, premium-tier purchases, new sub-brand additions) belong in subsequent ADRs. diff --git a/skills/DomainHunt/BrandFamilyPairing.md b/skills/DomainHunt/BrandFamilyPairing.md new file mode 100644 index 0000000..1ca8366 --- /dev/null +++ b/skills/DomainHunt/BrandFamilyPairing.md @@ -0,0 +1,66 @@ +# Brand Family Pairing + +A single domain rarely solves a brand-identity problem. Pairing creates resilience, sub-brand space, and zero-cost expansion through subdomains. + +## The apex + companions pattern + +Pick one strong apex on a primary TLD, then add sibling TLDs as namespaced product lines: + +| Property | Role | TLD selected for | +| ------------------------------ | ------------------------------------------------- | ------------------------- | +| Apex (e.g. `example.ai`) | Primary marketing site, user-facing identity | Brand strength + AI signal| +| Companion 1 (e.g. `example.dev`) | Developer docs, CLI / SDK download page | Dev signal, cheap | +| Companion 2 (e.g. `example.world`) | Thematic extension, persona sub-brand | Vibe pairing | +| Companion 3 (e.g. `example.md`) | Canonical documentation / specification surface | Markdown signal | + +A coherent 3-property bundle on mid-tier TLDs typically totals under $150/yr — cheaper than one premium single domain and reads as a richer brand. + +## Subdomain expansion + +Subdomains on an apex you already own cost nothing. After registering `example.ai`, you have: + +| Subdomain | Common purpose | +| ----------------------- | ---------------------------------------------------- | +| `docs.example.ai` | Documentation | +| `api.example.ai` | REST surface | +| `ai.example.ai` | Themed sub-product — fakes the `ai.example` visual | +| `cli.example.ai` | Download / installation page | +| `blog.example.ai` | Editorial content | +| `.example.ai` | Per-user instance (wildcard DNS) | + +A four-part DNS name reads as a real product surface. Use subdomains liberally before buying another TLD. + +## Defensive registration + +For a brand you intend to publish under, register the obvious neighbors even when you don't plan to use them: + +| Defensive target | Why | +| ----------------------------- | ------------------------------------------------------------------------------ | +| Plural / singular | `example.ai` plus `examples.ai` | +| Adjacent dev TLDs | If your apex is `.ai`, also grab `.dev` and `.app` | +| Hyphenated variant | `example-ai.com` for a `.ai` apex | +| Common close-typos | Rarely worth it unless under active impersonation | + +Rule of thumb: one apex plus one-to-two defensive registrations is reasonable. Five-plus defensive registrations is bikeshedding unless you're a high-trust brand under active impersonation. + +## When to walk away + +A brand-family search is failing when: + +- Every meaningful TLD is taken, premium-priced, or on a broker +- Adjacent typos are taken by speculators +- The apex name itself triggers a real trademark concern in your sector + +Walking away early is cheaper than walking away after registering a partial family. Either rename the brand or scope down to one TLD and lean on subdomains for everything else. + +## Trademark posture + +Three reasonable defaults when a candidate brand collides with an existing trademark: + +| Posture | When to apply | +| --------------------- | ---------------------------------------------------------------------------------------------------------- | +| Avoid entirely | Trademark holder is litigious AND your product overlaps their sector | +| Acknowledge and proceed | Trademark holder operates in a fully unrelated sector and the term is sector-specific within that domain | +| Acquire defensively | The collision is in your sector but the original holder is dormant, willing to sell, or unenforcing | + +The most common mistake is treating trademark risk as binary. A small AI tool sharing a name with a niche miniature line is not the same risk profile as a startup branding itself after a Fortune 500 product. Read the trademark filing — most are sector-scoped — before deciding the name is unusable. diff --git a/skills/DomainHunt/BrokerDetection.md b/skills/DomainHunt/BrokerDetection.md new file mode 100644 index 0000000..dd2b295 --- /dev/null +++ b/skills/DomainHunt/BrokerDetection.md @@ -0,0 +1,84 @@ +# Broker Detection + +When a domain returns `TAKEN`, the next question is whether it's actively used or parked for sale. The signals below identify the latter. + +## Nameserver signatures + +The clearest signal is the domain's authoritative nameservers. If they point at a known broker marketplace, the domain is for sale: + +| Nameserver pattern | Marketplace | +| ------------------------------------- | ---------------------------------------- | +| `*.afternic.com` | Afternic (GoDaddy's broker arm) | +| `*.daaz.org`, `daaz.com` | Daaz | +| `*.dan.com` | Dan.com (owned by GoDaddy) | +| `*.sedo.com`, `*.sedoparking.com` | Sedo | +| `*.parkingcrew.net` | ParkingCrew (often Squadhelp listings) | +| `nameshift.com` | Trademark / brand-protection parking | +| `trademarkarea.com` | Brand-protection parking, often speculation | + +Query nameservers with: + +```bash +dig @1.1.1.1 +short NS +``` + +Or read the `Name Server:` lines in the whois response. + +## Registrar signatures + +Some registrars are over-represented in speculative holdings: + +| Registrar | Often signals | +| -------------------------- | ------------------------------------------ | +| `Marcaria.com LLC` | Brand-protection or speculative hold | +| `Sav.com LLC` | Discount registrar — frequent flips | +| `Domains By Proxy LLC` | Privacy proxy — registrant could be anyone | +| `Network Solutions LLC` | Legacy holds, low resale interest | +| `MarkMonitor / CSC` | Corporate trademark protection — rarely for sale at any reachable price | + +## HTTP behavior on the live domain + +After identifying broker nameservers, fetch the apex to see the landing: + +```bash +curl -sIL --max-time 10 "https://example.ai" | grep -iE "^HTTP|^Location" +``` + +Common patterns: + +| Response | Meaning | +| ------------------------------------------------------- | ------------------------------------------------------------- | +| `HTTP 405 Method Not Allowed`, no body | Parked at broker, no static page | +| `HTTP 301/302` to `dan.com/buy-domain/...` or `daaz.com/lander?...` | Explicit marketplace listing | +| `HTTP 200` with broker branding | Sale page with asking price visible — read before inquiring | +| `HTTP 200` with substantive content | Real site, low resale odds | +| Empty response, connection refused | Registered but DNS not configured — could be fresh speculation | + +## Typical price ranges by signal class + +Asking prices on broker listings vary widely; these are working ranges, not commitments: + +| Domain class | Typical Afternic / Daaz ask | +| ----------------------------------------------------- | --------------------------- | +| Common-word `.com` or premium `.ai` | $5k - $50k | +| Short premium ccTLD (5-letter `.io` or `.md`) | $1k - $10k | +| Recently-registered 4-7 letter speculation | $500 - $5k | +| Domain quietly parked >10 years on private NS | Variable — open negotiation | + +## Acquisition friction signals + +Watch for these before committing emotional energy or budget: + +- Registrar is a corporate brand-protection service with no public seller — likely held for a corporate trademark, not for resale at any reachable price +- Registration creation date matches the launch of a known speculation pattern (dozens of similar names from the same registrant within a week) +- Nameservers point to a clearly real business — not for sale at any price worth paying +- The domain has a live A record AND a working website — that's a business, not a parked asset + +## Inquiry protocol + +When a brokered domain is genuinely worth pursuing: + +1. Open the apex URL in a browser — many listings show the BIN price or "make offer" floor without authentication. +2. Use the marketplace's inquiry form rather than emailing the registrant directly. Pricing structure and escrow are managed by the marketplace. +3. Start under the visible ask if there is one. Counters of 30-50% of the listed BIN are routine. +4. Budget for transfer fees and escrow (typically $50-200 on top of the price). diff --git a/skills/DomainHunt/RegistrarGuide.md b/skills/DomainHunt/RegistrarGuide.md new file mode 100644 index 0000000..844c944 --- /dev/null +++ b/skills/DomainHunt/RegistrarGuide.md @@ -0,0 +1,73 @@ +# Registrar Guide + +Where to actually buy each TLD, with verified pricing patterns and eligibility caveats. + +## TLD pricing reference + +Prices are approximate USD-equivalent. Confirm at checkout — promotions and premium-tier flagging can change the number. + +| TLD | Cheapest known retail | Typical retail | Notes | +| ---------------- | --------------------- | --------------------------- | ---------------------------------------------------- | +| `.ai` | ~$80/yr (2-yr min) | $80-100/yr | Anguilla. No premium tier on most names. | +| `.dev` | $15-20/yr | $15-20/yr | Google, HTTPS-required. | +| `.app` | $15-20/yr | $15-20/yr | Google, HTTPS-required. | +| `.io` | $40-60/yr | $40-60/yr | Premium-tier pricing on short names is common. | +| `.world` | $25-30/yr | $25-30/yr | Identity Digital gTLD. | +| `.build` | $30 standard | $30 / $500-$1500 premium | CentralNic. Many short names are premium-tier. | +| `.tools`, `.codes`, `.systems`, `.solutions` | $25-30/yr | $25-30/yr | Identity Digital family. | +| `.md` | nic.md direct: ~$26/yr (450 lei) | $180-$290/yr at international resellers | Moldova. "Medical doctor" premium at international resellers. | +| `.eu` | ~$5-15/yr | $5-15/yr | EURid. EU/EEA restriction enforced post-registration.| +| `.cz` | $10-20/yr | $10-20/yr | Czech Republic. Open registration. | +| `.de` | $5-15/yr | $5-15/yr | Germany. Open registration. | +| `.foo`, `.bar` | $25-50/yr | $25-50/yr | Google-operated. | +| `.ge` | $40-80/yr | $40-80/yr | Georgia. Open registration via accredited registrars.| +| `.rs` | $15-30/yr | $15-30/yr | Serbia. Open registration. | + +## Eligibility-restricted TLDs + +Some TLDs require proof of presence even though the name appears available: + +| TLD | Requirement | +| ---------------- | -------------------------------------------------------------------------------------------- | +| `.eu` | EU/EEA citizen, EU/EEA resident, or EU/EEA-based organization. EURid verifies post-registration. | +| `.au` | Australian individual, organization, or registered Australian trademark. | +| `.py` | Paraguayan presence in most registrar policies (some intermediaries circumvent). | +| `.bot` | Verified operation on an approved bot platform (Amazon Lex, MS Bot Framework, Dialogflow). | +| `.cu` | Cuban legal presence. | +| `.gov`, `.edu`, `.mil` | Sector-restricted (US government, education, military). | + +Failure to meet eligibility leads to post-registration suspension, not a refund. + +## Major registrar coverage + +| Registrar | Strengths | Weaknesses | +| -------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------- | +| Cloudflare | Wholesale at-cost pricing, no upsells, free DNS at any tier | ~390 TLDs only — no `.md`, `.cz`, `.foo`, many ccTLDs | +| Porkbun | Wide TLD coverage, transparent pricing, clean checkout UI | Doesn't sell `.md` | +| Namecheap | Aggressive first-year promos | Renewal usually 2-3× the first-year price | +| 101domain | Widest ccTLD coverage of any retail registrar — sells `.md`, `.au`, restricted ccTLDs | Steeper prices on common TLDs than Cloudflare/Porkbun | +| Gandi | EU-friendly, niche ccTLD support | Many TLDs gated behind paid "Corporate Services" | +| IONOS | Promotional first-year on `.eu` / `.de` family | Renewal pricing climbs sharply | +| Dynadot | Mid-range pricing, decent UX | Uneven ccTLD coverage | + +## Registry-direct paths + +Open ccTLD registries often sell at wholesale, saving 50-80% over reseller markup: + +| TLD | Registry | Direct path | +| ------- | ----------------- | ------------------------------------------------ | +| `.md` | nic.md | — manual email/phone process | +| `.cz` | CZ.NIC | or Subreg.cz | +| `.eu` | EURid | Sells via accredited registrars only | +| `.de` | DENIC | Via German registrars (`united-domains`, INWX) | + +## Buying patterns that save real money + +- **Single primary TLD on Cloudflare** when it's supported — at-cost, no surprise renewals. +- **Niche ccTLD direct from the registry** when open registration is allowed (`.md`, `.cz`, `.de`). Saves 50-80% over reseller markup. +- **Promotional first-year, transfer at renewal** — Namecheap and IONOS run sub-$5 promos; transfer to a stable registrar before the price jumps. +- **Inquire with local registrars** for country-specific TLDs (Moldovan / Czech / Polish / Belgian / Dutch). Often half the international price. + +## When the registry rules don't apply at your registrar + +Cloudflare requires its supported TLD list. Porkbun has its own. "Open registration" at the registry doesn't mean every registrar supports it. Cross-check the TLD against the registrar's catalogue before promising a stakeholder a name will be available. diff --git a/skills/DomainHunt/SKILL.md b/skills/DomainHunt/SKILL.md new file mode 100644 index 0000000..3cada6c --- /dev/null +++ b/skills/DomainHunt/SKILL.md @@ -0,0 +1,71 @@ +--- +name: DomainHunt +version: 0.1.0 +description: "Pick brandable available domains via RDAP, detect broker listings, plan brand families, and choose registrars without overpaying premium tiers. USE WHEN picking a domain, naming a project, checking domain availability, registering a domain, brand research, TLD hack, ccTLD pricing." +--- + +# DomainHunt + +A workflow for picking brandable, available domains without overpaying brokers or premium-tier registries. Wraps the `check-domain` CLI with strategy: candidate generation, RDAP probing, broker detection, brand-family pairing, and registrar selection. + +@TldHacks.md +@BrokerDetection.md +@RegistrarGuide.md +@BrandFamilyPairing.md + +## Workflow + +1. **Frame the brand.** Decide the apex word, the feeling, the audience. A short seed list of 5-10 names is enough — pruning happens at the next step. +2. **Probe with `check-domain`.** Run candidates in parallel against RDAP. Filter on `AVAIL` first, then triage `NO-RDAP` ccTLDs via direct whois. +3. **Detect broker traps.** For interesting `TAKEN` candidates, inspect nameservers. Afternic, Daaz, Dan.com, Sedo, nameshift, and trademarkarea signal active resale (typical ask $500-$50k). See [BrokerDetection.md](BrokerDetection.md). +4. **Look for TLD hacks.** A ccTLD that completes the word (`for.ge` reads as "forge") or a TLD that doubles as a file extension (`.md` for Markdown, `.rs` for Rust) can be the cleverest available solution. See [TldHacks.md](TldHacks.md). +5. **Plan a brand family.** Pick an apex on the strongest TLD and pair companions on thematic or cheap TLDs (`apex.ai` + `apex.dev` + `apex.world`) rather than chasing a single perfect domain. See [BrandFamilyPairing.md](BrandFamilyPairing.md). +6. **Pick registrars.** Verify the registry actually sells each TLD at acceptable prices. Some TLDs (`.md`, `.au`, `.py`) are restricted, gated, or premium-priced even when listed as available. See [RegistrarGuide.md](RegistrarGuide.md). + +## The check-domain tool + +Location: `bin/check-domain` (bundled with this module) or installed separately from . + +```bash +check-domain example.ai example.dev example.io +check-domain forge.{ai,dev,world,build,tools} +check-domain -q -f candidates.txt +``` + +The tool queries each TLD's authoritative RDAP endpoint via the IANA bootstrap registry, caches the bootstrap for 24h at `~/.cache/check-domain/`, and runs lookups in parallel. + +### Intent-to-flag mapping + +| Intent | Flag | Example | +| ---------------------------- | ------------------- | ------------------------------------------------- | +| Check one or several names | (positional args) | `check-domain forgeworld.ai forgeworld.dev` | +| Filter to available only | `-q` / `--quiet` | `check-domain -q forge.{ai,dev,build}` | +| Probe a curated list | `-f` / `--file` | `check-domain -f candidates.txt` | +| Show usage | `-h` / `--help` | `check-domain --help` | + +### Output legend + +| Status | Meaning | +| ---------- | ------------------------------------------------------------------ | +| `AVAIL` | RDAP returned 404 — not registered | +| `TAKEN` | RDAP returned 200 — registered (parked or actively used) | +| `HTTP-XXX` | Registry returned unexpected status (rate limit, throttling) | +| `NO-RDAP` | TLD has no public RDAP endpoint — verify manually via whois | + +`NO-RDAP` does not mean available. Common ccTLDs (`.io`, `.sh`, `.so`, `.gg`) lack public RDAP but most popular names on those TLDs are taken — always verify before assuming a `NO-RDAP` is winnable. + +## Red Flags + +| Thought | Reality | +| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | +| "First `AVAIL` hit — done." | Premium TLDs (`.build`, `.gold`, `.cars`) often show available but list at $500-$1500. Check checkout. | +| "`NO-RDAP` means I can probably get it." | Query the ccTLD whois directly. Most desirable names are taken even where RDAP is silent. | +| "I'll just email the parked owner." | Brokered domains have published or quoted asks on the Afternic/Daaz landing page. Read those first. | +| "Eligibility looks soft — I'll just register." | `.eu` requires EU/EEA, `.au` requires Australian presence, `.py` is gated. Suspended domains aren't a refund. | +| "One perfect domain solves everything." | A 3-property brand family on mid-tier TLDs often costs less than one premium domain and reads stronger. | + +## Constraints + +- Bash, curl, and python3 required for `check-domain` (macOS 12.3+ and most Linux distros ship them). +- RDAP queries are rate-limited per-IP at most registries. For sweeps over 50 domains expect occasional `HTTP-429` and slow the run. +- Brand decisions deserve an ADR — when the result lands on a multi-domain family, capture rationale in the project's `docs/decisions/`. diff --git a/skills/DomainHunt/TldHacks.md b/skills/DomainHunt/TldHacks.md new file mode 100644 index 0000000..04e8c90 --- /dev/null +++ b/skills/DomainHunt/TldHacks.md @@ -0,0 +1,78 @@ +# TLD Hacks + +Patterns where the TLD completes or amplifies the second-level word. + +## Country-code completion + +When a ccTLD reads as the end of a real word: + +| Pattern | Reads as | TLD origin | +| --------------------- | ------------------- | ---------- | +| `for.ge` | "forge" | Georgia | +| `.de` | English past tense | Germany | +| `.es` | Spanish plural/verb | Spain | +| `.it` | "X it" imperative | Italy | +| `.is` | "X is" sentence | Iceland | +| `.in` | "X in" preposition | India | +| `.ng` | English `-ing` form | Nigeria | +| `.am` | "X am" verb | Armenia | +| `.do` | "X do" verb | Dominican Republic | +| `.me` | "X me" command | Montenegro | +| `.us` | "X us" pronoun | USA | + +Most cleverly-readable TLD-completion plays have been claimed by domainers for over a decade. Always probe before assuming. + +## File-extension TLDs + +When the TLD doubles as a recognized file format: + +| TLD | Reads as | Brand fit | +| ------- | ------------------ | ---------------------------------------------------------- | +| `.md` | Markdown | Content-authoring tools, documentation-first projects | +| `.rs` | Rust source | Rust libraries and CLIs | +| `.sh` | Shell script | CLI tools, devops, infrastructure | +| `.py` | Python source | Python projects (registration heavily restricted) | +| `.so` | Shared object | Compiled libraries, plugins | +| `.zip` | Zip archive | Compression, releases, transfers (security-sensitive TLD) | +| `.mov` | QuickTime video | Video tools | + +## Element-symbol TLDs + +The periodic table hides in some country codes: + +| TLD | Element | Notes | +| ----- | ---------- | ---------------------------------------------------------------------------------- | +| `.ai` | none | Anguilla — reinterpreted as Artificial Intelligence | +| `.au` | Gold (Au) | Australia — also reads as "forge gold" for metalworking brands. Australian-presence required for direct `.au` | +| `.ag` | Silver (Ag)| Antigua and Barbuda | +| `.cu` | Copper (Cu)| Cuba — heavily restricted | +| `.pt` | Platinum (Pt) | Portugal | + +## Programmer-meta TLDs + +| TLD | Reads as | Operator / cost notes | +| ------ | ------------------------- | ------------------------------------------- | +| `.foo` | Placeholder variable | Google, premium-tier on short names | +| `.bar` | Placeholder variable | Google | +| `.new` | Create-new (sheets.new) | Google, single-action semantic | +| `.zip` | Compression | Google, controversial launch | + +## Verifying a candidate TLD actually exists + +Several plausible-sounding TLDs were never delegated. Confirm via IANA's bootstrap before designing around them: + +```bash +whois -h whois.iana.org . 2>&1 | grep -iE "whois:|refer:" +``` + +Empty `whois:` field or "0 objects" means not delegated. Examples that don't exist as TLDs: + +| Imagined TLD | Reality | +| ------------------------- | ---------------------------------------------------------- | +| `.agent` | Not delegated | +| `.forge` | Not delegated | +| `.keep` | Not delegated | +| `.skill` | Not delegated | +| `.galaxy`, `.empire`, `.realm`, `.universe`, `.cosmos`, `.kingdom` | None delegated | +| `.maker`, `.makers`, `.studios` | None delegated (singular `.studio` does exist) | +| `.developer`, `.development`, `.factory`, `.machine` | None delegated |