crw-map — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited crw-map (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
crawl — map first, then crawl only the section you need.
with crw-scrape (single pages) or crw-crawl (bulk). Map is URL-only — no page content is returned.
crw map docs.example.com | wc -l tells you howmany pages a subsequent crawl would touch before you commit.
grep instead ofcrawling the whole site.
CLI (binary on PATH):
crw map "https://docs.example.com" # URLs to stdout
crw map "https://docs.example.com" -d 3 --format json # JSON object, depth 3
crw map "https://example.com" --sitemap-only # sitemap.xml only
crw map "https://example.com" --no-sitemap # link crawl only
crw map "https://example.com" --format json > .crw/urls.jsonMCP (inside an agent harness):
crw_map(url="https://docs.example.com")
crw_map(url="https://docs.example.com", maxDepth=3, limit=200)
crw_map(url="https://example.com", useSitemap=false) # link crawl only
crw_map(url="https://example.com", crawlFallback=false) # sitemap onlyREST (drop-in for Firecrawl SDKs — just swap the base URL):
curl -X POST "$CRW_API_URL/v1/map" -H "Authorization: Bearer $CRW_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url":"https://docs.example.com","maxDepth":2,"limit":200}'
# Response: {"success":true,"data":{"links":[...]}} — links are under data.links
# jq tip for REST: jq '.data.links[]'| Need | CLI flag | MCP / REST field | |
|---|---|---|---|
| Discovery depth | -d/--depth N (default 2) | maxDepth (default 2) | |
| Result format | `--format text\ | json` | — (always JSON) |
| Sitemap only (no link crawl) | --sitemap-only | crawlFallback: false | |
| Link crawl only (no sitemap) | --no-sitemap | useSitemap: false | |
| Cap URL count | — | limit (default 100; 0 = unbounded) | |
| JS rendering | --js | — | |
| Proxy | --proxy URL | — | |
| Stealth mode | --stealth | — | |
| Rate limit | --rate-limit N (default 5.0 req/s) | — | |
| Concurrency | --concurrency N (default 10) | — | |
| Per-page timeout | --timeout MS (default 15000) | — |
MCP truncates to 100 URLs by default (truncated: true + totalDiscovered in response). Pass limit: 0 to opt out.
# 1. Map to see what's there
crw map "https://docs.example.com" --format json > .crw/urls.json
# 2a. Grep for the section you need
grep '"authentication"' .crw/urls.json
# 2b. Scrape a single page
crw scrape "https://docs.example.com/api/authentication"
# 2c. Or crawl the whole /api section
crw crawl "https://docs.example.com/api" -d 2 -l 50With MCP in a single agent turn:
crw_map(url="https://docs.example.com", limit=0)
# inspect links[], pick the /changelog/* subset
crw_crawl(url="https://docs.example.com/changelog", maxDepth=1, maxPages=20)crawl abort. If the map returns 5 000 URLs and you only need /blog/*, scope the crawl to that sub-path.
gives canonical URLs; the BFS link scan catches pages not in the sitemap. Use --sitemap-only only when you trust the sitemap is complete.
wikis; 1 is enough to enumerate top-level sections.
grep, jq '.links[]' (CLIJSON output), or wc -l rather than loading the full list into model context. For REST responses use jq '.data.links[]' (links are nested under data).
content, follow up with crw scrape or crw crawl.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.