Loading...
Loading...
Programmatic web search and scrape with context isolation. Use for any research task where you need to search the web, filter results, and extract specific information — without flooding your context window with raw HTML and boilerplate. This is the single biggest token-saver in the crw skill set. Triggered by "search for", "look up", "find", "research", "what's the latest on", or any query that requires current web information. Also use when asked to "search and filter", "find the important parts", or any task where you suspect the raw output will be large (multi-page scrapes, news aggregation, competitive research).
npx skill4agent add us/crw crw-dynamic-searchprint()crw search --jsonscrapeOptionsprint()print()print()crw search --jsoncrw scrape --format json# WRONG — raw results flood context, possibly 200K+ characters
crw search "quantum computing 2025" --json
# RIGHT — only your print() enters context
crw search "quantum computing 2025" --json 2>/dev/null | python3 -c "
import json, sys
data = json.load(sys.stdin)
for r in data:
print(f'[{r[\"position\"]}] {r[\"title\"]}')
print(f' {r[\"url\"]}')
print(f' {r[\"description\"][:150]}')
"crw search --json[
{
"title": "string",
"url": "string",
"description": "string (~200-600 chars from the search backend snippet)",
"snippet": "string (alias of description — always same value)",
"position": 1,
"score": 0.85,
"category": "general | news | images | null"
}
]scorenullpositiondescriptiondescriptionsnippetsnippetcategory"general""news""images"published_datecrw scrape --format jsonScrapeData{
"markdown": "string | null",
"html": "string | null",
"links": ["url1", "url2"],
"renderDecision": { "kind": "autoDefault", "chosen": "http" },
"creditCost": 1,
"contentType": "text/html",
"metadata": {
"title": "string | null",
"description": "string | null",
"ogTitle": "string | null",
"ogDescription": "string | null",
"ogImage": "string | null",
"sourceURL": "string",
"language": "string | null",
"statusCode": 200,
"renderedWith": "string | null",
"elapsedMs": 1234
}
}markdownmetadata.titlelinkscrw_searchdataapi.fastcrw.comdata.resultsdata.resultsdata{
"success": true,
"data": {
"results": [
{
"url": "string",
"title": "string",
"description": "string",
"snippet": "string",
"position": 1,
"score": 0.85,
"category": "string | null",
"publishedDate": "string | null"
}
]
}
}scrapeOptionsmarkdownhtmllinksmetadatacrw search "Python 3.13 release date" --json 2>/dev/null | python3 -c "
import json, sys
data = json.load(sys.stdin)
for r in data[:3]:
print(r['title'])
print(r['description'][:300])
print()
"<< 'PYEOF'python3 << 'PYEOF'
import json, subprocess
raw = subprocess.check_output(
['crw', 'search', 'your query', '--json', '--limit', '10'],
stderr=subprocess.DEVNULL
)
data = json.loads(raw)
for r in data:
print(f'[{r["position"]}] {r["title"]}')
print(f' {r["url"]}')
print(f' {r["description"][:200]}')
print()
PYEOF/tmp//tmp/crw_results.json/tmp/filter.py/tmp/python3 << 'PYEOF'
import json, subprocess
raw = subprocess.check_output(
['crw', 'search', 'solid-state battery commercialization 2025',
'--json', '--limit', '10'],
stderr=subprocess.DEVNULL
)
data = json.loads(raw)
# Save raw — stays on disk, never enters context
with open('/tmp/crw_results.json', 'w') as f:
json.dump(data, f)
# Print only what you need to pick next steps
# Sort by position (rank), not score — score is unreliable from the search backend
print(f'{len(data)} results saved to /tmp/crw_results.json\n')
for r in data:
print(f'[{r["position"]}] {r["title"][:90]}')
print(f' {r["url"]}')
print(f' {r["description"][:150]}')
print()
PYEOF/tmp/crw_results.jsonpython3 << 'PYEOF'
import json, subprocess
data = json.load(open('/tmp/crw_results.json'))
# Indices you chose from the triage in turn 1
for r in [data[0], data[2], data[4]]:
# Scrape the full page for results that looked relevant
try:
raw = subprocess.check_output(
['crw', 'scrape', r['url'], '--format', 'json'],
stderr=subprocess.DEVNULL, timeout=30
)
page = json.loads(raw)
except Exception:
continue
md = page.get('markdown') or ''
if not md:
continue
print(f'## {r["title"]}')
print(f'URL: {r["url"]}\n')
# Write filtering logic that matches the query — this is the key step
# Example: keep paragraphs about commercialization timelines
for para in md.split('\n\n'):
para = para.strip()
if len(para) > 80 and any(kw in para.lower() for kw in
['toyota', 'quantumscape', 'samsung', 'production',
'commercializ', '2025', '2026', 'gigafactory']):
print(para)
print()
print('---\n')
PYEOFpython3 << 'PYEOF'
import json, subprocess
# A URL you found referenced in the content you read in turn 2
raw = subprocess.check_output(
['crw', 'search', 'QuantumScape QSE-5 production timeline Q4 2025',
'--json', '--limit', '5'],
stderr=subprocess.DEVNULL
)
data = json.loads(raw)
for r in data[:3]:
print(f'## {r["title"]}')
print(f'URL: {r["url"]}')
print(r['description'])
print()
PYEOFposition: 1, 2, 3...print(f'## {title}')
print(f'URL: {url}\n')
print(relevant_content)
print('---\n')try:
raw = subprocess.check_output(['crw', 'scrape', url, '--format', 'json'],
stderr=subprocess.DEVNULL, timeout=30)
except Exception:
continueprint()python3 << 'PYEOF'
import json, subprocess
# Fan out: hit the same topic from multiple angles
queries = [
('general', 'EU AI Act compliance requirements 2025'),
('specific', 'EU AI Act high-risk AI systems Article 6 obligations'),
]
all_results = []
for label, q in queries:
raw = subprocess.check_output(
['crw', 'search', q, '--json', '--limit', '8'],
stderr=subprocess.DEVNULL
)
results = json.loads(raw)
for r in results:
r['_query'] = label
all_results.extend(results)
# Deduplicate by URL
seen = set()
unique = []
for r in all_results:
if r['url'] not in seen:
seen.add(r['url'])
unique.append(r)
# Save everything
with open('/tmp/eu_ai_results.json', 'w') as f:
json.dump(unique, f)
# Print triage sorted by position within each query batch
print(f'{len(unique)} unique results from {len(queries)} queries\n')
for r in unique[:12]:
print(f'[{r["_query"]}][pos {r["position"]}] {r["title"][:80]}')
print(f' {r["url"]}')
print(f' {r["description"][:120]}')
print()
PYEOFpython3jq# Print titles and URLs only
crw search "query" --json 2>/dev/null | jq '.[] | {title, url, description: .description[:200]}'
# Filter by keyword in description
crw search "query" --json 2>/dev/null | jq '[.[] | select(.description | ascii_downcase | contains("keyword"))]'crw search "query" # text output (default)
crw search "query" --json # JSON array
crw search "query" --json --fields title,url,snippet # projected fields only
crw search "query" --json --limit 5 # cap results
crw search "query" --category news --time-range week # news, last 7 days
crw scrape "https://example.com" # markdown
crw scrape "https://example.com" --format json # full ScrapeData JSON
crw scrape "https://example.com" --format json -o /tmp/page.json--fieldscrw search --jsontitleurldescriptionsnippetpositionscorecategory