Install
openclaw skills install submit-directoriesUse when submitting a product to AI/startup directories - covers the full pipeline from collecting product info, analyzing directories, discovering forms, au...
openclaw skills install submit-directoriesFull lifecycle for submitting a product to 800+ AI tool directories: collect product info → analyze directories → build submission plan → discover forms → auto-submit → manual browser submissions → track progress.
pip install -r requirements.txt
playwright install chromium
Never hardcode credentials in scripts. Set these before running any pipeline step:
# Required
export SUBMIT_PRODUCT_URL="https://yourproduct.com"
export SUBMIT_PRODUCT_NAME="Your Product Name"
export SUBMIT_TAGLINE="Your one-line tagline"
export SUBMIT_EMAIL="you@throwaway.com" # use throwaway email
export SUBMIT_AUTHOR_NAME="Jane Doe"
# Recommended
export SUBMIT_AUTHOR_FIRST="Jane"
export SUBMIT_AUTHOR_LAST="Doe"
export SUBMIT_USERNAME="youruser"
export SUBMIT_PASSWORD="throwaway-pass" # use throwaway password
# Optional
export SUBMIT_GITHUB_URL="https://github.com/you/repo"
export SUBMIT_TWITTER_URL="https://twitter.com/yourhandle"
export SUBMIT_KEYWORDS="ai,saas,marketing,automation"
export SUBMIT_LOGO="logo.png" # relative to script dir
export SUBMIT_SCREENSHOT="site-image.png" # relative to script dir
Tip: save these to a local .env file (already in .gitignore) and load with:
set -a && source .env && set +a
logo.png — product logo (used for file upload fields)site-image.png — product screenshot (used for file upload fields)Both should be in the same directory as the scripts.
Ask one at a time (never dump all at once):
| # | Field | Question |
|---|---|---|
| 1 | Product URL | "What is your product/startup website URL?" |
| 2 | Product Name | "What is your product name?" |
| 3 | Tagline | "Give me a one-line tagline." |
| 4 | Description | "Write 2-3 sentences: what it does, who it's for, what makes it different." |
| 5 | Pricing | "What is your pricing model?" (Free / Freemium / Open Source / Paid) |
| 6 | Keywords | "List 5-7 category keywords." |
| 7 | "What email for submissions?" | |
| 8 | Name | "What name on submissions?" (get first + last separately too) |
| 9 | Username | "Preferred username for sites requiring registration?" |
| 10 | Password | "Throwaway password for sites requiring registration?" ⚠️ Use a throwaway — never a real password. Set via SUBMIT_PASSWORD env var; passwords are stripped from submission_plan.json before saving. |
| 11 | GitHub URL | (optional) |
| 12 | Twitter/X | (optional) |
Then ask submission preferences:
Assets: Tell user to place logo.png and site-image.png in project root.
submission_plan.jsoncheckpoint.md with product info (omit passwords).venv/bin/python analyze_directories.py # HTTP-level: auth, captcha, pricing, dead domains
.venv/bin/python cleanup_and_categorize.py # Triage errors, build browser_check_list.json
.venv/bin/python browser_verify.py # Playwright verification (10 concurrent workers)
.venv/bin/python browser_verify.py --recheck-unknown # Deep recheck unknowns
Report auth type breakdown when done.
Filter directories.json:
site_status = activeauth_type = none OR auth_type = email_passwordgoogle_only / google_and_email only if user opted inCreate submission_plan.json entries with copy variation (rotate evenly), credentials, status: pending.
.venv/bin/python discover_forms.py
Visits each submission URL, extracts form field metadata, updates submission_plan.json. Report: discovered / not found / timeout counts.
.venv/bin/python submit_directories.py
Report: submitted / no matching fields / timed out / needs manual attention.
Use Playwright MCP (mcp__playwright namespace) for sites needing manual interaction.
browser_navigate → submission URLbrowser_snapshot → understand pagebrowser_fill_form / browser_type → fill all fieldsbrowser_click submit → verify confirmationbrowser_navigate → login pagebrowser_tabs to switch between OAuth popup and main tabbrowser_evaluate to set content directlybrowser_click dropdown → click optionbrowser_snapshot after each step for new fieldsbrowser_file_upload for logo/screenshotRequirements: gh CLI installed and authenticated (gh auth login). Set SUBMIT_GITHUB_URL if you want your repo linked in entries.
For awesome-list directories:
gh repo fork <owner>/<repo>
# Create branch, add product entry following repo format
gh pr create
Record PR URL in checkpoint.md.
Update checkpoint.md after each phase with: counts by status, successful list, failed list with reasons, next steps.
| Status | Meaning |
|---|---|
submitted | Confirmed submitted |
skipped_paid | Requires payment |
skipped_login_required | Requires account creation |
captcha | Needs manual captcha solve |
no_form_found | No submission form on page |
no_fields_matched | Form exists, no fields matched |
timeout / submit_timeout | Page/submit timed out |
cloudflare_blocked | Cloudflare challenge |
domain_parked | Dead domain |
submission_plan.json automatically before each save.| Blocker | Frequency | Detection |
|---|---|---|
| Paid listing | ~20% | Pricing page, Stripe links, "$" on submit page |
| reCAPTCHA / Turnstile | ~10% | iframe[src*=recaptcha] or [data-turnstile] |
| Login required | ~15% | Redirect to /login on submit URL |
| Newsletter-only forms | ~10% | Looks like submit but is email signup |
| Domain parked/dead | ~8% | No content, DNS failure |
| Cloudflare blocked | ~3% | Challenge page, 403 |
| Reciprocal link required | ~5% | Old web directories requiring backlink |
| File | Purpose |
|---|---|
directories.json | Master database (827+ directories) |
submission_plan.json | Targets with copy, fields, status (no credentials stored) |
checkpoint.md | Progress tracking — source of truth |
analyze_directories.py | HTTP-level analysis |
cleanup_and_categorize.py | Triage + browser check list |
browser_verify.py | Playwright browser verification |
discover_forms.py | Form field discovery |
submit_directories.py | Auto-submission engine |