Help us improve
Share bugs, ideas, or general feedback.
From para-obsidian
Inbox capture that matches Web Clipper output. Clips URLs or inline text as clipping notes with LLM-generated titles. Batch-capable for multiple URLs. No classification, no area/project assignment — triage handles that.
npx claudepluginhub nathanvale/side-quest-marketplace-old --plugin para-obsidianHow this skill is triggered — by the user, by Claude, or both
Slash command
/para-obsidian:clipThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Inbox capture that produces clipping notes matching Obsidian Web Clipper output — real page titles, raw fetched content, `<!-- highlights:0 -->` marker. No classification, no Layer 1 formatting, no area/project assignment. Everything gets organized later by `/para-obsidian:triage`.
Saves a URL or text snippet to the knowledge intake clippings folder for later review and promotion. Quick capture without leaving the session; items are audited on next /audit-knowledge run.
Creates importable JSON templates for the Obsidian Web Clipper by analyzing live page DOM, schema data, and selectors. Guides selector verification and template logic.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
Inbox capture that produces clipping notes matching Obsidian Web Clipper output — real page titles, raw fetched content, <!-- highlights:0 --> marker. No classification, no Layer 1 formatting, no area/project assignment. Everything gets organized later by /para-obsidian:triage.
Design philosophy: ADHD-friendly capture with Web Clipper parity. Save a link, get a real note — not a stub. Capture now, organize later.
Before processing any input, query the clipping template for its current structure:
para_template_fields({ template: "clipping", response_format: "json" })
Extract from response:
validArgs → which args to pass to para_create (e.g., source, clipped, domain)creation_meta.dest → destination folder (e.g., "00 Inbox")creation_meta.contentTargets → which section heading accepts content injection (e.g., ["Content"])creation_meta.titlePrefix → emoji prefix (e.g., "✂️ ")Use these discovered values throughout the skill instead of hardcoding them. If the template changes, this skill auto-adapts.
Parse $ARGUMENTS to determine mode:
Step 1: Extract all URLs from arguments (regex: https?://\S+).
| Result | Mode |
|---|---|
| 1+ URLs found | URL mode — create clipping notes |
| No URLs found | Inline text mode — create clipping note |
Step 2: Deduplicate URLs before processing (URL mode only).
For each URL, create a clipping note that triage recognizes as itemType: "clipping".
Step 1 — Extract domain:
Strip www. prefix from hostname:
github.com/anthropics/claude-code → domain: "github.com"
www.kentcdodds.com/blog/aha → domain: "kentcdodds.com"
Step 2 — Fetch content:
The clip skill should produce notes identical to what the Obsidian Web Clipper creates — including page content in the Content section. Fetch content for every URL.
| URL Pattern | Tool | Extract |
|---|---|---|
youtube.com, youtu.be | get_video_info + firecrawl_scrape | Title from video info, description + embed from Firecrawl |
x.com, twitter.com | Skip (no tool available yet) | Use domain as title, empty content |
| Everything else | firecrawl_scrape | metadata.title + markdown body |
YouTube URLs:
get_video_info({ url: "<url>" })
→ extract title from response
firecrawl_scrape({ url: "<url>", formats: ["markdown"], onlyMainContent: true })
→ extract markdown as page content (video description, chapters, links)
Combine into content: video embed  followed by the scraped description.
General URLs (Firecrawl):
firecrawl_scrape({
url: "<url>",
formats: ["markdown"],
onlyMainContent: true
})
→ extract metadata.title as page title
→ extract markdown as page content
X/Twitter URLs: Skip fetching. Firecrawl is blocklisted for x.com. Use domain as title, no content. Future x-twitter plugin will handle this.
If fetch fails: Fall back to domain as title with empty content. Never block capture on fetch failure.
Step 3 — Derive title:
Use the fetched page title as the note title. If fetching was skipped or failed, fall back to domain-based title:
github.com URL → title: github.comgithub.com URLs → titles: github.com - anthropics, github.com - modelcontextprotocolFor domain fallback, extract the slug from the first meaningful path segment (skip empty segments).
Step 4 — Create clipping note:
Use discovered values from Step 0 (validArgs for args, creation_meta.dest for dest, creation_meta.contentTargets[0] for content section heading):
para_create({
template: "clipping",
title: "<fetched-or-derived-title>",
dest: "<discovered-dest>",
args: {
source: "<full-url>",
clipped: "<YYYY-MM-DD>",
domain: "<domain>"
},
content: {
"<discovered-content-target>": "<fetched-content>\n\n<!-- highlights:0 -->"
},
response_format: "json"
})
The content parameter injects the fetched page content into the content target section discovered from creation_meta.contentTargets. The <!-- highlights:0 --> marker matches Web Clipper output format.
If no content was fetched (X/Twitter, or fetch failure), omit the content parameter entirely.
Process URLs sequentially — each fetch + para_create call completes before the next. Collect results for the report.
Step 5 — Batch commit:
para_commit({
message: "Clip: <N> URLs to inbox",
response_format: "json"
})
One commit for all notes. Never commit per-note.
Capture free text from the conversation into a clipping note.
Step 1 — Generate title:
Generate a concise, descriptive title (under 60 characters) that captures the essence of the text. Use your judgment as an LLM — don't just truncate, summarize the core idea into a clear title.
Step 2 — Create clipping note:
para_create({
template: "clipping",
title: "<generated-title>",
dest: "<discovered-dest>",
args: {
source: "conversation",
clipped: "<YYYY-MM-DD>"
},
content: {
"<discovered-content-target>": "<full-inline-text>\n\n<!-- highlights:0 -->"
},
response_format: "json"
})
The content parameter injects text into the content target section discovered from Step 0.
Defaults: source: "conversation". Zero-friction capture — no enum choices required. Triage or manual review can adjust later.
Step 3 — Commit:
para_commit({
message: "Clip: <title>",
response_format: "json"
})
URL mode (batch):
Clipped N URLs to inbox:
1. ✂️ AHA Programming ← kentcdodds.com/blog/aha-programming
2. ✂️ Claude Code ← github.com/anthropics/claude-code
3. ✂️ x.com ← x.com/housecor/status/123456 (no content — X not supported yet)
Committed. Run /para-obsidian:triage to classify.
URL mode (single):
Clipped: ✂️ AHA Programming → 00 Inbox/✂️ AHA Programming.md
Committed. Run /para-obsidian:triage to classify.
Inline mode:
Clipped: <title> → 00 Inbox/<title>.md
Committed. Run /para-obsidian:triage to process.
| Scenario | Action |
|---|---|
| Empty arguments | Report: "Nothing to clip. Pass URLs or text to capture." |
| Invalid URL (parse fails) | Skip that URL, report as warning, continue with remaining |
| Content fetch fails | Fall back to domain title + empty body. Report warning, continue. |
para_create fails for one URL | Log error, continue with remaining URLs |
| All URLs fail | Report all failures, create nothing |
para_commit fails | Report warning — notes still exist uncommitted |
| Duplicate URL in batch | Deduplicate before processing |
| Filename collision | para_create handles this automatically (appends number) |
Soft failure philosophy: Never block on individual failures in batch mode. Create what you can, report what failed. Fetch failures degrade gracefully to domain-only stubs.
Notes created by this skill are fully compatible with /para-obsidian:triage:
| Mode | type field | Triage detection | Triage action |
|---|---|---|---|
| URL | clipping | type === "clipping" + source is URL | Routes to analyze-web worker for classification |
| Inline text | clipping | type === "clipping" + source is NOT URL | Stays in inbox (manual review items) |
Clipping notes with fetched content give triage a head start — it can classify from the content already present rather than re-fetching.
/para-obsidian:clip https://kentcdodds.com/blog/aha-programming
Creates: 00 Inbox/✂️ AHA Programming.md (with full article content)
/para-obsidian:clip https://github.com/anthropics/claude-code https://youtube.com/watch?v=abc123 https://kentcdodds.com/blog/aha-programming
Creates 3 notes in 00 Inbox/ with fetched titles and content, commits all at once.
/para-obsidian:clip https://www.youtube.com/watch?v=dQw4w9WgXcQ
Creates: 00 Inbox/✂️ <Video Title>.md (title only, no transcript — triage fetches that)
/para-obsidian:clip The key insight is that Layer 1 captures raw content, Layer 2 bolds the most important 10-20%, and Layer 3 highlights the top 10% of bold passages.
Creates: 00 Inbox/Progressive Summarization Layer Strategy.md (LLM-generated title)
/para-obsidian:clip Check if React Server Components solve the waterfall problem for GMS checkout flow
Creates: 00 Inbox/RSC for GMS Checkout Waterfall Problem.md (LLM-generated title)
After reporting results, emit a structured completion signal so the brain orchestrator can parse the outcome:
SKILL_RESULT:{"status":"ok","skill":"clip","summary":"Clipped N URLs to inbox"}SKILL_RESULT:{"status":"partial","skill":"clip","clipped":N,"failed":M}SKILL_RESULT:{"status":"ok","skill":"clip","summary":"Clipped inline text to inbox"}SKILL_RESULT:{"status":"error","skill":"clip","error":"All URLs failed to clip"}SKILL_RESULT:{"status":"error","skill":"clip","error":"Nothing to clip"}