agentsclimarketplace

Skill

Skill Hectelion-SA/claude-investor-shortlist/skill

Build a structured Excel investor shortlist (M&A or fundraising mandate) by combining local investor databases, Outlook contacts, web search (Firecrawl) and email enrichment (Dropcontact). Output is a 2-tab .xlsx (branded cover page + 31-column investor table with full transaction pipeline). Trigger when the user says "build an investor list", "investor shortlist", "shortlist for X", "M&A target list", or invokes /investor-shortlist.From its SKILL.md

Install
npx -y skills add Hectelion-SA/claude-investor-shortlist --skill skill

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

4 things to look at

  • reads credentialsReads from 2 credential sources: `config.yaml > dropcontact.api_key` and 1 more.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 2 commands, including `Get-Process EXCEL | ForEach-Object { $_.CloseMainWindow() }` and 1 more.
  • fetches URLsInstructs the agent to fetch 1 URL, including https://api.dropcontact.io/batch.

SKILL.md

14.8 KB, ~4.0k tokens by cl100k_base, as published. Nobody here has run it

Skill: /investor-shortlist — Investor Shortlist Builder

Objective

Full pipeline questionnaire → multi-source research → Dropcontact + Outlook + Firecrawl enrichment → branded Excel output with transaction pipeline columns.

The output file matches a standardized M&A advisory format used for sell-side, buy-side and fundraising mandates.

Configuration is read from config.yaml in the same folder as this skill. See config.example.yaml for the schema. Important keys:

  • dropcontact.api_key (or env DROPCONTACT_API_KEY)
  • local_databases — list of Excel files to scan
  • output.default_folder — suggested save path
  • brand.* — firm name, colors, font for the cover page + table

Step 1 — Structured questionnaire (MANDATORY before any action)

Ask ALL questions below, grouped in 2-3 AskUserQuestion calls, never as bullet plain-text. If the user skips a question, re-ask with an explicit default value.

Block A — Target company & mandate

  1. Client company name (e.g. "Acme SA") + website (e.g. "acme.com")
  2. Company country: 🇨🇭 Switzerland / 🇫🇷 France / 🇲🇨 Monaco / 🇱🇺 Luxembourg / Other
  3. Mandate type:
    • Fundraise (capital growth, product development, geographic expansion)
    • M&A sell-side (full or partial sale)
    • M&A buy-side (external growth — target search)
    • Refinancing / Debt (senior, mezzanine)
    • Restructuring (capital, debt)

Block B — Target profile

  1. Sector: e.g. "Real estate / Construction", "Industrial", "Tech / SaaS", "Healthcare / MedTech", "Energy", "B2B services", etc.

  2. Sub-sector (optional): e.g. "Residential development", "B2B HR SaaS"

  3. If Fundraise → Round:

    • Pre-seed (<500k)
    • Seed (500k - 2M)
    • Series A (2-10M)
    • Series B (10-30M)
    • Series C / Growth (>30M)
    • Late stage / Pre-IPO
  4. If M&A → Valuation range: e.g. "2-10M", "10-50M", "50-200M", "200M+"

Block C — Volume & typology

  1. Number of target investors in the shortlist: 15-20 / 20-30 / 30-50 / 50+
  2. Typology (multi-select):
    • Private / HNWI / Family offices
    • Financial institutional (PE funds, VC, AM, pension funds, banks)
    • Strategic / Industrial (sector players, competitors, suppliers/customers)
    • Public / Para-public (cantonal banks, sovereign funds, foundations)
  3. Investor geography: same country as target / pan-European / global

Block D — Sources & execution

  1. Source mix:
    • Local only (local Excel databases + Outlook contacts only)
    • Internet only (Firecrawl/Brave search + Dropcontact)
    • Hybrid (recommended — local + internet in parallel)
  2. Save path: ask for absolute Windows path, or propose default from config.yaml > output.default_folder
  3. Filename: auto-generated from config.yaml > output.filename_template or ask for custom

