بنقرة واحدة
content-ingestion
Ingest web content into Kurt. Map sitemaps to discover URLs, then fetch content selectively.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Ingest web content into Kurt. Map sitemaps to discover URLs, then fetch content selectively.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Information gathering utilities (analytics, research, content analysis) (general)
Manage Kurt projects - add sources/targets, update project.md, detect missing content, track progress. (project)
One-time team setup that creates Kurt profile and foundation rules
Collect content feedback and identify patterns for rule updates
Extract and manage writing rules (style, structure, persona, publisher, custom) (project)
Configure CMS connections and perform ad-hoc content searches (Sanity, Contentful, WordPress)
| name | content-ingestion |
| description | Ingest web content into Kurt. Map sitemaps to discover URLs, then fetch content selectively. |
This skill enables efficient web content ingestion with a map-then-fetch workflow. Discover URLs from sitemaps first, review what was found, then selectively download only the content you need. Supports single document fetching and fast parallel batch downloads.
Content is extracted as markdown with metadata (title, author, date, categories) and stored in the sources/ directory.
# 1. Discover URLs from sitemap (fast, no downloads)
kurct content map https://www.anthropic.com
# 1a. OR discover with publish dates (slower, extracts dates from blogrolls)
kurct content map https://docs.getdbt.com/sitemap.xml --discover-dates
# 2. Review what was found
kurt content list --status NOT_FETCHED
# 3. Fetch content (parallel batch)
kurct content fetch --url-prefix https://www.anthropic.com/
Why two steps?
Three-step process:
NOT_FETCHED recordsWhen invoked from /create-project or /resume-project, use map-then-fetch to provide preview:
Map first - Show user what URLs were discovered
kurct content map https://docs.example.com
echo "Discovered X URLs. Preview:"
kurt content list --url-prefix https://docs.example.com --status NOT_FETCHED | head -10
Get approval - Ask if user wants to fetch all or selective
Found 150 URLs from docs.example.com
Preview (first 10):
1. https://docs.example.com/quickstart
2. https://docs.example.com/api/authentication
...
Fetch all 150 pages? Or selective? (all/selective/cancel)
Fetch approved content
# If all:
kurct content fetch --url-prefix https://docs.example.com
# If selective (user specifies path pattern):
kurct content fetch --url-prefix https://docs.example.com/api/
This provides Checkpoint 1 (preview) for the iterative source gathering pattern.
Discover URLs from sitemaps without downloading content.
# Discover all URLs from sitemap
kurct content map https://www.anthropic.com
# Discover with publish dates from blogrolls (recommended for blogs/docs)
kurct content map https://docs.getdbt.com/sitemap.xml --discover-dates
# Limit discovery (useful for testing)
kurct content map https://example.com --limit 10
# Map and fetch immediately
kurct content map https://example.com --fetch
# Discover dates with custom blogroll limit
kurct content map https://example.com --discover-dates --max-blogrolls 5
# JSON output for scripts
kurct content map https://example.com --output json
What happens:
/sitemap.xml, robots.txt, etc.)NOT_FETCHED statusExample output:
✓ Found 317 URLs from sitemap
Created: 317 new documents
✓ https://www.anthropic.com
ID: 6203468a | Status: NOT_FETCHED
✓ https://www.anthropic.com/news/claude-3-7-sonnet
ID: bc2bcf48 | Status: NOT_FETCHED
When to use --discover-dates:
How it works:
published_date populatedis_chronological=True and discovery_method="blogroll"Example:
# Discover docs.getdbt.com with date extraction
kurct content map https://docs.getdbt.com/sitemap.xml --discover-dates
# Output shows date discovery:
# ✓ Found 500 URLs from sitemap
# --- Discovering blogroll/changelog pages ---
# Found 8 potential blogroll/changelog pages
#
# Scraping https://docs.getdbt.com/blog...
# Found 45 posts with dates
# Scraping https://docs.getdbt.com/docs/dbt-versions/...
# Found 23 posts with dates
#
# ✓ Total documents discovered from blogrolls: 68
# New: 12 (not in sitemap)
# Existing: 56 (enriched with dates)
Performance:
--discover-dates: ~5-15 minutes (includes LLM analysis + page scraping)--max-blogrolls (default: 10 pages)Benefits:
If automatic discovery fails with "No sitemap found," use this fallback workflow:
Most sites use standard paths. Try these directly (not base URL):
# Standard path (most common)
kurct content map https://docs.getdbt.com/sitemap.xml
# Alternative paths
kurct content map https://docs.getdbt.com/sitemap_index.xml
kurct content map https://docs.getdbt.com/sitemap/sitemap.xml
kurct content map https://docs.getdbt.com/sitemaps/sitemap.xml
Success if: Kurt finds and processes the sitemap Next if fails: Try Tier 2
Use WebFetch to find sitemap URL in robots.txt:
WebFetch URL: https://docs.getdbt.com/robots.txt
Prompt: "Extract all Sitemap URLs from this robots.txt file"
Then try the discovered sitemap URLs:
kurct content map <sitemap-url-from-robots>
Success if: Sitemap URL found in robots.txt works Next if fails: Try Tier 3
Use WebSearch to discover sitemap location:
WebSearch: "site:docs.getdbt.com sitemap"
WebSearch: "docs.getdbt.com sitemap.xml"
Or check common documentation pages for sitemap links.
Then try discovered URLs with kurct content map
Success if: Sitemap found via search Next if fails: Try Tier 4
If no sitemap exists or is inaccessible, manually collect URLs:
Option A: Use WebSearch to find pages
WebSearch: "site:docs.getdbt.com tutorial"
WebSearch: "site:docs.getdbt.com guide"
Option B: Crawl from homepage
Option C: User provides URL list
Then add URLs manually:
kurct content add https://docs.getdbt.com/page1
kurct content add https://docs.getdbt.com/page2
kurct content add https://docs.getdbt.com/page3
# ❌ Automatic discovery fails
kurct content map https://docs.getdbt.com
# Error: No sitemap found
# ✅ Direct sitemap URL works!
kurct content map https://docs.getdbt.com/sitemap.xml --limit 100
# Success: Found 100 URLs from sitemap
Test if sitemap exists:
# Use WebFetch to check
WebFetch URL: https://example.com/sitemap.xml
Prompt: "Does this sitemap exist? If yes, describe its structure."
Why automatic discovery fails:
When to use each tier:
Download content for a specific document.
# Fetch by document ID
kurct content fetch 6203468a-e3dc-48f2-8e1f-6e1da34dab05
# Fetch by URL (creates document if needed)
kurct content fetch https://www.anthropic.com/company
What happens:
sources/{domain}/{path}/page.mdFETCHED status, content metadataDownload multiple documents in parallel (5-10x faster than sequential).
# Fetch all from domain
kurct content fetch --url-prefix https://www.anthropic.com/
# Fetch all blog posts
kurct content fetch --url-contains /blog/
# Fetch everything NOT_FETCHED
kurct content fetch --all
# Increase parallelism (default: 5)
kurct content fetch --url-prefix https://example.com/ --max-concurrent 10
# Retry failed documents
kurct content fetch --status ERROR --url-prefix https://example.com/
What happens:
Performance:
File structure after fetch:
sources/
└── www.anthropic.com/
├── news/
│ └── claude-3-7-sonnet.md
└── company.md
When sitemap discovery fails or you want to add specific URLs.
# Add URL without fetching
kurct content add https://example.com/page1
kurct content add https://example.com/page2
# Then fetch when ready
kurct content fetch https://example.com/page1
Create document record and fetch content in one step.
# Creates document if doesn't exist, then fetches
kurct content fetch https://example.com/specific-page
If kurct content fetch fails due to anti-bot protection or other issues, use WebFetch as a fallback with automatic import.
When using WebFetch, extract FULL metadata to preserve in the file:
Use WebFetch with this prompt:
"Extract ALL metadata from this page including:
- Full page title
- Description / meta description
- Author(s)
- Published date or last modified date
- Any structured data or meta tags
- The complete page content as markdown
Format the response to clearly show:
1. All metadata fields found
2. The markdown content"
Save the fetched content with YAML frontmatter:
---
title: "Full Page Title from WebFetch"
url: https://example.com/page
description: "Meta description or summary"
author: "Author Name or Organization"
published_date: "2025-10-22"
last_modified: "2025-10-22"
fetched_via: WebFetch
fetched_at: "2025-10-23"
---
# Page Content
[Markdown content from WebFetch...]
Once the file is saved to /sources/, the PostToolUse hook automatically:
Result: File is fully indexed in Kurt with proper title, author, dates, and description!
# 1. Kurt fetch fails
kurct content fetch https://docs.example.com/guide
# → Creates ERROR record
# 2. Use WebFetch (Claude does this automatically)
# Extracts metadata + content
# 3. Save with frontmatter to sources/
# File: sources/docs.example.com/guide.md
# 4. Auto-import hook triggers
# → Updates ERROR record to FETCHED
# → Populates title, author, date from frontmatter
# → Links file to database
# 5. Verify
kurt content get-metadata <doc-id>
# Shows proper title, metadata, FETCHED status
For custom extraction behavior beyond the CLI, use trafilatura Python library directly.
Control crawl depth, URL patterns, language filters, and more.
# See scripts/advanced_crawl_and_import.py
from trafilatura.spider import focused_crawler
todo = focused_crawler(
homepage,
max_seen_urls=100,
max_known_urls=50
)
Trafilatura Crawls Documentation
Fine-tune extraction: precision vs recall, include comments, handle tables.
# See scripts/advanced_fetch_custom_extraction.py
from trafilatura import extract
content = extract(
html,
include_comments=False,
include_tables=True,
favor_precision=True
)
Configure timeouts, minimum text size, date extraction.
# See scripts/custom_extraction_config.py
from trafilatura.settings import use_config
config = use_config()
config.set('DEFAULT', 'MIN_EXTRACTED_SIZE', '500')
| Task | Command | Performance |
|---|---|---|
| Map sitemap | kurct content map <url> | Fast (no downloads) |
| Map with dates | kurct content map <url> --discover-dates | ~5-15 min (LLM scraping) |
| Fetch single | kurct content fetch <id|url> | ~2-3s per doc |
| Batch fetch | kurct content fetch --url-prefix <url> | ~0.4-0.6s per doc |
| Add URL | kurct content add <url> | Instant |
| Review discovered | kurt content list --status NOT_FETCHED | Instant |
| Retry failures | kurct content fetch --status ERROR | Varies |
# URL Discovery
from kurt.ingest_map import (
map_sitemap, # Discover URLs from sitemap
map_blogrolls, # Discover from blogroll/changelog pages
identify_blogroll_candidates, # Find potential blogroll pages
extract_chronological_content, # Extract posts with dates
)
# Content Fetching
from kurt.ingest_fetch import (
add_document, # Add single URL
fetch_document, # Fetch single document
fetch_documents_batch, # Batch fetch (async parallel)
)
# Map sitemap
docs = map_sitemap("https://example.com", limit=100)
# Add document
doc = add_document("https://example.com/page")
# Fetch single
result = fetch_document(document_id="abc-123")
# Batch fetch
results = fetch_documents_batch(
document_ids=["abc-123", "def-456"],
max_concurrent=10
)
See:
| Issue | Solution |
|---|---|
| "No sitemap found" | See detailed guide above: Try direct sitemap URLs (.../sitemap.xml), check robots.txt, or use WebSearch. Full 4-tier fallback documented in "Troubleshooting: Sitemap Discovery Failures" section. |
| Slow batch fetch | Increase --max-concurrent (default: 5, try 10) |
| Extraction quality low | See advanced extraction scripts for custom settings |
| Duplicate content | Kurt automatically deduplicates using content hashes |
| Rate limiting | Reduce --max-concurrent or add delays |
| Content fetch fails | Use WebFetch fallback with frontmatter (see "WebFetch Fallback" section) |