Ask any AI model for a list of companies to sell to and you'll get one in seconds. It will look great. Every line will sound sure of itself.
Now try to answer: which of those lines are true?
"They're scaling fast." Says who? "200 employees." From where? "Recently funded." When? You can't tell the facts from the guesses, because the model writes both in the same confident voice.
So I built Lead Finder, a free, open-source Claude plugin with one rule: a fact needs a source, a guess becomes a question, and anything it couldn't check is "unknown".
/plugin marketplace add machgtm/lead-finder
/plugin install lead-finder@machgtm
Then ask: "Find 25 leads. I sell to software services firms with 50 to 1,000 people that sell to the US and Europe."
Here are the design decisions behind it, and the bugs that testing caught.
1. The model gathers evidence. A script does the maths.
The easiest way to get a made-up score is to ask a model for a score. So Claude never writes one. It only fills in a file of evidence:
{
"company": "Example Labs",
"domain": "example.com",
"signs": [
{"id": "services", "state": "met",
"source": "https://example.com/services",
"quote": "We build custom web and mobile apps"},
{"id": "size", "state": "unknown"}
],
"signals": [
{"id": "hiring_bd", "date": "2026-10-02",
"detail": "Hiring a Business Development Manager, US",
"source": "https://job-boards.greenhouse.io/example/jobs/102"}
]
}
Then score.py, about 300 lines of standard-library Python, turns that into a ranking. It also enforces the rules the model might bend:
- A sign marked
metwithout anhttp(s)source is downgraded tounknown, with a warning. - A signal without a date, or dated in the future, is dropped.
- Every change is printed, so Claude goes back to the source instead of editing the output.
Same evidence in, same scores out. And anyone can read the formula.
2. Unknown is not "no"
Most scoring treats missing data as a zero. That quietly punishes companies with thin websites and rewards ones with good SEO.
Here, fit only counts what's known:
| Score | Formula |
|---|---|
| Fit | weight of signs met ÷ weight of signs known |
| Coverage | weight of signs known ÷ all signs |
| Intent | for each signal type, weight × recency of its freshest copy, ÷ total signal weight |
If coverage is below 50%, the fit is "unproven" and the company can't be marked "Call now", however good it looks. It can only be "Qualify": go and find out.
3. Testing bug #1: a 2,400-person company scored "Call now"
I ran the plugin on my own ideal customer: software services firms with 50 to 1,000 people. One result was a well-run firm with 2,400+ engineers on its homepage. It hit four of five fit signs, was hiring for business development, and came out near the top.
The maths was right. The scorecard was wrong: "50 to 1,000 people" isn't one sign among five, it's a deal-breaker.
So signs can now be marked "required": true. A company that clearly fails one (with a source) is skipped, whatever else it scores. A company where it's merely unknown is not. Unknown never rules anyone out.
4. Testing bug #2: five job posts were five buying signals
An independent review of the code found this one. The scraper returns one row per job post, so a company with five open sales roles got five hiring signals, and its intent score went to 100. It ended up tied with a company that was hiring and had just raised money.
Now each signal type counts once, at the recency of its freshest copy. Five posts are one hiring signal, dated by the newest.
5. Job boards are public APIs (and their dates lie)
"Hiring a BD manager for the US" is one of the best buying signals there is, and it doesn't need scraping. Seven applicant-tracking systems publish open roles as public JSON or XML: Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee, Breezy HR and Personio.
def greenhouse(slug, fetch):
data = fetch(f"https://boards-api.greenhouse.io/v1/boards/{slug}/jobs")
if not isinstance(data, dict) or "jobs" not in data:
return None # no board: "unknown", not "not hiring"
return [{
"title": j.get("title", ""),
"date": to_date(j.get("first_published")), # not updated_at
"source": j.get("absolute_url", ""),
} for j in data["jobs"]]
Two lessons from building these:
-
Use the posting date, never
updated_at. Greenhouse bumpsupdated_atwhenever a job is edited, which turns a year-old opening into "posted yesterday". - Record real responses as test fixtures. I captured live responses from all seven boards and test the parsers against them. A weekly CI job also calls the live boards, so I hear about an API change before users do.
6. Honest under failure
The best test I ran was an accident. I ran the plugin in a sandbox where almost every website was blocked. It couldn't read a single company page.
A lot of agents would have filled the gap from search snippets. This one returned zero leads. It listed the five candidates it had found as "unverified", explained what was blocked, and suggested what would let it finish.
That behaviour is written into the skill: if fewer companies survive checking than you asked for, say so. Never pad the list.
The same goes for namesakes. During testing, a "raised $10M" headline turned out to be about a crypto company with almost the same name as the software firm being checked. Now the skill checks that news and job boards belong to the same website before using them.
What it doesn't do (yet)
- Discovery is the hard part. Many smaller companies, especially in India, hire through systems with no public feed. Then hiring is "unknown", and Claude falls back to careers pages and news.
- No people, no emails. It finds companies and roles, from public pages only. No LinkedIn scraping, nothing behind a login.
- It doesn't send anything. It gives you a ranked list, the evidence, and one first question per company that's built only from a sourced fact.
Try it, break it
The code is MIT-licensed, has no dependencies, and has 46 tests: github.com/MachGTM/lead-finder.
I'd love pull requests for more public job boards, better discovery sources for specific markets, and scorecard examples for other industries.
And if you've seen a lead tool turn a guess into a "fact", I'd like to hear how you caught it.
I'm building MachGTM, an AI SDR that shows a source for every fact it writes with. Lead Finder is the free, open-source first step.

Top comments (0)