Step 2 — Multi-source research

2.1 — Local databases (if Local or Hybrid)

Read every file listed in config.yaml > local_databases. The skill auto-detects the header row by looking for columns matching patterns like:

  • company, name, firm, investor → investor name
  • email, mail, contact email → contact email
  • country, pays → country
  • focus, sector, theme, specialty → investment focus
  • phone, tel, mobile → phone
  • first name, prénom, last name, nom, surname → person

Filter by sub-sector / country / typology matching the brief. Score relevance 1-5.

If no local databases configured → skip this step and rely on internet + Dropcontact.

2.2 — Outlook contacts (Windows only, if outlook.scan_contacts: true)

Scan local Outlook contacts via PowerShell COM to identify investors already in your address book. Cross-reference by:

  • CompanyName (fuzzy match with identified investors)
  • Email domain (match with investor websites)

Reference PowerShell script (inline):

$outlook=New-Object -ComObject Outlook.Application
$ns=$outlook.GetNamespace("MAPI")
$contactsFolder=$ns.GetDefaultFolder(10)
$results=New-Object System.Collections.ArrayList
function ProcessFolder($folder, $list){
  foreach($item in $folder.Items){
    if($item.Class -eq 40){
      [void]$list.Add([PSCustomObject]@{
        FullName=$item.FullName; FirstName=$item.FirstName; LastName=$item.LastName
        CompanyName=$item.CompanyName; JobTitle=$item.JobTitle
        Email1=$item.Email1Address; Email2=$item.Email2Address
        BusinessPhone=$item.BusinessTelephoneNumber; MobilePhone=$item.MobileTelephoneNumber
        WebPage=$item.WebPage; Categories=$item.Categories
      })
    }
  }
  foreach($sf in $folder.Folders){ ProcessFolder $sf $list }
}
ProcessFolder $contactsFolder $results
foreach($store in $ns.Stores){
  try{
    $root=$store.GetRootFolder()
    foreach($f in $root.Folders){
      if($f.DefaultItemType -eq 2){ ProcessFolder $f $results }
    }
  }catch{}
}
$results | ConvertTo-Json -Depth 3 | Out-File -FilePath "$env:TEMP\_outlook_contacts.json" -Encoding utf8

Read the JSON in utf-8-sig (Windows BOM).

A hit in Outlook = the user already has a direct relationship with the contact → score boost, no Dropcontact call needed (Outlook email is more reliable than enriched email).

2.3 — Internet search (if Internet or Hybrid)

For each target with no clear decision-maker, use Firecrawl MCP (or your preferred web search) with focused queries:

"COMPANY_NAME" CEO managing director 2025 OR 2026
"COMPANY_NAME" managing partner OR président
"COMPANY_NAME" investor relations contact

Always double-check names (current CEO vs former, role changes, company rebrandings). Common pitfalls:

  • A CEO can have left up to 12 months ago — cross-check via news
  • Funds rebrand (e.g. acquisition-driven name changes) — verify current legal name
  • Asset managers often have multiple legal entities — pick the one matching the investment thesis

2.4 — Dropcontact enrichment (ALWAYS, unless Outlook email already validated)

API key from config.yaml > dropcontact.api_key or env DROPCONTACT_API_KEY. Never hardcode the key in the script.

Endpoint: POST https://api.dropcontact.io/batch

Payload:

{
  "data": [
    {"first_name": "First", "last_name": "Last", "company": "Company", "website": "domain.com"}
  ],
  "siren": false
}

Poll GET /batch/{request_id} every 15s (up to 40 attempts).

Returned fields: email[0].email, email[0].qualification (nominative@pro, catch-all@pro, not_found), phone[0].number.

Multi-pass strategy: if Dropcontact returns "Not found", search alternative decision-makers (CFO, Head of M&A, Managing Partner) via Firecrawl, then re-run Dropcontact.


Step 3 — Excel file generation

3.1 — File structure (2 tabs — NO Synthesis tab)

