Auto-Pilot / 全自动
更新于 a month ago

tapestry

Mmichalparkola
0.2k
michalparkola/tapestry-skills-for-claude-code/tapestry
74
Agent 评分

💡 摘要

一个主控技能,用于检测URL内容类型(YouTube视频、文章、PDF),提取其文本,并自动生成结构化的“Ship-Learn-Next”行动计划。

🎯 适合人群

寻求结构化学习路径的自学者将媒体内容转化为项目的内容创作者将研究转化为行动项的产品经理为学习计划总结材料的学生将教程工作流自动化的开发者

🤖 AI 吐槽:这把瑞士军刀很棒,直到你发现它主要只是在调用其他更锋利的刀。

安全分析低风险

该技能会执行shell命令、从用户提供的URL下载文件并可能自动安装软件包。如果URL输入被恶意构造(例如,通过文件名进行shell注入),将存在任意命令执行的风险。缓解措施:严格清理URL输入,避免直接将其用于命令替换,并在沙盒环境中运行。


name: tapestry description: Unified content extraction and action planning. Use when user says "tapestry ", "weave ", "help me plan ", "extract and plan ", "make this actionable ", or similar phrases indicating they want to extract content and create an action plan. Automatically detects content type (YouTube video, article, PDF) and processes accordingly. allowed-tools: Bash,Read,Write

Tapestry: Unified Content Extraction + Action Planning

This is the master skill that orchestrates the entire Tapestry workflow:

  1. Detect content type from URL
  2. Extract content using appropriate skill
  3. Automatically create a Ship-Learn-Next action plan

When to Use This Skill

Activate when the user:

  • Says "tapestry [URL]"
  • Says "weave [URL]"
  • Says "help me plan [URL]"
  • Says "extract and plan [URL]"
  • Says "make this actionable [URL]"
  • Says "turn [URL] into a plan"
  • Provides a URL and asks to "learn and implement from this"
  • Wants the full Tapestry workflow (extract → plan)

Keywords to watch for: tapestry, weave, plan, actionable, extract and plan, make a plan, turn into action

How It Works

Complete Workflow:

  1. Detect URL type (YouTube, article, PDF)
  2. Extract content using appropriate skill:
    • YouTube → youtube-transcript skill
    • Article → article-extractor skill
    • PDF → download and extract text
  3. Create action plan using ship-learn-next skill
  4. Save both content file and plan file
  5. Present summary to user

URL Detection Logic

YouTube Videos

Patterns to detect:

  • youtube.com/watch?v=
  • youtu.be/
  • youtube.com/shorts/
  • m.youtube.com/watch?v=

Action: Use youtube-transcript skill

Web Articles/Blog Posts

Patterns to detect:

  • http:// or https://
  • NOT YouTube, NOT PDF
  • Common domains: medium.com, substack.com, dev.to, etc.
  • Any HTML page

Action: Use article-extractor skill

PDF Documents

Patterns to detect:

  • URL ends with .pdf
  • URL returns Content-Type: application/pdf

Action: Download and extract text

Other Content

Fallback:

  • Try article-extractor (works for most HTML)
  • If fails, inform user of unsupported type

Step-by-Step Workflow

Step 1: Detect Content Type

URL="$1" # Check for YouTube if [[ "$URL" =~ youtube\.com/watch || "$URL" =~ youtu\.be/ || "$URL" =~ youtube\.com/shorts ]]; then CONTENT_TYPE="youtube" # Check for PDF elif [[ "$URL" =~ \.pdf$ ]]; then CONTENT_TYPE="pdf" # Check if URL returns PDF elif curl -sI "$URL" | grep -i "Content-Type: application/pdf" > /dev/null; then CONTENT_TYPE="pdf" # Default to article else CONTENT_TYPE="article" fi echo "📍 Detected: $CONTENT_TYPE"

Step 2: Extract Content (by Type)

YouTube Video

