openleads 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. openleads-2.0.0/LICENSE +133 -0
  2. openleads-2.0.0/PKG-INFO +256 -0
  3. openleads-2.0.0/README.md +217 -0
  4. openleads-2.0.0/automation.py +14 -0
  5. openleads-2.0.0/lead_engine.py +48 -0
  6. openleads-2.0.0/openleads/__init__.py +22 -0
  7. openleads-2.0.0/openleads/__main__.py +5 -0
  8. openleads-2.0.0/openleads/_http.py +54 -0
  9. openleads-2.0.0/openleads/cache/__init__.py +4 -0
  10. openleads-2.0.0/openleads/cache/store.py +85 -0
  11. openleads-2.0.0/openleads/campaign.py +283 -0
  12. openleads-2.0.0/openleads/chat.py +291 -0
  13. openleads-2.0.0/openleads/cli.py +211 -0
  14. openleads-2.0.0/openleads/config.py +59 -0
  15. openleads-2.0.0/openleads/emails/__init__.py +15 -0
  16. openleads-2.0.0/openleads/emails/mx.py +84 -0
  17. openleads-2.0.0/openleads/emails/permute.py +87 -0
  18. openleads-2.0.0/openleads/emails/resolve.py +156 -0
  19. openleads-2.0.0/openleads/emails/smtp_verify.py +68 -0
  20. openleads-2.0.0/openleads/engine.py +83 -0
  21. openleads-2.0.0/openleads/intent.py +208 -0
  22. openleads-2.0.0/openleads/models.py +160 -0
  23. openleads-2.0.0/openleads/sources/__init__.py +88 -0
  24. openleads-2.0.0/openleads/sources/base.py +42 -0
  25. openleads-2.0.0/openleads/sources/github.py +92 -0
  26. openleads-2.0.0/openleads/sources/npi.py +100 -0
  27. openleads-2.0.0/openleads/sources/openalex.py +92 -0
  28. openleads-2.0.0/openleads/sources/producthunt.py +90 -0
  29. openleads-2.0.0/openleads/sources/yc.py +160 -0
  30. openleads-2.0.0/openleads/ui.py +43 -0
  31. openleads-2.0.0/openleads/writers.py +67 -0
  32. openleads-2.0.0/openleads.egg-info/PKG-INFO +256 -0
  33. openleads-2.0.0/openleads.egg-info/SOURCES.txt +46 -0
  34. openleads-2.0.0/openleads.egg-info/dependency_links.txt +1 -0
  35. openleads-2.0.0/openleads.egg-info/entry_points.txt +2 -0
  36. openleads-2.0.0/openleads.egg-info/requires.txt +20 -0
  37. openleads-2.0.0/openleads.egg-info/top_level.txt +3 -0
  38. openleads-2.0.0/pyproject.toml +57 -0
  39. openleads-2.0.0/setup.cfg +4 -0
  40. openleads-2.0.0/tests/test_cache.py +38 -0
  41. openleads-2.0.0/tests/test_campaign.py +45 -0
  42. openleads-2.0.0/tests/test_chat.py +67 -0
  43. openleads-2.0.0/tests/test_emails.py +125 -0
  44. openleads-2.0.0/tests/test_engine.py +111 -0
  45. openleads-2.0.0/tests/test_intent.py +56 -0
  46. openleads-2.0.0/tests/test_new_sources.py +112 -0
  47. openleads-2.0.0/tests/test_openleads.py +89 -0
  48. openleads-2.0.0/tests/test_sources.py +87 -0