Tab 1: "Cover page" — minimal format (REQUIRED)

No content beyond the 6 lines below. Do NOT add enrichment sources, statistics, score legend, or important notes (this content goes in the chat summary post-generation, not in the file).

CellContentStyle
B2{brand.firm_name} (from config)font_family 14, primary_color, italic
B5{Client Company} — {Mandate type}font_family 25, primary_color
B6Investor shortlist {sector context}font_family 18, secondary_color, italic
B8Prepared for: {Title First Last [and Co-founder]}, {Company}font_family 11
B9Date: {DD MMM YYYY in English, e.g. "21 May 2026"}font_family 11
B10Targets: {N} investors {Country} ({typologies comma-separated})font_family 11

Concrete example (placeholder):

  • B2: "Acme M&A LLP"
  • B5: "Example SA — Series A+ Fundraise"
  • B6: "Investor shortlist MedTech / FemTech Switzerland"
  • B8: "Prepared for: Dr. John Doe and Jane Smith, Example SA"
  • B9: "Date: 21 May 2026"
  • B10: "Targets: 48 investors Switzerland (financial, family offices, strategic, public)"

Tab 2: "Investors" — 31 columns (header row = 4)

Identification block (cols 1-14):

  1. # (rank)
  2. Category (e.g. "Developer / Promoter CH", "Asset Manager RE CH", "Pension fund CH", etc.)
  3. Investor (legal name)
  4. Country (with flag emoji)
  5. City / Region
  6. Type (e.g. "Real estate developer", "Listed RE fund manager")
  7. Focus / Specialty (sector detail + ticket size)
  8. Civ. (Mr / Ms)
  9. First name
  10. Last name
  11. Title / Role
  12. Email (hyperlink mailto:)
  13. Phone
  14. Website (hyperlink https://)

Scoring block (col 15): 15. Score (1-5 with color coding from brand.accent_*: 5=green, 4=pale blue, 3=grey, 2=orange)

Transaction pipeline block (cols 16-31): 16. Type (empty at creation — fill manually: "Hot lead", "Warm lead", etc.) 17. Status (empty — "Not contacted", "Contacted", "Replied", "Meeting", "Pitch", "DD", "Closed-Won", "Closed-Lost") 18. Contacted by (initials — from defaults.prepared_by_initials) 19. Last contact (date of last exchange) 20. First intent email sent (X = sent) 21. Email date 22. Teaser sent (X) 23. NDA sent (X) 24. Teaser & NDA date 25. IM and process letter sent (X) 26. IM & process letter date 27. Management presentation (pitch) date 28. MBO/LOI reception date 29. Dataroom opening 30. Signing 31. Closing

All pipeline columns (16-31) are empty at creation — filled in as the transaction progresses.

IMPORTANT: do NOT create a "Synthesis" tab. The file contains only 2 tabs: "Cover page" + "Investors". The statistical summary (count by category, email quality, etc.) is delivered in the post-generation chat message, not in the file.

3.2 — Branding (from config.yaml)

Read brand.* from config.yaml. Defaults shown below match Hectelion SA original styling; override in config for your firm.

# Loaded from config['brand']:
primary_color    = "182E4E"   # main navy
secondary_color  = "0E2841"   # darker navy
accent_pale      = "DCEAF7"   # score 4
accent_green     = "6FCF9A"   # score 5
accent_orange    = "FFC000"   # score 2
accent_grey      = "F2F2F2"   # score 3
alert_red        = "C00000"   # alerts
border_grey      = "D9D9D9"   # cell borders
font_family      = "Cardo"    # cover page + table

# Grid: Cover page 25 / 18 / 14 / 11
# Table: header 11 bold white, data 10 (dense cells)
# Same font across the whole file — single source of truth.

3.3 — Header row style (Investors table)

  • Fill: primary_color solid
  • Text: White, font_family 11pt Bold
  • Alignment: left, center vertical, wrap_text
  • Border: thin border_grey
  • Header row height: 32

3.4 — Data rows (Investors table)

  • Font: font_family 10pt
  • Investor (col 3): font_family 10pt Bold primary_color
  • Email (col 12): hyperlink mailto, font_family 10pt color #0563C1 underline
  • Website (col 14): hyperlink https, font_family 10pt color #0563C1 underline
  • Score (col 15): centered, font_family 10pt primary_color bold, fill by value
  • Data row height: 70 (wrap text)
  • Freeze panes: header row + first 3 columns

Step 4 — Save

  1. Verify destination folder exists; create it if not
  2. If file already open in Excel: close Excel via PowerShell Get-Process EXCEL | ForEach-Object { $_.CloseMainWindow() } before saving
  3. Save the .xlsx file
  4. Optionally open the file automatically: Start-Process "{path}"
  5. Confirm to the user with a clickable markdown link: [{filename}.xlsx]({relative_or_absolute_path})

Step 5 — Final report to the user

After generation, present:

## Enrichment summary

**N/Total operational emails (X%)**

| Source | Count |
|---|---|
| ✅ Dropcontact nominative | ... |
| 🟦 Dropcontact catch-all  | ... |
| 📇 Outlook (your base)    | ... |
| ⚠ Standard to confirm    | ... |
| ❓ To clarify             | ... |

## Top X high-priority targets (score 5)
1. ...
2. ...

List any emails not found + reason (opaque public funds, low-visibility companies, etc.) with a recommended action (LinkedIn DM, formal letter, etc.).


Best practices

Deduplication

  • Before export, dedup by email (one email = one row max)
  • If same company but 2 decision-makers: keep the most senior / sector-relevant
  • NEVER contact 2 people at the same company with separate emails

Contact details

  • If Dropcontact email = catch-all@pro → flag in column, keep but mark
  • If not found → fallback info@{domain} + alternative decision-maker search (CFO, MD)
  • Phone: prefer direct mobile if Dropcontact returns one

Name verification

  • Always validate that the decision-maker currently holds the position (CEOs change)
  • Cross-reference Dropcontact name with Firecrawl news if any doubt
  • For large institutions: scan the latest annual report / press release if available

LinkedIn fallback

  • For non-Outlook contacts, optionally add a "LinkedIn" column with a pre-generated search URL: https://www.linkedin.com/search/results/people/?keywords={urllib.parse.quote(f"{first} {last} {company}")}
  • Cell display: "🔗 Search" hyperlink colored #0A66C2

Data security

  • NEVER commit the Dropcontact API key to a public repo (config.yaml is in .gitignore)
  • Excel files containing emails and phones should be treated as confidential client data
  • Save shortlists to a controlled folder (OneDrive/SharePoint with client access controls)

Reference script

See build_shortlist.py in this skill folder — Python reference implementation, configurable via config.yaml.


Anti-patterns to avoid

  • ❌ Skipping the questionnaire and inventing a generic list
  • ❌ Calling Dropcontact without checking Outlook first (existing contacts are highest quality)
  • ❌ Defaulting all emails to info@ out of laziness — always try Dropcontact first
  • ❌ Hardcoding the Dropcontact API key in the script — use config.yaml or env var
  • ❌ Hardcoding firm branding in the script — read from config.brand
  • ❌ Creating a "Synthesis" tab — the file has EXACTLY 2 tabs (Cover + Investors); the stats summary goes in the chat
  • ❌ Overloading the cover page (sources, score legend, statistics) — minimal format, 6 lines only (B2/B5/B6/B8/B9/B10)
  • ❌ Keeping rows with no email — by default, filter all rows without operational email before export (unless user explicitly asks to keep them)
  • ❌ Forgetting the pipeline columns (16-31) — that's the main value-add of the file
  • ❌ Listing CEO names without verifying they're still in post
  • ❌ Skipping the cover page — it's the visual recap of the file

What ships with it: 1 file

20.4 KB alongside SKILL.md, 1 of them executable

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.