$npx -y skills add Varnan-Tech/opendirectory --skill pricing-finderTell it what your product is (URL or description) and it finds 5 competitors globally, fetches their actual pricing pages, extracts every tier and price point, and returns a complete pricing intelligence report: the dominant pricing model in your space, a benchmark price table, f
| 1 | # Pricing Finder |
| 2 | |
| 3 | Tell it your product URL or description. It finds 5 competitors, fetches their actual pricing pages, and returns a complete pricing intelligence report: dominant model in your space, benchmark price table, feature gate analysis, positioning map, and a concrete pricing recommendation for your product. |
| 4 | |
| 5 | **Zero required API keys.** Runs entirely on free pip dependencies. Optional API keys improve quality. |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | **Zero-hallucination policy:** Every price point, tier name, and feature gate in the output must trace to fetched pricing page content or a DuckDuckGo search snippet. This applies to: |
| 10 | - Competitor prices: extracted verbatim from fetched page content only |
| 11 | - "Contact Sales": recorded as-is, never estimated or replaced with a number |
| 12 | - Tier names: copied exactly from the page, not paraphrased |
| 13 | - Feature lists: extracted from page content, not inferred from product knowledge |
| 14 | - Positioning observations: derived from the benchmark table data only |
| 15 | |
| 16 | --- |
| 17 | |
| 18 | ## Common Mistakes |
| 19 | |
| 20 | | The agent will want to... | Why that's wrong | |
| 21 | |---|---| |
| 22 | | Fill in "Contact Sales" with an estimated price | Never estimate enterprise pricing. Record it as "Contact Sales" exactly. | |
| 23 | | Use training knowledge for competitor prices | Every price must trace to fetched page content or a search snippet. | |
| 24 | | Skip the competitor confirmation step | Always show discovered competitors and wait for confirmation. Wrong competitors = wrong benchmarks. | |
| 25 | | Recommend a price without referencing benchmark data | Every price recommendation must cite a specific number from the benchmark table. | |
| 26 | | Mark a page as high quality when content < 500 chars | < 500 chars means the page was not fetched -- mark data_quality as 'low' and use search snippet fallback. | |
| 27 | | Use em dashes in output | Replace all em dashes with hyphens. | |
| 28 | |
| 29 | --- |
| 30 | |
| 31 | ## Read Reference Files Before Each Run |
| 32 | |
| 33 | ```bash |
| 34 | cat references/pricing-models.md |
| 35 | cat references/extraction-guide.md |
| 36 | cat references/positioning-guide.md |
| 37 | ``` |
| 38 | |
| 39 | --- |
| 40 | |
| 41 | ## Step 1: Setup Check |
| 42 | |
| 43 | ```bash |
| 44 | echo "TAVILY_API_KEY: ${TAVILY_API_KEY:+set (search quality enhanced)}${TAVILY_API_KEY:-not set, DuckDuckGo will be used (free)}" |
| 45 | echo "FIRECRAWL_API_KEY: ${FIRECRAWL_API_KEY:+set (JS rendering enhanced)}${FIRECRAWL_API_KEY:-not set, requests+BS4 will be used (free)}" |
| 46 | echo "" |
| 47 | python3 -c "from ddgs import DDGS; import requests, bs4, html2text; print('Dependencies OK')" 2>/dev/null \ |
| 48 | || echo "ERROR: Missing dependencies. Run: pip install ddgs requests beautifulsoup4 html2text" |
| 49 | ``` |
| 50 | |
| 51 | **If dependencies are missing:** Stop immediately. Tell the user: "Missing Python dependencies. Run this to install them: `pip install ddgs requests beautifulsoup4 html2text` -- all free, no accounts needed. Then try again." |
| 52 | |
| 53 | **If only API keys are missing:** Continue. DuckDuckGo and requests+BS4 are the free defaults. |
| 54 | |
| 55 | Derive product slug: |
| 56 | |
| 57 | ```bash |
| 58 | PRODUCT_SLUG=$(python3 -c " |
| 59 | from urllib.parse import urlparse |
| 60 | import sys, re |
| 61 | url = 'URL_HERE' |
| 62 | if url.startswith('http'): |
| 63 | host = urlparse(url).netloc.replace('www.', '') |
| 64 | print(host.split('.')[0]) |
| 65 | else: |
| 66 | print(re.sub(r'[^a-z0-9]', '-', url[:30].lower()).strip('-')) |
| 67 | ") |
| 68 | echo "Product slug: $PRODUCT_SLUG" |
| 69 | ``` |
| 70 | |
| 71 | --- |
| 72 | |
| 73 | ## Step 2: Parse Input |
| 74 | |
| 75 | Collect from the conversation: |
| 76 | - `product_url`: the URL to fetch (required, unless user pastes a description directly) |
| 77 | - `geography`: optional -- US / Europe / India / global. Default: US |
| 78 | |
| 79 | **If the user provides only a pasted description (no URL):** Skip Steps 3 and 4. Go directly to Step 4 (product analysis) using the pasted text as `product_content`. Set `page_source` to `user_description` and note in `data_quality_flags`. |
| 80 | |
| 81 | **If neither URL nor description:** Ask: "What is the URL of your product or startup? Or paste a short description: what it does, who it's for, and what makes it different." |
| 82 | |
| 83 | --- |
| 84 | |
| 85 | ## Step 3: Fetch Product Page |
| 86 | |
| 87 | **Primary: Firecrawl (if FIRECRAWL_API_KEY is set)** |
| 88 | |
| 89 | ```bash |
| 90 | curl -s -X POST https://api.firecrawl.dev/v1/scrape \ |
| 91 | -H "Authorization: Bearer $FIRECRAWL_API_KEY" \ |
| 92 | -H "Content-Type: application/json" \ |
| 93 | -d '{"url": "URL_HERE", "formats": ["markdown"], "onlyMainContent": true}' \ |
| 94 | | python3 -c " |
| 95 | import sys, json |
| 96 | d = json.load(sys.stdin) |
| 97 | content = d.get('data', {}).get('markdown', '') or d.get('markdown', '') |
| 98 | print(f'Fetched via Firecrawl: {len(content)} characters') |
| 99 | open('/ |