Skip to content
Marketing
Skill

/domain-expired-opportunity-finder

Evaluates expired domain candidates against a target niche, scores them by topical relevance, historical activity level, and history cleanliness, then outputs a ranked shortlist with explainable reasoning and risk flags.

From plugin
opendirectory-gtm-skills
58364 skills
Install
$ npx -y skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/domain-expired-opportunity-finder

Context preview

The summary Claude sees to decide when to auto-load this skill.

Evaluates expired domain candidates against a target niche, scores them by topical relevance, historical activity level, and history cleanliness, then outputs a ranked shortlist with explainable reasoning and risk flags.

SKILL.md

domain-expired-opportunity-finder.SKILL.md
name: domain-expired-opportunity-finder
description: Evaluates expired domain candidates against a target niche, scores them by topical relevance, historical activity level, and history cleanliness, then outputs a ranked shortlist with explainable reasoning and risk flags.
compatibility: [claude-code, gemini-cli, github-copilot]
author: ajaycodesitbetter
version: 1.0.0

Expired Domain Opportunity Finder

Evaluate expired domain candidates for a specific niche. Score them on topical fit, historical activity level, history cleanliness, and redirect suitability. Output a conservative, explainable shortlist for human review.

---

**Critical rule:** Every recommendation must include BOTH a positive rationale (`why_selected`) AND a caution rationale (`why_risky`). Never output a bare score without explanation.

**Conservative-by-default rule:** When signals are incomplete or contradictory, lower the confidence level. Do not surface ambiguous candidates as strong opportunities. Missing data reduces confidence, never inflates it.

**Anti-abuse rule:** Never encourage unrelated redirects, PBN construction, or domain repurposing where the historical topic does not match the target niche. Read `references/guardrails.md` for the full anti-abuse policy.

---

Step 1: Setup Check

Check the environment before doing anything else.

Verify that `curl` and `python3` (or `python`) are available:

curl --version > /dev/null 2>&1 && echo "curl: available" || echo "curl: MISSING"
python3 --version 2>/dev/null || python --version 2>/dev/null || echo "python: MISSING"

Check for an optional LLM API key for enhanced niche-relevance scoring:

echo "LLM_API_KEY: ${LLM_API_KEY:+set}"

**If `curl` or `python` is missing:** Stop. Tell the user: "This skill requires curl and Python 3.10+. Please install them and try again."

**If `LLM_API_KEY` is not set:** Continue. The skill will use rule-based scoring only (domain string matching, Wayback title analysis, keyword overlap). Note to the user: "Running in rule-based-only mode. Set LLM_API_KEY for enhanced niche-relevance scoring."

**If `LLM_API_KEY` is set:** The skill will use LLM-enhanced scoring for topical relevance analysis. This provides deeper contextual assessment of niche fit.

QA: State the scoring mode (llm-enhanced or rule-based-only) and confirm tools are available.

---

Step 2: Input Collection

Collect the required and optional inputs from the user.

**Required:**

  • `target_niche` (string): The core niche to evaluate against. Examples: "developer tools", "AI SaaS", "cybersecurity", "fintech".

**Optional (ask only if not provided):**

  • `seed_keywords` (array): Keywords to refine topical matching. If not provided, extract 3–5 keywords from the niche name automatically.
  • `candidate_domains` (array): Specific domains to evaluate. If not provided, prompt the user.
  • `discovery_source` (string): Where candidates came from — `manual`, `expireddomains-net`, `external-feed`.
  • `min_snapshots` (integer): Minimum historical snapshot threshold. Default: 10.
  • `max_risk_level` (string): `low`, `medium`, or `high`. Controls how aggressively risky candidates are filtered. Default: `medium`.
  • `intended_use` (string): `rebuild`, `redirect`, or `either`. Default: `either`.

**If no `candidate_domains` are provided:** Ask: "Please provide a list of expired domain candidates to evaluate. You can: 1. Paste domain names (one per line or comma-separated) 2. Provide a file path to a text file with one domain per line 3. Say 'example' to run with a built-in demo set for the 'developer tools' niche"

**If the user says 'example':** Use this demo set:

devtoolsweekly.com
codeshipnews.io
stackforgeapp.com
quickseorank.net
bestcheaphosting247.com
cloudbuildpro.dev
reactwidgetlib.com
megadealsshop.xyz

After collecting all inputs, confirm: "Target niche: [niche]. Evaluating [N] candidate domains. Scoring mode: [mode]. Intended use: [use]."

---

Step 3: Candidate Normalization

Clean and validate the candidate list before scoring.

python3 -c "
import sys, re

domains = '''CANDIDATE_LIST_HERE'''.strip().split('\n')
seen = set()
valid = []
invalid = []

for d in domains:
    d = d.strip().lower()
    # Strip protocols and paths
    d = re.sub(r'^https?://', '', d)
    d = d.split('/')[0]
    d = d.strip('.')

    if not d:
        continue

    # Basic TLD validation
    if '.' not in d or len(d) < 4:
        invalid.append(d)
        continue

    # Deduplicate
    if d in seen:
        continue
    seen.add(d)
    valid.append(d)

print(f'Valid candidates: {len(valid)}')
print(f'Removed (invalid/duplicate): {len(invalid)}')
for v in valid:
    print(f'  ✓ {v}')
for i in invalid:
    print(f'  ✗ {i} (invalid format)')
"

Replace `CANDIDATE_LIST_HERE` with the actual domain list from Step 2.

State: "[N] valid candidates after normalization. [M] removed (invalid/duplicate)."

If 0 valid candidates remain, stop and tell the user: "No valid domain candidates found. Please provide domain names in the format 'example.com'."

---

Step 4: Signal Collection

For each valid candidate, collect signals from free public sources. Run these checks sequentially per domain.

4a: Wayback CDX API — History Snapshots

Query the Wayback Machine for all historical snapshots. We use `limit=100000` and explicit `from`/`to` parameters are intentionally omitted so that CDX returns snapshots from the full lifetime of the domain. The results are sorted ascending by timestamp (oldest first) so `first_capture` and `last_capture` are accurate:

curl -s "https://web.archive.org/cdx/search/cdx?url=DOMAIN_HERE&output=json&fl=timestamp,statuscode&collapse=timestamp:6&limit=100000" \
  | python3 -c "
import sys, json

try:
    data = json.load(sys.stdin)
    if len(data) <= 1:
        print(json.dumps({'domain': 'DOMAIN_HERE', 'snapshots': 0, 'first_capture': None, 'last_capture': None, 'status_codes': {}, 'years_active': 0}))
    else:
Read more
Ships withopendirectory-gtm-skills

AI Agent Skills built for Founders who hate Marketing

Get the whole plugin