@@ -0,0 +1,133 @@
1
+ # PolyForm Noncommercial License 1.0.0
2
+
3
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
4
+
5
+ ## Acceptance
6
+
7
+ In order to get any license under these terms, you must agree
8
+ to them as both strict obligations and conditions to all your
9
+ licenses.
10
+
11
+ ## Copyright License
12
+
13
+ The licensor grants you a copyright license for the software to
14
+ do everything you might do with the software that would
15
+ otherwise infringe the licensor's copyright in it for any
16
+ permitted purpose. However, you may only distribute the software
17
+ according to [Distribution License](#distribution-license) and
18
+ make changes or new works based on the software according to
19
+ [Changes and New Works License](#changes-and-new-works-license).
20
+
21
+ ## Distribution License
22
+
23
+ The licensor grants you an additional copyright license to
24
+ distribute copies of the software. Your license to distribute
25
+ covers distributing the software with changes and new works
26
+ permitted by [Changes and New Works
27
+ License](#changes-and-new-works-license).
28
+
29
+ ## Notices
30
+
31
+ You must ensure that anyone who gets a copy of any part of the
32
+ software from you also gets a copy of these terms or the URL for
33
+ them above, as well as copies of any plain-text lines beginning
34
+ with `Required Notice:` that the licensor provided with the
35
+ software. For example:
36
+
37
+ > Required Notice: Copyright 2026 Samyar Shafiee / NGN Hacks (https://ngnhacks.ca)
38
+
39
+ ## Changes and New Works License
40
+
41
+ The licensor grants you an additional copyright license to make
42
+ changes and new works based on the software for any permitted
43
+ purpose.
44
+
45
+ ## Patent License
46
+
47
+ The licensor grants you a patent license for the software that
48
+ covers patent claims the licensor can license, or becomes able to
49
+ license, that you would infringe by using the software.
50
+
51
+ ## Noncommercial Purposes
52
+
53
+ Any noncommercial purpose is a permitted purpose.
54
+
55
+ ## Personal Uses
56
+
57
+ Personal use for research, experiment, and testing for the
58
+ benefit of public knowledge, personal study, private
59
+ entertainment, hobby projects, amateur pursuits, or religious
60
+ observance, without any anticipated commercial application, is
61
+ use for a permitted purpose.
62
+
63
+ ## Noncommercial Organizations
64
+
65
+ Use by any charitable organization, educational institution,
66
+ public research organization, public safety or health
67
+ organization, environmental protection organization, or
68
+ government institution is use for a permitted purpose regardless
69
+ of the source of funding or obligations resulting from the
70
+ funding.
71
+
72
+ ## Fair Use
73
+
74
+ You may have "fair use" rights for the software under the law.
75
+ These terms do not limit them.
76
+
77
+ ## No Other Rights
78
+
79
+ These terms do not allow you to sublicense or transfer any of
80
+ your licenses to anyone else, or prevent the licensor from
81
+ granting licenses to anyone else. These terms do not imply any
82
+ other licenses.
83
+
84
+ ## Patent Defense
85
+
86
+ If you make any written claim that the software infringes or
87
+ contributes to infringement of any patent, your patent license
88
+ for the software granted under these terms ends immediately. If
89
+ your company makes such a claim, your patent license ends
90
+ immediately for work on behalf of your company.
91
+
92
+ ## Violations
93
+
94
+ The first time you are notified in writing that you have violated
95
+ any of these terms, or done anything with the software not
96
+ covered by your licenses, your licenses can nonetheless continue
97
+ if you come into full compliance with these terms, and take
98
+ practical steps to correct past violations, within 32 days of
99
+ receiving notice. Otherwise, all your licenses end immediately.
100
+
101
+ ## No Liability
102
+
103
+ ***As far as the law allows, the software comes as is, without
104
+ any warranty or condition, and the licensor will not be liable to
105
+ you for any damages arising out of these terms or the use or
106
+ nature of the software, under any kind of legal claim.***
107
+
108
+ ## Definitions
109
+
110
+ The **licensor** is the individual or entity offering these
111
+ terms, and the **software** is the software the licensor makes
112
+ available under these terms.
113
+
114
+ **You** refers to the individual or entity agreeing to these
115
+ terms.
116
+
117
+ **Your company** is any legal entity, sole proprietorship, or
118
+ other kind of organization that you work for, plus all
119
+ organizations that have control over, are under the control of,
120
+ or are under common control with that organization. **Control**
121
+ means ownership of substantially all the assets of an entity, or
122
+ the power to direct its management and policies by vote,
123
+ contract, or otherwise. Control can be direct or indirect.
124
+
125
+ **Your licenses** are all the licenses granted to you for the
126
+ software under these terms.
127
+
128
+ **Use** means anything you do with the software requiring one of
129
+ your licenses.
130
+
131
+ ---
132
+
133
+ Required Notice: Copyright 2026 Samyar Shafiee / NGN Hacks (https://ngnhacks.ca)
@@ -0,0 +1,256 @@
1
+ Metadata-Version: 2.4
2
+ Name: openleads
3
+ Version: 2.0.0
4
+ Summary: Free, open-source Apollo alternative: a universal entity→verified-email engine with pluggable free data sources (founders, developers, doctors, researchers) and an interactive chat CLI.
5
+ Author: Samyar Shafiee
6
+ License: PolyForm-Noncommercial-1.0.0
7
+ Project-URL: Homepage, https://github.com/Samyrrrrrr990/openleads
8
+ Project-URL: Repository, https://github.com/Samyrrrrrr990/openleads
9
+ Project-URL: Issues, https://github.com/Samyrrrrrr990/openleads/issues
10
+ Project-URL: Changelog, https://github.com/Samyrrrrrr990/openleads/blob/main/CHANGELOG.md
11
+ Keywords: lead-generation,email-finder,apollo-alternative,sales,cli,prospecting,cold-email,smtp-verification,yc,founders,osint,doctors,researchers,developers,data-enrichment
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Office/Business
17
+ Classifier: Topic :: Communications :: Email
18
+ Classifier: Operating System :: OS Independent
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Provides-Extra: chat
23
+ Requires-Dist: rich>=13.0; extra == "chat"
24
+ Requires-Dist: prompt_toolkit>=3.0; extra == "chat"
25
+ Provides-Extra: campaign
26
+ Requires-Dist: requests>=2.31.0; extra == "campaign"
27
+ Requires-Dist: python-dotenv>=1.0.0; extra == "campaign"
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0; extra == "dev"
30
+ Requires-Dist: ruff>=0.4.0; extra == "dev"
31
+ Requires-Dist: build>=1.0; extra == "dev"
32
+ Requires-Dist: twine>=5.0; extra == "dev"
33
+ Provides-Extra: all
34
+ Requires-Dist: rich>=13.0; extra == "all"
35
+ Requires-Dist: prompt_toolkit>=3.0; extra == "all"
36
+ Requires-Dist: requests>=2.31.0; extra == "all"
37
+ Requires-Dist: python-dotenv>=1.0.0; extra == "all"
38
+ Dynamic: license-file
39
+
40
+ <div align="center">
41
+
42
+ # 🧲 OpenLeads
43
+
44
+ ### The free, open-source Apollo alternative β€” for *everyone*.
45
+
46
+ **Find founders, developers, doctors, researchers β€” anyone β€” and verify their emails, using only free, public data. No paid APIs. No API keys. No seat fees. Now with an interactive chat CLI.**
47
+
48
+ [![License: PolyForm NC](https://img.shields.io/badge/license-PolyForm%20Noncommercial-blue.svg)](./LICENSE)
49
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8%2B-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/)
50
+ [![Zero-dependency core](https://img.shields.io/badge/core-zero%20dependencies-success.svg)](#-how-it-works)
51
+ [![PyPI](https://img.shields.io/badge/pip-install%20openleads-blue.svg)](https://pypi.org/project/openleads/)
52
+ [![CI](https://github.com/Samyrrrrrr990/openleads/actions/workflows/ci.yml/badge.svg)](https://github.com/Samyrrrrrr990/openleads/actions/workflows/ci.yml)
53
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md)
54
+ [![Stars](https://img.shields.io/github/stars/Samyrrrrrr990/openleads?style=social)](https://github.com/Samyrrrrrr990/openleads/stargazers)
55
+
56
+ </div>
57
+
58
+ ---
59
+
60
+ Apollo, Hunter, RocketReach, and ZoomInfo all sell the same two things: **a contact database** and **email verification**. Their moat is the database. **OpenLeads inverts it.**
61
+
62
+ > OpenLeads is a **universal `entity β†’ verified email` engine**, fed by a registry of **pluggable, free, keyless public data sources.**
63
+
64
+ The email engine doesn't care *who* you're looking for. So coverage grows by adding small **source plugins**, not by paying for a database. v2.0 ships sources for **startup founders, open-source developers, U.S. doctors, and academic researchers** β€” and you can add any vertical (lawyers, podcasters, real-estate agents…) by dropping a single `.py` file in a folder.
65
+
66
+ All for **$0**, in code you can read in one sitting.
67
+
68
+ ```text
69
+ openleads> find 25 AI founders, verified emails only
70
+ plan source=yc count=25 filter=AI verified-only parser=rule
71
+ ┏━━━┳━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓
72
+ ┃ # ┃ βœ“ ┃ Email ┃ Name ┃ Title ┃ Org ┃ Score ┃
73
+ ┑━━━╇━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩
74
+ β”‚ 1 β”‚ OK β”‚ ada@acme.ai β”‚ Ada Lovelace β”‚ Founder β”‚ Acme β”‚ 96 β”‚
75
+ β”‚ 2 β”‚ ~CAβ”‚ grace@cobol.dev β”‚ Grace Hopper β”‚ CEO β”‚ COBOLwx β”‚ 71 β”‚
76
+ β””β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”˜
77
+ 25 leads Β· 18 verified Β· /export FILE to save
78
+ ```
79
+
80
+ > `OK` = SMTP-verified Β· `~CA` = catch-all best-guess Β· `~PG` = MX-only pattern guess Β· **Score** = 0–100 confidence
81
+
82
+ ---
83
+
84
+ ## ✨ Why OpenLeads
85
+
86
+ | | OpenLeads | Apollo / Hunter (free tier) |
87
+ | --- | --- | --- |
88
+ | **Cost** | $0, forever | Credit-limited, then paid |
89
+ | **API key required** | ❌ None | βœ… Required |
90
+ | **Who you can find** | Founders, devs, doctors, researchers, **+ any vertical you plug in** | Their database only |
91
+ | **Email verification** | βœ… Live SMTP `RCPT` + 0–100 score | Paid feature |
92
+ | **Catch-all detection** | βœ… Yes | Sometimes |
93
+ | **Interactive chat CLI** | βœ… Yes (`openleads chat`) | ❌ |
94
+ | **You own the code** | βœ… Readable, hackable, extensible | ❌ Black box |
95
+ | **Output** | βœ… CSV / JSON / NDJSON | Often gated |
96
+ | **Core dependencies** | **Zero** (stdlib only) | β€” |
97
+
98
+ ## πŸš€ Install
99
+
100
+ ```bash
101
+ # Python (recommended) β€” zero-dependency engine + plain CLI
102
+ pip install openleads
103
+
104
+ # …with the pretty interactive chat TUI
105
+ pip install "openleads[chat]"
106
+
107
+ # …with the cold-email companion too
108
+ pip install "openleads[all]"
109
+ ```
110
+
111
+ Prefer Node? A thin wrapper lets you run it with **npx** (it installs the Python package on first use):
112
+
113
+ ```bash
114
+ npx openleads find "50 fintech founders verified only"
115
+ # or: npm i -g openleads
116
+ ```
117
+
118
+ ## ⚑ Quickstart
119
+
120
+ ```bash
121
+ # Launch the interactive chat β€” just type what you want
122
+ openleads
123
+
124
+ # Or go one-shot, non-interactive:
125
+ openleads find "50 fintech founders, verified only" --out leads.csv
126
+ openleads find --source npi --keyword pediatric --location CA --format json
127
+ openleads find "rust developers in Berlin" --source github --format ndjson --out devs.ndjson
128
+
129
+ # Verify specific addresses
130
+ openleads verify ada@acme.io grace@cobol.dev
131
+
132
+ # See what you can search
133
+ openleads sources
134
+ ```
135
+
136
+ No signup, no key, no database fees.
137
+
138
+ ## πŸ’¬ The chat CLI
139
+
140
+ `openleads chat` (or just `openleads`) opens a Claude-Code-style REPL. Type requests in plain English and refine conversationally:
141
+
142
+ ```text
143
+ openleads> pediatricians in California
144
+ openleads> only verified
145
+ openleads> /source github
146
+ openleads> machine learning researchers as ndjson
147
+ openleads> /export leads.ndjson
148
+ ```
149
+
150
+ - **Works fully offline.** A rule-based intent parser understands counts, verticals, locations, filters, and `verified only` β€” **no API key needed.**
151
+ - **Optionally smarter.** Set `OPENROUTER_API_KEY` (a free model works) and free-form input is parsed by an LLM. The active mode is always shown.
152
+ - **Slash commands** for precision: `/source`, `/count`, `/verified`, `/format`, `/export`, `/sources`, `/cache`, `/help`, `/quit`.
153
+
154
+ ## 🧩 Sources (and adding your own)
155
+
156
+ ```bash
157
+ $ openleads sources
158
+ github [people ] developers & open-source orgs
159
+ npi [people ] U.S. doctors & healthcare providers
160
+ openalex [people ] researchers & academics
161
+ producthunt [company] trending products & startups
162
+ yc [company] startup founders (Y Combinator)
163
+ ```
164
+
165
+ All are **keyless and free**. Want a vertical we don't ship β€” recruiters, lawyers, real-estate agents, your CRM export? Drop a `*.py` file in `~/.openleads/sources/`:
166
+
167
+ ```python
168
+ from openleads.sources.base import Source
169
+ from openleads.models import Entity, Query
170
+
171
+ class LawyersSource(Source):
172
+ name = "lawyers"
173
+ kind = "people"
174
+ vertical = "attorneys"
175
+ description = "State bar directory."
176
+
177
+ def search(self, query: Query):
178
+ for row in fetch_from_some_free_directory(query):
179
+ yield Entity(full_name=row["name"], organization=row["firm"],
180
+ domain=row["firm_domain"], source=self.name)
181
+ ```
182
+
183
+ Run `openleads sources` and it's there. The email engine handles the rest. Full guide: [`docs/sources.md`](./docs/sources.md).
184
+
185
+ ## πŸ“¦ Output formats
186
+
187
+ ```bash
188
+ openleads find "20 founders" --format csv # default; CRM/mail-merge ready
189
+ openleads find "20 founders" --format json # array, includes score + signals
190
+ openleads find "20 founders" --format ndjson # one lead per line, streamable
191
+ openleads find "20 founders" --format json --out - # write to stdout
192
+ ```
193
+
194
+ The CSV schema is a superset of v1's, so the cold-email companion and any existing tooling keep working.
195
+
196
+ ## πŸ” How it works
197
+
198
+ ```mermaid
199
+ flowchart LR
200
+ Q[Your request<br/>chat or CLI] --> I[Intent parser<br/>rule-based Β± LLM]
201
+ I --> S[Source plugin<br/>yc Β· github Β· npi Β· openalex Β· …]
202
+ S --> E[Email engine<br/>multi-resolver MX β†’ permutations β†’ SMTP RCPT]
203
+ E --> C[Confidence score 0–100<br/>+ honest label]
204
+ C --> O[CSV Β· JSON Β· NDJSON]
205
+ E <--> K[(SQLite cache<br/>MX Β· SMTP Β· datasets)]
206
+ ```
207
+
208
+ The crown jewel is the **email engine** ([deep dive](./docs/how-it-works.md)): MX cross-checked across **two DNS-over-HTTPS resolvers**, common name permutations, and a real SMTP `RCPT` probe (no message is ever sent) with **catch-all detection**. Results carry an explainable **0–100 score**. A **SQLite cache** avoids re-probing domains and mail servers between runs.
209
+
210
+ > πŸ“‘ SMTP verification needs outbound **port 25**. Works on most servers; some home ISPs block it, in which case OpenLeads gracefully falls back to MX-validated pattern guesses.
211
+
212
+ ## πŸ“¨ Bonus: cold-email companion
213
+
214
+ `openleads campaign` turns `leads.csv` into personalized outreach β€” LLM-drafted (free OpenRouter models supported), clean formatting, placeholder guards, sends over **your own** SMTP, and saves a copy to Sent. Dry-run by default; `--live` to send.
215
+
216
+ ```bash
217
+ pip install "openleads[campaign]"
218
+ cp .env.example .env # add your SMTP + OpenRouter creds
219
+ openleads campaign # dry run (preview)
220
+ openleads campaign --live # send for real
221
+ ```
222
+
223
+ > ⚠️ This is the only part that touches your mailbox. The lead engine never sends anything.
224
+
225
+ ## 🧭 Responsible use
226
+
227
+ OpenLeads is for legitimate outreach, recruiting, research, and prospecting. Some verticals carry extra weight β€” e.g. healthcare providers (NPI) and academics β€” so please read [`docs/responsible-use.md`](./docs/responsible-use.md). **You** are responsible for anti-spam law (CAN-SPAM, GDPR, CASL) and each source's terms.
228
+
229
+ ## πŸ—ΊοΈ What's new in v2.0
230
+
231
+ - βœ… Installable package + **`openleads` CLI** (pip & npx)
232
+ - βœ… **Interactive chat REPL** (rule-based, LLM-optional)
233
+ - βœ… **Pluggable sources** + 4 new keyless verticals (GitHub, NPI, OpenAlex, ProductHunt)
234
+ - βœ… **Confidence scoring (0–100)** with multi-resolver MX cross-checks
235
+ - βœ… **SQLite caching** layer
236
+ - βœ… **`--format json/ndjson`** output
237
+
238
+ See the full [CHANGELOG](./CHANGELOG.md).
239
+
240
+ ## 🀝 Contributing
241
+
242
+ PRs very welcome β€” see [CONTRIBUTING.md](./CONTRIBUTING.md). The easiest high-impact contribution is **a new source plugin** ([guide](./docs/sources.md)) β€” that's literally how OpenLeads becomes "Apollo for everyone."
243
+
244
+ ## πŸ“„ License
245
+
246
+ [PolyForm Noncommercial 1.0.0](./LICENSE) β€” free for personal, research, educational, and nonprofit use. Commercial use? See [COMMERCIAL-LICENSE.md](./COMMERCIAL-LICENSE.md).
247
+
248
+ ## πŸ™ Acknowledgements
249
+
250
+ [`yc-oss/api`](https://github.com/yc-oss/api) Β· [OpenAlex](https://openalex.org) Β· [NPI Registry](https://npiregistry.cms.hhs.gov/) Β· GitHub & ProductHunt public data Β· and everyone who has ever rage-quit a "request a demo" button.
251
+
252
+ <div align="center">
253
+
254
+ **If OpenLeads saved you a subscription, consider leaving a ⭐ β€” it genuinely helps.**
255
+
256
+ </div>
@@ -0,0 +1,217 @@
1
+ <div align="center">
2
+
3
+ # 🧲 OpenLeads
4
+
5
+ ### The free, open-source Apollo alternative β€” for *everyone*.
6
+
7
+ **Find founders, developers, doctors, researchers β€” anyone β€” and verify their emails, using only free, public data. No paid APIs. No API keys. No seat fees. Now with an interactive chat CLI.**
8
+
9
+ [![License: PolyForm NC](https://img.shields.io/badge/license-PolyForm%20Noncommercial-blue.svg)](./LICENSE)
10
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8%2B-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/)
11
+ [![Zero-dependency core](https://img.shields.io/badge/core-zero%20dependencies-success.svg)](#-how-it-works)
12
+ [![PyPI](https://img.shields.io/badge/pip-install%20openleads-blue.svg)](https://pypi.org/project/openleads/)
13
+ [![CI](https://github.com/Samyrrrrrr990/openleads/actions/workflows/ci.yml/badge.svg)](https://github.com/Samyrrrrrr990/openleads/actions/workflows/ci.yml)
14
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md)
15
+ [![Stars](https://img.shields.io/github/stars/Samyrrrrrr990/openleads?style=social)](https://github.com/Samyrrrrrr990/openleads/stargazers)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ Apollo, Hunter, RocketReach, and ZoomInfo all sell the same two things: **a contact database** and **email verification**. Their moat is the database. **OpenLeads inverts it.**
22
+
23
+ > OpenLeads is a **universal `entity β†’ verified email` engine**, fed by a registry of **pluggable, free, keyless public data sources.**
24
+
25
+ The email engine doesn't care *who* you're looking for. So coverage grows by adding small **source plugins**, not by paying for a database. v2.0 ships sources for **startup founders, open-source developers, U.S. doctors, and academic researchers** β€” and you can add any vertical (lawyers, podcasters, real-estate agents…) by dropping a single `.py` file in a folder.
26
+
27
+ All for **$0**, in code you can read in one sitting.
28
+
29
+ ```text
30
+ openleads> find 25 AI founders, verified emails only
31
+ plan source=yc count=25 filter=AI verified-only parser=rule
32
+ ┏━━━┳━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓
33
+ ┃ # ┃ βœ“ ┃ Email ┃ Name ┃ Title ┃ Org ┃ Score ┃
34
+ ┑━━━╇━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩
35
+ β”‚ 1 β”‚ OK β”‚ ada@acme.ai β”‚ Ada Lovelace β”‚ Founder β”‚ Acme β”‚ 96 β”‚
36
+ β”‚ 2 β”‚ ~CAβ”‚ grace@cobol.dev β”‚ Grace Hopper β”‚ CEO β”‚ COBOLwx β”‚ 71 β”‚
37
+ β””β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”˜
38
+ 25 leads Β· 18 verified Β· /export FILE to save
39
+ ```
40
+
41
+ > `OK` = SMTP-verified Β· `~CA` = catch-all best-guess Β· `~PG` = MX-only pattern guess Β· **Score** = 0–100 confidence
42
+
43
+ ---
44
+
45
+ ## ✨ Why OpenLeads
46
+
47
+ | | OpenLeads | Apollo / Hunter (free tier) |
48
+ | --- | --- | --- |
49
+ | **Cost** | $0, forever | Credit-limited, then paid |
50
+ | **API key required** | ❌ None | βœ… Required |
51
+ | **Who you can find** | Founders, devs, doctors, researchers, **+ any vertical you plug in** | Their database only |
52
+ | **Email verification** | βœ… Live SMTP `RCPT` + 0–100 score | Paid feature |
53
+ | **Catch-all detection** | βœ… Yes | Sometimes |
54
+ | **Interactive chat CLI** | βœ… Yes (`openleads chat`) | ❌ |
55
+ | **You own the code** | βœ… Readable, hackable, extensible | ❌ Black box |
56
+ | **Output** | βœ… CSV / JSON / NDJSON | Often gated |
57
+ | **Core dependencies** | **Zero** (stdlib only) | β€” |
58
+
59
+ ## πŸš€ Install
60
+
61
+ ```bash
62
+ # Python (recommended) β€” zero-dependency engine + plain CLI
63
+ pip install openleads
64
+
65
+ # …with the pretty interactive chat TUI
66
+ pip install "openleads[chat]"
67
+
68
+ # …with the cold-email companion too
69
+ pip install "openleads[all]"
70
+ ```
71
+
72
+ Prefer Node? A thin wrapper lets you run it with **npx** (it installs the Python package on first use):
73
+
74
+ ```bash
75
+ npx openleads find "50 fintech founders verified only"
76
+ # or: npm i -g openleads
77
+ ```
78
+
79
+ ## ⚑ Quickstart
80
+
81
+ ```bash
82
+ # Launch the interactive chat β€” just type what you want
83
+ openleads
84
+
85
+ # Or go one-shot, non-interactive:
86
+ openleads find "50 fintech founders, verified only" --out leads.csv
87
+ openleads find --source npi --keyword pediatric --location CA --format json
88
+ openleads find "rust developers in Berlin" --source github --format ndjson --out devs.ndjson
89
+
90
+ # Verify specific addresses
91
+ openleads verify ada@acme.io grace@cobol.dev
92
+
93
+ # See what you can search
94
+ openleads sources
95
+ ```
96
+
97
+ No signup, no key, no database fees.
98
+
99
+ ## πŸ’¬ The chat CLI
100
+
101
+ `openleads chat` (or just `openleads`) opens a Claude-Code-style REPL. Type requests in plain English and refine conversationally:
102
+
103
+ ```text
104
+ openleads> pediatricians in California
105
+ openleads> only verified
106
+ openleads> /source github
107
+ openleads> machine learning researchers as ndjson
108
+ openleads> /export leads.ndjson
109
+ ```
110
+
111
+ - **Works fully offline.** A rule-based intent parser understands counts, verticals, locations, filters, and `verified only` β€” **no API key needed.**
112
+ - **Optionally smarter.** Set `OPENROUTER_API_KEY` (a free model works) and free-form input is parsed by an LLM. The active mode is always shown.
113
+ - **Slash commands** for precision: `/source`, `/count`, `/verified`, `/format`, `/export`, `/sources`, `/cache`, `/help`, `/quit`.
114
+
115
+ ## 🧩 Sources (and adding your own)
116
+
117
+ ```bash
118
+ $ openleads sources
119
+ github [people ] developers & open-source orgs
120
+ npi [people ] U.S. doctors & healthcare providers
121
+ openalex [people ] researchers & academics
122
+ producthunt [company] trending products & startups
123
+ yc [company] startup founders (Y Combinator)
124
+ ```
125
+
126
+ All are **keyless and free**. Want a vertical we don't ship β€” recruiters, lawyers, real-estate agents, your CRM export? Drop a `*.py` file in `~/.openleads/sources/`:
127
+
128
+ ```python
129
+ from openleads.sources.base import Source
130
+ from openleads.models import Entity, Query
131
+
132
+ class LawyersSource(Source):
133
+ name = "lawyers"
134
+ kind = "people"
135
+ vertical = "attorneys"
136
+ description = "State bar directory."
137
+
138
+ def search(self, query: Query):
139
+ for row in fetch_from_some_free_directory(query):
140
+ yield Entity(full_name=row["name"], organization=row["firm"],
141
+ domain=row["firm_domain"], source=self.name)
142
+ ```
143
+
144
+ Run `openleads sources` and it's there. The email engine handles the rest. Full guide: [`docs/sources.md`](./docs/sources.md).
145
+
146
+ ## πŸ“¦ Output formats
147
+
148
+ ```bash
149
+ openleads find "20 founders" --format csv # default; CRM/mail-merge ready
150
+ openleads find "20 founders" --format json # array, includes score + signals
151
+ openleads find "20 founders" --format ndjson # one lead per line, streamable
152
+ openleads find "20 founders" --format json --out - # write to stdout
153
+ ```
154
+
155
+ The CSV schema is a superset of v1's, so the cold-email companion and any existing tooling keep working.
156
+
157
+ ## πŸ” How it works
158
+
159
+ ```mermaid
160
+ flowchart LR
161
+ Q[Your request<br/>chat or CLI] --> I[Intent parser<br/>rule-based Β± LLM]
162
+ I --> S[Source plugin<br/>yc Β· github Β· npi Β· openalex Β· …]
163
+ S --> E[Email engine<br/>multi-resolver MX β†’ permutations β†’ SMTP RCPT]
164
+ E --> C[Confidence score 0–100<br/>+ honest label]
165
+ C --> O[CSV Β· JSON Β· NDJSON]
166
+ E <--> K[(SQLite cache<br/>MX Β· SMTP Β· datasets)]
167
+ ```
168
+
169
+ The crown jewel is the **email engine** ([deep dive](./docs/how-it-works.md)): MX cross-checked across **two DNS-over-HTTPS resolvers**, common name permutations, and a real SMTP `RCPT` probe (no message is ever sent) with **catch-all detection**. Results carry an explainable **0–100 score**. A **SQLite cache** avoids re-probing domains and mail servers between runs.
170
+
171
+ > πŸ“‘ SMTP verification needs outbound **port 25**. Works on most servers; some home ISPs block it, in which case OpenLeads gracefully falls back to MX-validated pattern guesses.
172
+
173
+ ## πŸ“¨ Bonus: cold-email companion
174
+
175
+ `openleads campaign` turns `leads.csv` into personalized outreach β€” LLM-drafted (free OpenRouter models supported), clean formatting, placeholder guards, sends over **your own** SMTP, and saves a copy to Sent. Dry-run by default; `--live` to send.
176
+
177
+ ```bash
178
+ pip install "openleads[campaign]"
179
+ cp .env.example .env # add your SMTP + OpenRouter creds
180
+ openleads campaign # dry run (preview)
181
+ openleads campaign --live # send for real
182
+ ```
183
+
184
+ > ⚠️ This is the only part that touches your mailbox. The lead engine never sends anything.
185
+
186
+ ## 🧭 Responsible use
187
+
188
+ OpenLeads is for legitimate outreach, recruiting, research, and prospecting. Some verticals carry extra weight β€” e.g. healthcare providers (NPI) and academics β€” so please read [`docs/responsible-use.md`](./docs/responsible-use.md). **You** are responsible for anti-spam law (CAN-SPAM, GDPR, CASL) and each source's terms.
189
+
190
+ ## πŸ—ΊοΈ What's new in v2.0
191
+
192
+ - βœ… Installable package + **`openleads` CLI** (pip & npx)
193
+ - βœ… **Interactive chat REPL** (rule-based, LLM-optional)
194
+ - βœ… **Pluggable sources** + 4 new keyless verticals (GitHub, NPI, OpenAlex, ProductHunt)
195
+ - βœ… **Confidence scoring (0–100)** with multi-resolver MX cross-checks
196
+ - βœ… **SQLite caching** layer
197
+ - βœ… **`--format json/ndjson`** output
198
+
199
+ See the full [CHANGELOG](./CHANGELOG.md).
200
+
201
+ ## 🀝 Contributing
202
+
203
+ PRs very welcome β€” see [CONTRIBUTING.md](./CONTRIBUTING.md). The easiest high-impact contribution is **a new source plugin** ([guide](./docs/sources.md)) β€” that's literally how OpenLeads becomes "Apollo for everyone."
204
+
205
+ ## πŸ“„ License
206
+
207
+ [PolyForm Noncommercial 1.0.0](./LICENSE) β€” free for personal, research, educational, and nonprofit use. Commercial use? See [COMMERCIAL-LICENSE.md](./COMMERCIAL-LICENSE.md).
208
+
209
+ ## πŸ™ Acknowledgements
210
+
211
+ [`yc-oss/api`](https://github.com/yc-oss/api) Β· [OpenAlex](https://openalex.org) Β· [NPI Registry](https://npiregistry.cms.hhs.gov/) Β· GitHub & ProductHunt public data Β· and everyone who has ever rage-quit a "request a demo" button.
212
+
213
+ <div align="center">
214
+
215
+ **If OpenLeads saved you a subscription, consider leaving a ⭐ β€” it genuinely helps.**
216
+
217
+ </div>
@@ -0,0 +1,14 @@
1
+ """
2
+ Back-compat shim. The outreach companion moved to ``openleads.campaign`` in v2.0.
3
+
4
+ python automation.py # dry-run preview (was the old behavior)
5
+ python automation.py --live # send
6
+
7
+ Prefer: ``openleads campaign`` / ``openleads campaign --live``.
8
+ """
9
+ import sys
10
+
11
+ from openleads.campaign import main
12
+
13
+ if __name__ == "__main__":
14
+ raise SystemExit(main(sys.argv[1:]))
@@ -0,0 +1,48 @@
1
+ """
2
+ Back-compat shim for OpenLeads v1.
3
+
4
+ The engine moved into the installable ``openleads`` package in v2.0. This module
5
+ re-exports the v1 public helpers and forwards the old CLI to ``openleads find``
6
+ so existing scripts keep working. Prefer the new entry point:
7
+
8
+ openleads find "20 founders" # or: python -m openleads find ...
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import sys
13
+
14
+ # Re-export the v1 public API from its new homes (behavior unchanged).
15
+ from openleads.emails.permute import ( # noqa: F401
16
+ candidate_emails,
17
+ domain_of,
18
+ name_parts,
19
+ )
20
+ from openleads.emails.resolve import find_email # noqa: F401
21
+ from openleads.sources.yc import ( # noqa: F401
22
+ pick_exec,
23
+ split_location,
24
+ )
25
+
26
+
27
+ def _translate(argv: list[str]) -> list[str]:
28
+ """Map v1 flags onto the new ``find`` subcommand."""
29
+ out: list[str] = []
30
+ for a in argv:
31
+ if a == "--no-write":
32
+ out += ["--out", "-"] # v1 'print only' β‰ˆ write CSV to stdout
33
+ else:
34
+ out.append(a)
35
+ return out
36
+
37
+
38
+ def main() -> int:
39
+ sys.stderr.write(
40
+ "[deprecation] `lead_engine.py` is now a shim. Use `openleads find ...` "
41
+ "(or `python -m openleads find ...`).\n"
42
+ )
43
+ from openleads.cli import main as cli_main
44
+ return cli_main(["find"] + _translate(sys.argv[1:]))
45
+
46
+
47
+ if __name__ == "__main__":
48
+ raise SystemExit(main())