skills/capabilities/crustdata-supabase/SKILL.md
Search CrustData People Search API for ICP-matching leads with automatic Supabase deduplication. Queries existing leads in the database, passes them as exclude_profiles to CrustData, fetches only net-new leads, and upserts results. Supports pagination, rate limiting, test mode, and reusable configs.
npx skillsauth add athina-ai/goose-skills crustdata-supabaseInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Search for ICP-matching leads using CrustData's People Search API with automatic deduplication against a Supabase database. Each run fetches only net-new leads — existing database entries are excluded at the API level via CrustData's exclude_profiles feature.
You need a Supabase project with URL and service role key. Add to .env:
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
The full database schema lives in tools/supabase/schema.sql. Run it via the Supabase SQL Editor or using the setup script:
python3 tools/supabase/setup_database.py
This creates 6 tables: runs, companies, people, signals, enrichment_log, outreach_log. This skill writes to the people table (dedup by linkedin_url UNIQUE constraint).
Ensure CRUSTDATA_API_TOKEN is set in .env.
Ask the user these questions to build the CrustData filter config:
Build the filters array using CrustData's exact filter format. Each filter is:
{
"filter_type": "FILTER_NAME",
"type": "in" or "not in",
"value": ["value1", "value2"]
}
Available filter types: CURRENT_TITLE, PAST_TITLE, CURRENT_COMPANY, PAST_COMPANY, COMPANY_HEADQUARTERS, COMPANY_HEADCOUNT, REGION, INDUSTRY, SENIORITY_LEVEL, FUNCTION, YEARS_AT_CURRENT_COMPANY, YEARS_IN_CURRENT_POSITION, YEARS_OF_EXPERIENCE, COMPANY_TYPE, PROFILE_LANGUAGE, SCHOOL, KEYWORD, FIRST_NAME, LAST_NAME.
Boolean filters (no type/value): RECENTLY_CHANGED_JOBS, POSTED_ON_LINKEDIN, IN_THE_NEWS.
For titles, fuzzy_match: true can be added for broader matching.
Save config:
skills/crustdata-supabase/configs/{client-name}.json
Config JSON structure:
{
"client_name": "happy-robot",
"search_config_name": "growth-leaders-sf",
"icp_segment": "growth-leaders",
"filters": [
{
"filter_type": "CURRENT_TITLE",
"type": "in",
"value": ["Head of Growth", "VP Growth", "Director of Growth"],
"fuzzy_match": true
},
{
"filter_type": "REGION",
"type": "in",
"value": ["San Francisco Bay Area"]
},
{
"filter_type": "COMPANY_HEADCOUNT",
"type": "in",
"value": ["51-200", "201-500", "501-1,000"]
},
{
"filter_type": "INDUSTRY",
"type": "in",
"value": ["Software Development", "Technology, Information and Internet"]
}
],
"post_processing": {
"strict_title_and_company_match": false,
"exclude_names": []
},
"max_pages": 20,
"mode": "standard"
}
CRITICAL: Never upsert leads to Supabase without explicit user approval.
This skill writes to the people table. Unwanted writes pollute the database, and cleaning up bad entries across multiple test runs is painful.
Required flow:
--preview first to show total matching count and cost estimate--test to fetch a small sample (~25 leads) — present results to the user before any database writeThe agent must NEVER pass --yes on a first run. The --yes flag is only for pre-approved automated runs where the user has already reviewed and confirmed the filters work correctly.
If the user hasn't approved the upsert: Export the CSV and show sample results. Let the user review. Only proceed to upsert after they confirm.
python3 skills/crustdata-supabase/scripts/prospect_search.py \
--config skills/crustdata-supabase/configs/{client-name}.json \
[--test] [--yes] [--preview] [--dry-run]
Flags:
--config (required) — path to client config JSON--test — limit to 1 page / 25 results max--yes — skip cost confirmation prompt. Only use for pre-approved automated runs, never on first runs.--preview — show total matching count only (5 credits)--dry-run — show what would happen, no API callsStep 1: Connect to Supabase — Verify connection, count existing leads.
Step 2: Fetch existing URLs — SELECT all linkedin_url from people table for dedup.
Step 3: Build CrustData payload — Combine user filters with exclude_profiles from Supabase.
Step 4: Search page 1 — Get first 25 results + total_display_count. Show cost estimate.
Step 5: Paginate — Fetch remaining pages with 4s delay between requests (rate limit: 15 req/min).
Step 6: Present results to user — Show sample leads (names, titles, companies) and ask for explicit approval before writing to the database.
Step 7: Upsert to Supabase — Only after user approval. Insert new leads, update existing on conflict (linkedin_url UNIQUE).
Step 8: Export CSV — Write results to output/{client-name}-{timestamp}.csv.
| Parameter | Test | Standard | Full | |-----------|------|----------|------| | Max pages | 1 | 20 | 100 | | Max results | 25 | 500 | 2,500 | | Est. credits | 5-25 | 25-500 | 100-2,500 |
CrustData charges 1 credit per profile returned (minimum 5 per request). Preview mode costs 5 credits. Always run --preview or --test first to verify filters before a full run.
Present results:
Common adjustments:
fuzzy_match: true), broaden regionsmax_pages or switch to test modeNew leads are stored in the people table with full CrustData data including email, title, company, location, industry, and headcount. Each person is tagged with client_name, search_config_name, and icp_segment for traceability.
Exported to skills/crustdata-supabase/output/{client-name}-{timestamp}.csv:
| Column | Description | |--------|-------------| | Name | Full name | | Title | Current job title | | Company | Current company name | | Company LinkedIn URL | Company page URL | | Company Website | Company domain | | Company Industry | Industry | | Company Headcount | Employee count | | Company Type | Public, Private, etc. | | Person LinkedIn URL | Profile URL | | Region | Geographic location | | Headline | LinkedIn headline | | Years of Experience | Total YoE | | Connections | LinkedIn connection count | | Skills | Semicolon-separated skills | | Email | Business email (if available) |
Trigger phrases:
Preview (count only):
python3 skills/crustdata-supabase/scripts/prospect_search.py \
--config skills/crustdata-supabase/configs/happy-robot.json --preview
Test run (review results before approving DB write):
python3 skills/crustdata-supabase/scripts/prospect_search.py \
--config skills/crustdata-supabase/configs/happy-robot.json --test
Full run (only after user approves test results):
python3 skills/crustdata-supabase/scripts/prospect_search.py \
--config skills/crustdata-supabase/configs/happy-robot.json
POST https://api.crustdata.com/screener/person/search/Authorization: Token {CRUSTDATA_API_TOKEN}post_processing.exclude_profiles — array of LinkedIn URLs to skipCrustdata/Crustdata_documentation/people-docs/realtime-searchapi.mdCrustdata/Crustdata_documentation/how_to_build_people_filters.mdcontent-media
Takes an existing screen recording or demo video and adds professional zoom/pan effects synchronized to the narration. Uses transcript-driven zoom targeting and Remotion for rendering. Optionally replaces audio with a soundtrack.
tools
Repurposes long-form video (podcasts, interviews, talks) into short-form vertical clips for Instagram Reels, TikTok, and YouTube Shorts. Handles transcription, moment selection, clip extraction, speaker-tracked reframing (16:9 to 9:16), and animated captions.
development
Creates talking head videos from any source material (docs, changelogs, blog posts, notes, transcripts). Produces multi-scene videos with avatar narration over screenshots/images using HeyGen v2 API. Supports Quick Shot and Full Producer modes.
tools
Generates Instagram-ready product reels from any e-commerce product page URL. Scrapes product images, classifies by type, generates AI-animated clips via Higgsfield API, creates text overlays with style presets, and composes a 15-20 second reel with music. Supports model-based and product-only reels.