# Use youtube-transcript skill workflow echo "📺 Extracting YouTube transcript..." # 1. Check for yt-dlp if ! command -v yt-dlp &> /dev/null; then echo "Installing yt-dlp..." brew install yt-dlp fi # 2. Get video title VIDEO_TITLE=$(yt-dlp --print "%(title)s" "$URL" | tr '/' '_' | tr ':' '-' | tr '?' '' | tr '"' '') # 3. Download transcript yt-dlp --write-auto-sub --skip-download --sub-langs en --output "temp_transcript" "$URL" # 4. Convert to clean text (deduplicate) python3 -c " import sys, re seen = set() vtt_file = 'temp_transcript.en.vtt' try: with open(vtt_file, 'r') as f: for line in f: line = line.strip() if line and not line.startswith('WEBVTT') and not line.startswith('Kind:') and not line.startswith('Language:') and '-->' not in line: clean = re.sub('<[^>]*>', '', line) clean = clean.replace('&amp;', '&').replace('&gt;', '>').replace('&lt;', '<') if clean and clean not in seen: print(clean) seen.add(clean) except FileNotFoundError: print('Error: Could not find transcript file', file=sys.stderr) sys.exit(1) " > "${VIDEO_TITLE}.txt" # 5. Cleanup rm -f temp_transcript.en.vtt CONTENT_FILE="${VIDEO_TITLE}.txt" echo "✓ Saved transcript: $CONTENT_FILE"

Article/Blog Post

# Use article-extractor skill workflow echo "📄 Extracting article content..." # 1. Check for extraction tools if command -v reader &> /dev/null; then TOOL="reader" elif command -v trafilatura &> /dev/null; then TOOL="trafilatura" else TOOL="fallback" fi echo "Using: $TOOL" # 2. Extract based on tool case $TOOL in reader) reader "$URL" > temp_article.txt ARTICLE_TITLE=$(head -n 1 temp_article.txt | sed 's/^# //') ;; trafilatura) METADATA=$(trafilatura --URL "$URL" --json) ARTICLE_TITLE=$(echo "$METADATA" | python3 -c "import json, sys; print(json.load(sys.stdin).get('title', 'Article'))") trafilatura --URL "$URL" --output-format txt --no-comments > temp_article.txt ;; fallback) ARTICLE_TITLE=$(curl -s "$URL" | grep -oP '<title>\K[^<]+' | head -n 1) ARTICLE_TITLE=${ARTICLE_TITLE%% - *} curl -s "$URL" | python3 -c " from html.parser import HTMLParser import sys class ArticleExtractor(HTMLParser): def __init__(self): super().__init__() self.content = [] self.skip_tags = {'script', 'style', 'nav', 'header', 'footer', 'aside', 'form'} self.in_content = False def handle_starttag(self, tag, attrs): if tag not in self.skip_tags and tag in {'p', 'article', 'main'}: self.in_content = True def handle_data(self, data): if self.in_content and data.strip(): self.content.append(data.strip()) def get_content(self): return '\n\n'.join(self.content) parser = ArticleExtractor() parser.feed(sys.stdin.read()) print(parser.get_content()) " > temp_article.txt ;; esac # 3. Clean filename FILENAME=$(echo "$ARTICLE_TITLE" | tr '/' '-' | tr ':' '-' | tr '?' '' | tr '"' '' | cut -c 1-80 | sed 's/ *$//') CONTENT_FILE="${FILENAME}.txt" mv temp_article.txt "$CONTENT_FILE" echo "✓ Saved article: $CONTENT_FILE"

PDF Document

# Download and extract PDF echo "📑 Downloading PDF..." # 1. Download PDF PDF_FILENAME=$(basename "$URL") curl -L -o "$PDF_FILENAME" "$URL" # 2. Extract text using pdftotext (if available) if command -v pdftotext &> /dev/null; then pdftotext "$PDF_FILENAME" temp_pdf.txt CONTENT_FILE="${PDF_FILENAME%.pdf}.txt" mv temp_pdf.txt "$CONTENT_FILE" echo "✓ Extracted text from PDF: $CONTENT_FILE" # Optionally keep PDF echo "Keep original PDF? (y/n)" read -r KEEP_PDF if [[ ! "$KEEP_PDF" =~ ^[Yy]$ ]]; then rm "$PDF_FILENAME" fi else # No pdftotext available echo "⚠️ pdftotext not found. PDF downloaded but not extracted." echo " Install with: brew install poppler" CONTENT_FILE="$PDF_FILENAME" fi

Step 3: Create Ship-Learn-Next Action Plan

IMPORTANT: Always create an action plan after extracting content.

# Read the extracted content CONTENT_FILE="[from previous step]" # Invoke ship-learn-next skill logic: # 1. Read the content file # 2. Extract core actionable lessons # 3. Create 5-rep progression plan # 4. Save as: Ship-Learn-Next Plan - [Quest Title].md # See ship-learn-next/SKILL.md for full details

