MCP Server Builder
anthropics/skills
Guides the design and implementation of Model Context Protocol servers in TypeScript or Python, from tool naming and error messages to evaluation.
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…
$ npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Varnan-Tech/opendirectory domain-expired-opportunity-finder --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Varnan-Tech/opendirectory.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/domain-expired-opportunity-finder .claude/skills/domain-expired-opportunity-finder && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "domain-expired-opportunity-finder" agent skill from https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finder into .claude/skills/domain-expired-opportunity-finder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "domain-expired-opportunity-finder", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finderType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Varnan-Tech/opendirectory domain-expired-opportunity-finder --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Varnan-Tech/opendirectory.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/domain-expired-opportunity-finder .agents/skills/domain-expired-opportunity-finder && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "domain-expired-opportunity-finder" agent skill from https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finder into .agents/skills/domain-expired-opportunity-finder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "domain-expired-opportunity-finder", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Varnan-Tech/opendirectory domain-expired-opportunity-finder --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Varnan-Tech/opendirectory.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/domain-expired-opportunity-finder .cursor/skills/domain-expired-opportunity-finder && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "domain-expired-opportunity-finder" agent skill from https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finder into .cursor/skills/domain-expired-opportunity-finder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "domain-expired-opportunity-finder", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Varnan-Tech/opendirectory.git --path skills/domain-expired-opportunity-finder--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Varnan-Tech/opendirectory domain-expired-opportunity-finder --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Varnan-Tech/opendirectory.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/domain-expired-opportunity-finder .gemini/skills/domain-expired-opportunity-finder && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "domain-expired-opportunity-finder" agent skill from https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finder into .gemini/skills/domain-expired-opportunity-finder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "domain-expired-opportunity-finder", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Varnan-Tech/opendirectory domain-expired-opportunity-finderInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Varnan-Tech/opendirectory.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/domain-expired-opportunity-finder .github/skills/domain-expired-opportunity-finder && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "domain-expired-opportunity-finder" agent skill from https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finder into .github/skills/domain-expired-opportunity-finder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "domain-expired-opportunity-finder", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Varnan-Tech/opendirectory domain-expired-opportunity-finder --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Varnan-Tech/opendirectory.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/domain-expired-opportunity-finder .opencode/skills/domain-expired-opportunity-finder && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "domain-expired-opportunity-finder" agent skill from https://github.com/Varnan-Tech/opendirectory/tree/main/skills/domain-expired-opportunity-finder into .opencode/skills/domain-expired-opportunity-finder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "domain-expired-opportunity-finder", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
domain-expired-opportunity-finderEvaluates 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…
Domain Expired Opportunity Finder is an agent skill from Varnan-Tech/opendirectory. 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.
Its SKILL.md is about 4.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 9 other files, including reference files (for example `README.md`, `evals/evals.json` and `references/guardrails.md`). Compatibility notes: ["claude-code","gemini-cli","github-copilot"]
It works with Python. The repository describes itself as: AI Agent Skills built for Founders who hate Marketing. The licence is MIT.
7 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 62e437a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
python3curlpythonFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
web.archive.orgrdap.orggenerativelanguage.googleapis.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
LLM_API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
["claude-code","gemini-cli","github-copilot"]
From compatibility in the SKILL.md frontmatter.
Domain Expired Opportunity Finder loads about 4.8k tokens when it runs, and up to ~12k if it reads all its reference files. Until then it costs about 64 tokens; SKILL.md has 1,460 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Varnan-Tech/opendirectory at commit 62e437a, republished under its MIT licence (© Varnan-Tech). 1,460 words, ~4,821 tokens.
.claude/skills/domain-expired-opportunity-finder/SKILL.md (or your agent's skills folder). This skill also uses 7 other files; get the full folder from GitHub.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.
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.
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:
If the user says 'example': Use this demo set:
devtoolsweekly.com
codeshipnews.io
stackforgeapp.com
quickseorank.net
bestcheaphosting247.com
cloudbuildpro.dev
reactwidgetlib.com
megadealsshop.xyzAfter collecting all inputs, confirm: "Target niche: [niche]. Evaluating [N] candidate domains. Scoring mode: [mode]. Intended use: [use]."
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'."
For each valid candidate, collect signals from free public sources. Run these checks sequentially per domain.
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:
rows = data[1:] # skip header row
timestamps = [r[0] for r in rows] # already ascending (oldest first)
statuses = [r[1] for r in rows]
status_counts = {}
for s in statuses:
status_counts[s] = status_counts.get(s, 0) + 1
first_year = int(timestamps[0][:4])
last_year = int(timestamps[-1][:4])
print(json.dumps({
'domain': 'DOMAIN_HERE',
'snapshots': len(rows),
'first_capture': timestamps[0],
'last_capture': timestamps[-1],
'status_codes': status_counts,
'years_active': last_year - first_year + 1
}))
except:
print(json.dumps({'domain': 'DOMAIN_HERE', 'snapshots': 0, 'error': 'wayback_api_failed'}))
"Rate limiting: Wait 2 seconds between Wayback API calls to be polite to the service.
For candidates with > 0 snapshots, fetch the most recent snapshot to extract the page title (used for topical relevance scoring):
curl -s -L "https://web.archive.org/web/LATEST_TIMESTAMP/http://DOMAIN_HERE" \
| python3 -c "
import sys, re
html = sys.stdin.read()[:50000]
title_match = re.search(r'<title[^>]*>(.*?)</title>', html, re.IGNORECASE | re.DOTALL)
title = title_match.group(1).strip() if title_match else 'no title found'
# Extract meta description too
meta_match = re.search(r'<meta[^>]*name=[\"']description[\"'][^>]*content=[\"'](.*?)[\"']', html, re.IGNORECASE)
desc = meta_match.group(1).strip() if meta_match else 'no description found'
print(f'Title: {title}')
print(f'Description: {desc}')
"Replace LATEST_TIMESTAMP with the most recent timestamp from Step 4a.
Use the cross-platform HTTP-based RDAP standard (replaces OS-dependent WHOIS). An HTTP 404 from RDAP means the domain is not registered (i.e. it is genuinely available or untracked) — that is distinct from a network failure. Handle both cases explicitly:
python3 -c "
import urllib.request, urllib.error, json
domain = 'DOMAIN_HERE'
try:
req = urllib.request.Request(
f'https://rdap.org/domain/{domain}',
headers={'User-Agent': 'Mozilla/5.0'}
)
with urllib.request.urlopen(req, timeout=10) as response:
data = json.loads(response.read().decode())
registrar = 'unknown'
created = 'unknown'
for entity in data.get('entities', []):
if 'registrar' in entity.get('roles', []):
try:
registrar = entity.get('vcardArray', [[]])[1][0][3]
except Exception:
pass
for event in data.get('events', []):
if event.get('eventAction') == 'registration':
created = event.get('eventDate', 'unknown')
print(json.dumps({
'domain': domain,
'status': 'registered',
'registrar': registrar,
'created': created
}))
except urllib.error.HTTPError as e:
if e.code == 404:
# Domain has no RDAP object — likely unregistered or not in RDAP coverage
print(json.dumps({'domain': domain, 'status': 'unregistered_or_no_rdap_object'}))
else:
print(json.dumps({'domain': domain, 'error': f'rdap_http_error_{e.code}'}))
except Exception:
print(json.dumps({'domain': domain, 'error': 'rdap_lookup_failed'}))
"Score keyword overlap between the domain name and the target niche / seed keywords:
python3 -c "
import re, json
domain = 'DOMAIN_HERE'
niche = 'NICHE_HERE'
seeds = SEEDS_JSON_HERE # e.g., ['devops', 'ci/cd', 'code editor']
# Extract words from domain
domain_base = domain.rsplit('.', 1)[0] # remove TLD
domain_words = re.split(r'[-_.]', domain_base.lower())
# Check niche words
niche_words = niche.lower().split()
all_keywords = set(niche_words + [s.lower() for s in seeds])
matches = [w for w in domain_words if any(kw in w or w in kw for kw in all_keywords)]
match_ratio = len(matches) / max(len(domain_words), 1)
print(json.dumps({
'domain': domain,
'domain_words': domain_words,
'keyword_matches': matches,
'match_ratio': round(match_ratio, 2)
}))
"If the LLM API key is configured, batch all candidates with their collected signals and ask for a contextual niche-relevance assessment.
Note: The request/response format below uses the Gemini API (generateContent
format). It is not compatible with OpenAI-style endpoints without modification.
If you use a different provider, you must adapt the JSON body and response parsing.
cat > /tmp/domain-relevance-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "You are an SEO research analyst. For each expired domain candidate provided, assess its topical relevance to the specified target niche. Consider the domain name, historical page title, and meta description. For each domain, output a JSON object with: domain (string), relevance_score (integer 1-10), relevance_rationale (one sentence explaining the score), redirect_plausibility (integer 1-10), redirect_rationale (one sentence). Output only a JSON array. No commentary before or after."
}]
},
"contents": [{
"parts": [{
"text": "DOMAIN_SIGNALS_AND_NICHE_CONTEXT_HERE"
}]
}],
"generationConfig": {
"temperature": 0.2,
"maxOutputTokens": 2048
}
}
ENDJSONReplace DOMAIN_SIGNALS_AND_NICHE_CONTEXT_HERE with:
Send the request to the Gemini API:
curl -s -X POST \
"${LLM_API_ENDPOINT:-https://generativelanguage.googleapis.com/v1beta}/models/${LLM_MODEL:-gemini-2.0-flash}:generateContent?key=$LLM_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/domain-relevance-request.json \
| python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
text = d['candidates'][0]['content']['parts'][0]['text']
print(text)
except (KeyError, IndexError, json.JSONDecodeError) as e:
print(json.dumps({'error': 'llm_response_parse_failed', 'detail': str(e)}))
"If the LLM call or response parsing fails, log the error and continue with rule-based scoring only. Do not stop the workflow.
After all signal collection, state: "Signal collection complete for [N] candidates. [M] Wayback hits, [K] RDAP lookups succeeded."
Read references/scoring-model.md for the full scoring framework.
For each candidate, compute scores across the 6 dimensions:
Topical Relevance (0–30): Combine domain keyword match ratio, historical title/description analysis, and LLM relevance score (if available). Without LLM: use keyword match ratio × 15 + title keyword overlap × 15. With LLM: use LLM relevance_score × 3.
Historical Activity Level (0–25): Based on Wayback snapshot diversity and frequency. More snapshots consistently captured across multiple years indicates higher sustained activity and inferred legitimacy.
Historical Content Quality (0–15): Derived from historical page title and meta description analysis, checking for natural phrasing versus keyword stuffing. Without LLM: base score of 8/15 adjusted by exact-match density.
History Cleanliness (0–15): Based on Wayback snapshot count, years active, status code consistency, and absence of parking page indicators.
Redirect Suitability (0–10): Based on topic continuity between historical content and target niche. Use LLM redirect_plausibility score if available; otherwise use keyword overlap ratio.
Signal Completeness (0–5): Count how many data sources returned usable data (Wayback, RDAP, domain analysis, LLM if configured).
Compute:
opportunity_score = sum of all dimension scores (0–100)confidence = based on how many dimensions have strong data (see scoring-model.md)recommended_action = based on score + confidence + risk flags (see Step 6)Read references/risk-flags.md for the complete flag definitions.
Apply risk flags to each candidate:
| Check | Flag Applied |
|---|---|
| Historical topic overlap < 30% with target niche | topic_mismatch |
| Domain active < 1 year before expiry | short_history |
| < 3 Wayback snapshots or all parking pages | unclear_history |
| Sudden Wayback drop-off after years of activity | possible_deindex |
Snapshot count below min_snapshots | weak_historical_activity |
| Redirect suitability < 4/10 | redirect_mismatch |
Apply recommendation logic:
| Score + Flags | Recommendation |
|---|---|
Score ≥ 75 AND confidence high AND no High-severity flags | high-priority-review |
Score ≥ 55 AND confidence ≥ medium | review |
| Score ≥ 55 BUT redirect_suitability < 4/10 | rebuild-only-review |
| Score < 55 OR any critical High-severity flag | reject |
Apply max_risk_level filter:
max_risk_level = low: exclude any candidate with Medium or High flagsmax_risk_level = medium: exclude candidates with High flags onlymax_risk_level = high: include all candidates (no filter)Read references/output-format.md for the exact JSON schema.
Read references/guardrails.md for the required disclaimer text.
Default: Shortlist mode. Show only candidates with recommended_action
of high-priority-review, review, or rebuild-only-review.
If the user requested audit mode, show ALL candidates with full dimension breakdowns including rejection reasons.
## Expired Domain Opportunity Finder — [YYYY-MM-DD]
**Target niche:** [niche]
**Seed keywords:** [keywords]
**Intended use:** [rebuild/redirect/either]
**Candidates evaluated:** [N]
**Shortlisted:** [M]
**Rejected:** [K]
**Scoring mode:** [llm-enhanced / rule-based-only]
---
### 1. [domain.com] — Score: [N]/100 | Confidence: [level] | Action: [recommendation]
**Topical fit:** [summary]
**Activity level:** [summary]
**Content quality:** [summary]
**History:** [summary]
**Redirect suitability:** [level]
**Risk flags:** [flags or "none"]
**Why selected:** [rationale]
**Why risky:** [rationale]
---
[repeat for each shortlisted domain, ranked by opportunity_score descending]
---
**Disclaimer:** These results are research recommendations, not guarantees
of SEO value. Redirect analysis should only be considered when strong
topic continuity exists between the expired domain and your target site.
Search engine algorithms change frequently. Always perform manual due
diligence — including checking current index status, reviewing the full
backlink profile with a commercial tool, and verifying domain history —
before making any acquisition decision. This skill does not endorse or
facilitate manipulative SEO practices.Save the structured JSON output:
mkdir -p docs/expired-domain-intel
OUTFILE="docs/expired-domain-intel/$(date +%Y-%m-%d).json"
cat > "$OUTFILE" << 'EOF'
JSON_OUTPUT_HERE
EOF
echo "Saved to $OUTFILE"If 0 candidates pass the shortlist: "No candidates met the shortlist criteria for the '[niche]' niche with the current risk tolerance. This is a normal outcome — it means the evaluated domains were not strong enough matches. Try:
Run every check before presenting output:
why_selected AND why_riskyhigh-priority-review actionredirect_mismatch are labeled rebuild-only-review (not review)scoring_mode correctly reflects whether LLM was usedopportunity_score descendingdocs/expired-domain-intel/YYYY-MM-DD.jsonFix any violation before presenting.
why_risky© Varnan-Tech, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 7 other files (references) in skills/domain-expired-opportunity-finder of Varnan-Tech/opendirectory.
Open the folder on GitHubat commit 62e437a
Domain Expired Opportunity Finder next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Domain Expired Opportunity Finder this skillVarnan-Tech/opendirectory | 674 | — | ~4.8k | Automated safety check: Pass | MIT | |
| MCP Server Builderanthropics/skills | 180k | 63 repos | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| PDF Processinganthropics/skills | 180k | 47 repos | ~2k | Automated safety check: Pass | Proprietary | |
| NotebookLM Research AssistantPleasePrompto/notebooklm-skill | 7.8k | 14 repos | ~2.4k | Automated safety check: Notes | MIT | |
| Manim Video Productionbrowser-use/video-use | 29k | 6 repos | ~3k | Automated safety check: Pass | MIT | |
| PPT Masterhugohe3/ppt-master | 59k | 1 repos | ~2.5k | Automated safety check: Pass | MIT |
anthropics/skills
Guides the design and implementation of Model Context Protocol servers in TypeScript or Python, from tool naming and error messages to evaluation.
anthropics/skills
Handles everyday PDF jobs in Python and on the command line: extract text and tables, merge, split, rotate, watermark, fill forms, encrypt and OCR.
PleasePrompto/notebooklm-skill
Lets Claude Code ask questions of your Google NotebookLM notebooks through browser automation and return answers grounded in your uploaded sources.
browser-use/video-use
Produces math and technical explainer videos with Manim Community Edition: concept animations, equation derivations, algorithm walkthroughs and data stories.
hugohe3/ppt-master
Generates editable PowerPoint decks, rebuilds slides from images, fills .pptx templates and polishes existing presentations through routed workflows.
zLanqing/codex-claude-academic-skills
Machine learning in Python with scikit-learn. An agent skill from zLanqing/codex-claude-academic-skills.
Varnan-Tech/opendirectory
Creates professionally designed B2B SaaS e-books in HTML + CSS, exported as print-ready PDF.
Varnan-Tech/opendirectory
Generates and updates README.md and API reference docs by reading your codebase's functions, routes, types, schemas, and architecture.
Varnan-Tech/opendirectory
Generates data visualization charts (bar, line, area, pie, doughnut, scatter, radar, treemap) as PNG using Apache ECharts v6.
Varnan-Tech/opendirectory
Creates animated looping GIFs from CSS animations (default) or AI image-to-video.
Varnan-Tech/opendirectory
Given a product description, category keywords, or competitor names (any combination), searches Reddit, Hacker News, GitHub Issues, G2, and Google Trends for the real pains your market experiences…
Varnan-Tech/opendirectory
Aggregates RSS feeds from the past week, synthesizes the top stories using Gemini, and publishes a newsletter digest to Ghost CMS.
Works with
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…. Domain Expired Opportunity Finder is an agent skill from Varnan-Tech/opendirectory. 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.
Run `npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a claude-code`. Or copy the skill folder (skills/domain-expired-opportunity-finder in Varnan-Tech/opendirectory) into .claude/skills/domain-expired-opportunity-finder in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a codex`. Or copy the skill folder (skills/domain-expired-opportunity-finder in Varnan-Tech/opendirectory) into .agents/skills/domain-expired-opportunity-finder in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Varnan-Tech/opendirectory --skill domain-expired-opportunity-finder -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/domain-expired-opportunity-finder, .gemini/skills/domain-expired-opportunity-finder, .github/skills/domain-expired-opportunity-finder and .opencode/skills/domain-expired-opportunity-finder in your project.
Going by SKILL.md and its folder, Domain Expired Opportunity Finder needs the command-line tools its instructions call (python3, curl and python) and credentials named LLM_API_KEY. Our summary lists: Python 3; A credential in LLM_API_KEY. Compatibility (from SKILL.md): ["claude-code","gemini-cli","github-copilot"].
SKILL.md names 3 domains. In commands or code: web.archive.org, rdap.org and generativelanguage.googleapis.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Domain Expired Opportunity Finder is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.8k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 7k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Domain Expired Opportunity Finder: MCP Server Builder (anthropics/skills, 180k stars), PDF Processing (anthropics/skills, 180k stars), NotebookLM Research Assistant (PleasePrompto/notebooklm-skill, 7.8k stars) and Manim Video Production (browser-use/video-use, 29k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Varnan-Tech (a GitHub organization) maintains it in Varnan-Tech/opendirectory, which has 674 GitHub stars. The repository holds 61 skills in this directory. The repository was last updated on August 16, 2026.
Source: Varnan-Tech/opendirectory on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.