og-inspect
Inspect a URL's Open Graph and Twitter Card metadata and render a styled HTML page showing how the link unfurls on Facebook, X/Twitter, LinkedIn, Slack/Discord, and Tumblr. Also prints a JSON summary to stdout. Use when the user asks to "preview a link", "check OG tags", "inspect Open Graph", "see how a URL looks when shared", or invokes `/og-inspect <url>`.
What this skill does
# /og-inspect — Open Graph / share-card inspector
Given a URL, fetch the page, extract Open Graph + Twitter Card metadata, render a styled HTML preview showing how the link unfurls on Facebook, X/Twitter, LinkedIn, Slack/Discord, and Tumblr, and print a JSON summary. Like https://www.opengraph.xyz/ but local.
## Workflow
1. **Get the URL.** The user invokes `/og-inspect <url>`. If no URL is provided, ask: "Which URL should I inspect?"
2. **Run the inspector.** Execute the bash block below with the URL as `$1`. It fetches the page with `curl`, parses meta tags with Python stdlib (`html.parser`), writes a styled HTML preview to `~/claude.nosync/og-previews/YYYY-MM-DD-<host>-<slug>.html`, prints the absolute path of the HTML file to stderr, and prints the JSON summary to stdout.
3. **Open the HTML file** in the default browser with `open "<path>"`.
4. **Print the JSON** result to the terminal (it is already on stdout from step 2 — relay it to the user).
## The script
Run this with the URL as the first argument. Treat the URL as untrusted input — the script already does shell-safe quoting and no `eval`.
```bash
set -uo pipefail
URL="${1:-}"
if [ -z "$URL" ]; then
echo "usage: og-inspect <url>" >&2
exit 1
fi
# Normalize: prepend https:// if no scheme
if ! printf '%s' "$URL" | grep -qE '^https?://'; then
URL="https://$URL"
fi
OUTDIR="$HOME/claude.nosync/og-previews"
mkdir -p "$OUTDIR"
TMP_HTML="$(mktemp -t og-inspect.XXXXXX).html"
TMP_META="$(mktemp -t og-inspect.XXXXXX).meta"
TMP_JSON="$(mktemp -t og-inspect.XXXXXX).json"
TMP_PATH="$(mktemp -t og-inspect.XXXXXX).path"
trap 'rm -f "$TMP_HTML" "$TMP_META" "$TMP_JSON" "$TMP_PATH"' EXIT
# Fetch. Always emit the meta file even on failure so Python can render a stub.
# On TLS verification failure (curl exit 60), retry with -k and flag a warning.
TLS_INSECURE=0
CURL_COMMON=( -sSL
-A "Mozilla/5.0 (compatible; OGInspectBot/1.0)"
-H "Accept: text/html,application/xhtml+xml"
--max-time 15
--max-filesize 5000000
-w '%{http_code}\n%{url_effective}\n%{content_type}\n'
-o "$TMP_HTML" )
curl "${CURL_COMMON[@]}" "$URL" > "$TMP_META" 2>/dev/null
RC=$?
if [ "$RC" -eq 60 ]; then
TLS_INSECURE=1
curl -k "${CURL_COMMON[@]}" "$URL" > "$TMP_META" 2>/dev/null
RC=$?
fi
if [ "$RC" -ne 0 ]; then
printf '0\n%s\n\n' "$URL" > "$TMP_META"
fi
# Parse + render. Python writes JSON to TMP_JSON and the output filepath to TMP_PATH.
python3 - "$URL" "$TMP_HTML" "$TMP_META" "$OUTDIR" "$TLS_INSECURE" >"$TMP_JSON" 2>"$TMP_PATH" <<'PY'
import sys, os, json, html, re
from datetime import datetime, timezone
from html.parser import HTMLParser
from urllib.parse import urljoin, urlparse
orig_url, tmp_html, tmp_meta, outdir, tls_insecure = sys.argv[1:6]
tls_insecure = tls_insecure == "1"
with open(tmp_meta) as f:
lines = f.read().splitlines()
status_str = lines[0] if len(lines) > 0 else "0"
final_url = lines[1] if len(lines) > 1 and lines[1] else orig_url
ctype = lines[2] if len(lines) > 2 else ""
# Decode body with charset detection (file may be missing/empty if curl failed)
try:
with open(tmp_html, "rb") as f:
raw = f.read()
except FileNotFoundError:
raw = b""
charset = None
m = re.search(r"charset=([\w\-]+)", ctype, re.I)
if m: charset = m.group(1)
if not charset:
mm = re.search(rb'<meta[^>]+charset=["\']?([\w\-]+)', raw[:4096], re.I)
if mm:
try: charset = mm.group(1).decode("ascii")
except Exception: pass
charset = charset or "utf-8"
try:
text = raw.decode(charset, errors="replace")
except LookupError:
text = raw.decode("utf-8", errors="replace")
text = text.replace("\x00", "")
class MetaParser(HTMLParser):
def __init__(self):
super().__init__()
self.metas, self.links = [], []
self.title = None
self._in_title = False
self._title_parts = []
def handle_starttag(self, tag, attrs):
d = {k.lower(): v for k, v in attrs}
if tag == "meta":
prop = d.get("property") or d.get("name") or d.get("itemprop")
content = d.get("content")
if prop and content is not None:
self.metas.append((prop.lower(), content))
elif tag == "link":
rel, href = d.get("rel"), d.get("href")
if rel and href: self.links.append((rel.lower(), href))
elif tag == "title":
self._in_title = True
def handle_endtag(self, tag):
if tag == "title":
self._in_title = False
if self.title is None:
self.title = "".join(self._title_parts).strip()
def handle_data(self, data):
if self._in_title: self._title_parts.append(data)
p = MetaParser()
try: p.feed(text)
except Exception: pass
def collect(prefix):
out = {}
for k, v in p.metas:
if k == prefix or k.startswith(prefix + ":"):
sub = k[len(prefix):].lstrip(":") or "_"
out.setdefault(sub, v.strip())
return out
og = collect("og")
tw = collect("twitter")
def by_name(n):
for k, v in p.metas:
if k == n: return v.strip()
return None
def resolve(u):
if not u: return None
try: return urljoin(final_url, u)
except Exception: return u
for d in (og, tw):
if d.get("image"): d["image"] = resolve(d["image"])
if d.get("url"): d["url"] = resolve(d["url"])
canonical = favicon = apple_icon = None
for rel, href in p.links:
rels = rel.split()
if "canonical" in rels and not canonical: canonical = resolve(href)
if "icon" in rels and not favicon: favicon = resolve(href)
if "apple-touch-icon" in rels and not apple_icon: apple_icon = resolve(href)
other = {
"title": p.title,
"description": by_name("description"),
"author": by_name("author"),
"theme_color": by_name("theme-color"),
"canonical": canonical,
"favicon": favicon or apple_icon,
}
warnings = []
if not og.get("title"): warnings.append("missing og:title")
if not og.get("description"): warnings.append("missing og:description")
if not og.get("image"): warnings.append("missing og:image")
if not tw.get("card"): warnings.append("missing twitter:card")
if status_str == "0":
warnings.append("fetch failed (network, DNS, timeout, or size cap)")
elif status_str != "200":
warnings.append(f"HTTP status {status_str}")
if ctype and "html" not in ctype.lower():
warnings.append(f"non-HTML content-type: {ctype}")
if tls_insecure:
warnings.append("TLS verification failed — refetched with -k (cert mismatch or self-signed)")
status_int = int(status_str) if status_str.isdigit() else 0
result = {
"url": orig_url,
"final_url": final_url,
"fetched_at": datetime.now(timezone.utc).isoformat(),
"status": status_int,
"content_type": ctype,
"tls_insecure": tls_insecure,
"warnings": warnings,
"og": og,
"twitter": tw,
"other": other,
}
# Filename
parsed = urlparse(final_url)
host = (parsed.hostname or "unknown").lower()
if host.startswith("www."): host = host[4:]
host_slug = re.sub(r"[^a-z0-9]+", "-", host).strip("-") or "unknown"
seg = (parsed.path.strip("/").split("/", 1)[0] or "root")[:30]
path_slug = re.sub(r"[^a-z0-9]+", "-", seg.lower()).strip("-") or "root"
fname = f"{datetime.now().strftime('%Y-%m-%d')}-{host_slug}-{path_slug}.html"
fpath = os.path.join(outdir, fname)
# HTML rendering
def esc(s):
return html.escape("" if s is None else str(s), quote=True)
def img_or_placeholder(url, alt=""):
if url:
return f'<img src="{esc(url)}" alt="{esc(alt)}" loading="lazy" referrerpolicy="no-referrer">'
return '<div class="img-placeholder">no image</div>'
def table_rows(d):
if not d:
return '<tr><td colspan="2" class="missing">— no tags found —</td></tr>'
rows = []
for k, v in sorted(d.items()):
rows.append(f'<tr><th>{esc(k)}</th><td title="{esc(v)}">{esc(v)}</td></tr>')
return "".joRelated in Image & Video
watch
IncludedWatch a video (URL or local path). Downloads with yt-dlp, extracts auto-scaled frames with ffmpeg, pulls the transcript from captions (or Whisper API fallback), and hands the result to Claude so it can answer questions about what's in the video.
physical-ai-defect-image-generation
IncludedUse when the user wants to orchestrate defect image generation, run associated setup, or handle outputs on OSMO. The Day 0 path handles cold-start with USD-to-ROI, image-edit augmentation, and AnomalyGen to create initial PCBA datasets. The Day 1 path performs inference and labeling on real images. This skill helps with first-time asset setup, creation of finetuning checkpoints, and configuring deployment. Trigger keywords: defect image generation, dig workflow, dig pipeline, defect image detection workflow, aoi pipeline, aoi anomalygen, usd2roi anomalygen, day 0 pcba, day 1 pcba, day 1 real-photo alignment, day 1 manual roi, metal surface anomaly, glass defect, anomalygen finetune, setup_pcb, setup_metal, setup_glass, setup_pretrained, dig setup, dig datasets, dig pretrained checkpoint, dig image-edit endpoint.
accelint-react-best-practices
IncludedReact performance optimization and best practices. ALWAYS use this skill when working with any React code - writing components, hooks, JSX; refactoring; optimizing re-renders, memoization, state management; reviewing for performance; fixing hydration mismatches; debugging infinite re-renders, stale closures, input focus loss, animations restarting; preventing remounting; implementing transitions, lazy initialization, effect dependencies. Even simple React tasks benefit from these patterns. Covers React 19+ (useEffectEvent, Activity, ref props). Triggers - useEffect, useState, useMemo, useCallback, memo, inline components, nested components, components inside components, re-render, performance, hydration, SSR, Next.js, useDeferredValue, combined hooks.
elevenlabs-agents
IncludedBuild conversational AI voice agents with ElevenLabs Platform using React, JavaScript, React Native, or Swift SDKs. Configure agents, tools (client/server/MCP), RAG knowledge bases, multi-voice, and Scribe real-time STT. Use when: building voice chat interfaces, implementing AI phone agents with Twilio, configuring agent workflows or tools, adding RAG knowledge bases, testing with CLI "agents as code", or troubleshooting deprecated @11labs packages, Android audio cutoff, CSP violations, dynamic variables, or WebRTC config. Keywords: ElevenLabs Agents, ElevenLabs voice agents, AI voice agents, conversational AI, @elevenlabs/react, @elevenlabs/client, @elevenlabs/react-native, @elevenlabs/elevenlabs-js, @elevenlabs/agents-cli, elevenlabs SDK, voice AI, TTS, text-to-speech, ASR, speech recognition, turn-taking model, WebRTC voice, WebSocket voice, ElevenLabs conversation, agent system prompt, agent tools, agent knowledge base, RAG voice agents, multi-voice agents, pronunciation dictionary, voice speed control, elevenlabs scribe, @11labs deprecated, Android audio cutoff, CSP violation elevenlabs, dynamic variables elevenlabs, case-sensitive tool names, webhook authentication
humanizer
IncludedHumanize AI-generated text by detecting and removing patterns typical of LLM output. Rewrites text to sound natural, specific, and human. Uses 28 pattern detectors, 560+ AI vocabulary terms across 3 tiers, and statistical analysis (burstiness, type-token ratio, readability) for comprehensive detection. Use when asked to humanize text, de-AI writing, make content sound more natural/human, review writing for AI patterns, score text for AI detection, or improve AI-generated drafts. Covers content, language, style, communication, and filler categories.
generating-mermaid-diagrams
IncludedSalesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says "diagram", "visualize", "ERD", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user wants PNG/SVG image output (use generating-visual-diagrams), or asks about non-Salesforce systems.