Key points for plan creation:

  • Extract actionable lessons (not just summaries)
  • Define a specific 4-8 week quest
  • Create Rep 1 (shippable this week)
  • Design Reps 2-5 (progressive iterations)
  • Save plan to markdown file
  • Use format: Ship-Learn-Next Plan - [Brief Quest Title].md

Step 4: Present Results

Show user:

✅ Tapestry Workflow Complete!

📥 Content Extracted:
   ✓ [Content type]: [Title]
   ✓ Saved to: [filename.txt]
   ✓ [X] words extracted

📋 Action Plan Created:
   ✓ Quest: [Quest title]
   ✓ Saved to: Ship-Learn-Next Plan - [Title].md

🎯 Your Quest: [One-line summary]

📍 Rep 1 (This Week): [Rep 1 goal]

When will you ship Rep 1?

Complete Tapestry Workflow Script

#!/bin/bash # Tapestry: Extract content + create action plan # Usage: tapestry <URL> URL="$1" if [ -z "$URL" ]; then echo "Usage: tapestry <URL>" exit 1 fi echo "🧵 Tapestry Workflow Starting..." echo "URL: $URL" echo "" # Step 1: Detect content type if [[ "$URL" =~ youtube\.com/watch || "$URL" =~ youtu\.be/ || "$URL" =~ youtube\.com/shorts ]]; then CONTENT_TYPE="youtube" elif [[ "$URL" =~ \.pdf$ ]] || curl -sI "$URL" | grep -iq "Content-Type: application/pdf"; then CONTENT_TYPE="pdf" else CONTENT_TYPE="article" fi echo "📍 Detected: $CONTENT_TYPE" echo "" # Step 2: Extract content case $CONTENT_TYPE in youtube) echo "📺 Extracting YouTube transcript..." # [YouTube extraction code from above] ;; article) echo "📄 Extracting article..." # [Article extraction code from above] ;; pdf) echo "📑 Downloading PDF..." # [PDF extraction code from above] ;; esac echo "" # Step 3: Create action plan echo "🚀 Creating Ship-Learn-Next action plan..." # [Plan creation using ship-learn-next skill] echo "" echo "✅ Tapestry Workflow Complete!" echo "" echo "📥 Content: $CONTENT_FILE" echo "📋 Plan: Ship-Learn-Next Plan - [title].md" echo "" echo "🎯 Next: Review your action plan and ship Rep 1!"

Error Handling

Common Issues:

1. Unsupported URL type

  • Try article extraction as fallback
  • If fails: "Could not extract content from this URL type"

2. No content extracted

  • Check if URL is accessible
  • Try alternate extraction method
  • Inform user: "Extraction failed. URL may require authentication."

3. Tools not installed

  • Auto-install when possible (yt-dlp, reader, trafilatura)
  • Provide install instructions if auto-install fails
  • Use fallback methods when available

4. Empty or invalid content

  • Verify file has content before creating plan
  • Don't create plan if extraction failed
  • Show pre
五维分析
清晰度7/10
创新性7/10
实用性8/10
完整性9/10
可维护性6/10
优缺点分析

优点

  • 编排了从内容提取到计划制定的完整多步骤工作流
  • 针对不同内容类型具有健壮的URL检测和回退逻辑
  • 输出格式清晰、可操作,旨在促使用户执行

缺点

  • 高度依赖外部工具(yt-dlp、pdftotext等)和网络调用
  • 复杂的bash脚本容易出错且难以调试
  • 行动计划生成逻辑定义模糊,可能过于简单

相关技能

pytorch

S
toolCode Lib / 代码库
92/ 100

“它是深度学习的瑞士军刀,但祝你好运能从47种安装方法里找到那个不会搞崩你系统的那一个。”

agno

S
toolCode Lib / 代码库
90/ 100

“它承诺成为智能体领域的Kubernetes,但得看开发者有没有耐心学习又一个编排层。”

nuxt-skills

S
toolCo-Pilot / 辅助式
90/ 100

“这本质上是一份组织良好的小抄,能把你的 AI 助手变成一只 Nuxt 框架的复读机。”

免责声明:本内容来源于 GitHub 开源项目,仅供展示和评分分析使用。

版权归原作者所有 michalparkola.