| content from, another skill needs to parse source material, "parse this URL", "extract content", "解析链接", "提取内容".
npx skills add https://github.com/joeseesun/qiaomu-cut-skill --skill content-parser
Extract and normalize content from URLs across supported platforms. Returns structured data including content body, metadata, and references. Useful as a preprocessing step for content generation skills or standalone content extraction.
shared/config-pattern.md before any interaction~/Downloads/ or .listenhub/ — save to the current working directory<HARD-GATE>
Use the AskUserQuestion tool for every multiple-choice step — do NOT print options as plain text. Ask one question at a time. Wait for the user's answer before proceeding to the next step. After collecting URL and options, confirm with the user before calling the extraction API.
</HARD-GATE>
Follow shared/config-pattern.md § API Key Check. If the key is missing, stop immediately.
Follow shared/config-pattern.md Step 0 (Zero-Question Boot).
If file doesn't exist — silently create with defaults and proceed:
mkdir -p ".listenhub/content-parser"
echo '{"autoDownload":true}' > ".listenhub/content-parser/config.json"
CONFIG_PATH=".listenhub/content-parser/config.json"
CONFIG=$(cat "$CONFIG_PATH")
Do NOT ask any setup questions. Proceed directly to the Interaction Flow.
If file exists — read config silently and proceed:
CONFIG_PATH=".listenhub/content-parser/config.json"
[ ! -f "$CONFIG_PATH" ] && CONFIG_PATH="$HOME/.listenhub/content-parser/config.json"
CONFIG=$(cat "$CONFIG_PATH")
Only run when the user explicitly asks to reconfigure. Display current settings:
当前配置 (content-parser):
自动下载:{是 / 否}
Then ask:
autoDownload: trueautoDownload: falseSave immediately:
NEW_CONFIG=$(echo "$CONFIG" | jq --argjson dl {true/false} '. + {"autoDownload": $dl}')
echo "$NEW_CONFIG" > "$CONFIG_PATH"
CONFIG=$(cat "$CONFIG_PATH")
Free text input. Ask the user:
> What URL would you like to extract content from?
Ask if the user wants to configure extraction options:
Question: "Do you want to configure extraction options?"
Options:
- "No, use defaults" — Extract with default settings
- "Yes, configure options" — Set summarize, maxLength, or Twitter tweet count
If "Yes", ask follow-up questions:
Summarize:
Ready to extract content:
URL: {url}
Options: {summarize: true, maxLength: 5000, twitter.count: 50} / default
Proceed?
Wait for explicit confirmation before calling the API.
references/supported-platforms.md) {
"source": {
"type": "url",
"uri": "{url}"
},
"options": {
"summarize": true/false,
"maxLength": 5000,
"twitter": {
"count": 50
}
}
}
Omit options if user chose defaults.
POST /v1/content/extract → extract taskIdrun_in_background: true and timeout: 300000. Note: status field is .data.status (not processStatus), interval is 5s, values are processing/completed/failed: TASK_ID="<id-from-step-3>"
for i in $(seq 1 60); do
RESULT=$(curl -sS "https://api.marswave.ai/openapi/v1/content/extract/$TASK_ID" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "X-Source: skills" 2>/dev/null)
STATUS=$(echo "$RESULT" | tr -d '\000-\037\177' | jq -r '.data.status // "processing"')
case "$STATUS" in
completed) echo "$RESULT"; exit 0 ;;
failed) echo "FAILED: $RESULT" >&2; exit 1 ;;
*) sleep 5 ;;
esac
done
echo "TIMEOUT" >&2; exit 2
If autoDownload is true, generate a slug from the extracted title (falling back to domain name if no title). Follow shared/config-pattern.md § Artifact Naming for slug generation and dedup.
{slug}.md to the current directory — full extracted content in markdown{slug}.json to the current directory — full raw API response data SLUG="{title-slug}" # e.g. "topology-wikipedia"
# Dedup: check if files exist
BASE="$SLUG"; i=2
while [ -e "${SLUG}.md" ] || [ -e "${SLUG}.json" ]; do SLUG="${BASE}-${i}"; i=$((i+1)); done
echo "$CONTENT_MD" > "${SLUG}.md"
echo "$RESULT" > "${SLUG}.json"
Present:
内容提取完成!
来源:{url}
标题:{metadata.title}
长度:~{character count} 字符
消耗积分:{credits}
已保存到当前目录:
{slug}.md
{slug}.json
/podcast, /tts)Estimated time: 10-30 seconds depending on content size and platform.
Environment variable: LISTENHUB_API_KEY (format: lh_sk_...)
Store in ~/.zshrc (macOS) or ~/.bashrc (Linux):
export LISTENHUB_API_KEY="lh_sk_..."
How to obtain: Visit https://listenhub.ai/settings/api-keys (Pro plan required).
Base URL: https://api.marswave.ai/openapi/v1
Required headers (every request):
Authorization: Bearer $LISTENHUB_API_KEY
Content-Type: application/json
X-Source: skills
The X-Source: skills header identifies requests as coming from Claude Code skills (CLI tool).
curl template:
curl -sS -X POST "https://api.marswave.ai/openapi/v1/{endpoint}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{ ... }'
For GET requests, omit -d and change -X POST to -X GET.
Security notes:
Create a content extraction task for a URL. Returns a taskId for polling.
Request body:
| Field | Required | Type | Description |
|-------|----------|------|-------------|
| source | Yes | object | Source to extract from |
| source.type | Yes | string | Must be "url" |
| source.uri | Yes | string | Valid HTTP(S) URL to extract content from |
| options | No | object | Extraction options |
| options.summarize | No | boolean | Whether to generate a summary |
| options.maxLength | No | integer | Maximum content length |
| options.twitter | No | object | Twitter/X specific options |
| options.twitter.count | No | integer | Number of tweets to fetch (1-100, default 20) |
Response:
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb"
}
}
Error codes:
| Code | Meaning |
|------|---------|
| 29003 | Validation error ("source.uri" is required, "source.uri" must be a valid uri) |
| 21007 | Invalid API key |
Get extraction task status and results.
Path params:
| Param | Type | Description |
|-------|------|-------------|
| taskId | string | 24-char hex task ID |
Response states:
failCode and messageResponse (processing):
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb",
"status": "processing",
"createdAt": "2025-04-09T12:00:00Z",
"data": null,
"credits": 0,
"failCode": null,
"message": null
}
}
Response (completed):
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb",
"status": "completed",
"createdAt": "2025-04-09T12:00:00Z",
"data": {
"content": "Extracted text content...",
"metadata": {
"title": "Article Title",
"author": "Author Name",
"publishedAt": "2025-04-01T08:00:00Z"
},
"references": [
"https://example.com/related-article"
]
},
"credits": 5,
"failCode": null,
"message": null
}
}
Response (failed):
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb",
"status": "failed",
"createdAt": "2025-04-09T12:00:00Z",
"data": null,
"credits": 0,
"failCode": "EXTRACT_FAILED",
"message": "Unable to extract content from the provided URL"
}
}
Key fields:
| Field | Type | Description |
|-------|------|-------------|
| status | string | processing, completed, or failed |
| data.data.content | string | Extracted text content |
| data.data.metadata | object | Page metadata (title, author, publishedAt) |
| data.data.references | array | Referenced URLs (array of strings) |
| credits | integer | Credits consumed |
| failCode | string | Error code (null on success) |
| message | string | Error message (null on success) |
Error codes:
| Code | Meaning |
|------|---------|
| 29003 | Invalid taskId format |
| 25002 | Task not found |
5-second interval, 60 polls max. Run with run_in_background: true and timeout: 300000.
Two-step pattern:
taskId from the response.run_in_background: true. You will be notified automatically when it completes.The exact polling bash command is already specified in the Workflow section (Step 5).
HTTP status codes:
| Code | Meaning | Action |
|------|---------|--------|
| 200 | Success | Parse response body |
| 400 | Bad request | Check parameters |
| 401 | Invalid API key | Re-check LISTENHUB_API_KEY |
| 402 | Insufficient credits | Inform user to recharge |
| 403 | Forbidden | No permission for this resource |
| 429 | Rate limited | Exponential backoff, retry after delay |
| 500/502/503/504 | Server error | Retry up to 3 times |
Retry strategy:
Application error codes:
| Code | Meaning |
|------|---------|
| 21007 | Invalid user API key |
| 25429 | Rate limited (application-level) |
User: "Parse this article: https://en.wikipedia.org/wiki/Topology"
Agent workflow:
https://en.wikipedia.org/wiki/Topologycurl -sS -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{
"source": {
"type": "url",
"uri": "https://en.wikipedia.org/wiki/Topology"
}
}'
curl -sS "https://api.marswave.ai/openapi/v1/content/extract/69a7dac700cf95938f86d9bb" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "X-Source: skills"
User: "Extract recent tweets from @elonmusk, get 50 tweets"
Agent workflow:
https://x.com/elonmusk{"twitter": {"count": 50}}curl -sS -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{
"source": {
"type": "url",
"uri": "https://x.com/elonmusk"
},
"options": {
"twitter": {
"count": 50
}
}
}'
Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take joeseesun/content-parser from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.