OpenOutreach is a free, open source marketing & customer engagement project written in Python and released under GPL-3.0. It has 3,026 GitHub stars, 561 forks and 1 open issues, and was last pushed 10 days ago. On this registry it ranks #26 of 50 tracked projects in Marketing & Customer Engagement, with 5 head-to-head comparisons available. It gained 25 stars over the last 3 tracked days.

What is OpenOutreach?

What it is

OpenOutreach is an open-source AI agent for B2B lead generation, written in Python and licensed under GPL-3.0. It is a self-hosted CLI that lets a user describe a product and target market, then finds matching people from a licensed data provider and judges each one against an ideal customer profile learned from those descriptions.

The tool solves the gap between a cold-email sequencer and a lead database. The input is not a list upload, but a description of the product and target market. The output is not only rows, but a plain-language verdict for each person and the reason that person fits. It can buy a verified work address and send the first email from the user's mailbox, while avoiding browser automation, social-network accounts, and scraping.

Key capabilities

  • It turns a product description and target-market description into an ideal customer profile, then returns qualified leads as CSV on standard output.
  • It writes a reason for each match, so the user can read the verdict and correct the description when the result is wrong.
  • It can retrieve a verified work address for one credit per address and send email from the user's mailbox.
  • It supports bounded runs, such as finding and sending to five leads while spending at most five credits.
  • It stores state in ~/.openoutreach, so a stopped run continues from the existing count instead of repeating work.
  • It ships a Claude Code plugin and a skill file that teach an agent when to run find, send, run, and status.

Who uses it and how

  • A B2B marketer uses it as a self-hosted lead finder by describing the product, reviewing the verdicts, and correcting the description when the matches are wrong.
  • A growth team uses it to generate qualified leads without uploading a list, then sends the first message from its own mailbox after obtaining verified work addresses.
  • A developer or Claude Code user runs the CLI, or installs the plugin and skill so an agent can call find, send, run, and status.

Getting started

The typical install method is uv tool install openoutreach, followed by running openoutreach for onboarding and a first lead run. Users can also install the Claude Code plugin from the GitHub repository or copy the skills/find-leads/ directory into ~/.claude/skills/.

When to use it — and when not to

OpenOutreach fits teams that want a Python, GPL-3.0, self-hosted CLI for AI-assisted B2B lead qualification and email sending from their own mailbox. It is less suitable for people who need a browser-based social outreach workflow or no per-address credit cost, because verified work addresses cost one credit each and the README describes no browser, daemon manager, or container. The facts show one open issue and no listed contributor count, so a self-hoster should review maintenance.

project readme (upstream, from github) — read inline

OpenOutreach Logo

OpenOutreach — open-source AI agent for B2B lead generation

Describe your product. Define your target market. The AI finds the people who fit, tells you why each one does, and emails them.

Self-hosted CLI. One install, one onboarding, one command.

GitHub stars GitHub forks License: GPLv3 Open Issues


Demo


🚀 What is OpenOutreach?

OpenOutreach is a self-hosted, open-source lead finder that qualifies for you — and then writes the email. You describe your product and your target market; it discovers matching people from a licensed data provider, judges each one against the ICP it learned from your description, hands you the ones that fit with the reason each was chosen written out, and opens the conversation from your own mailbox.

Two things make that different from what you may have used before:

  • Unlike a cold-email sequencer, you don't bring a list. There is nothing to upload. The input is a sentence about your product.
  • Unlike a lead database, the output is not rows. It is a verdict per person, in plain language you can read and disagree with — and correcting the description is how you correct the verdicts.

It has zero platform-ToS surface: browserless, no social-network account, no scraping. There is no account to get banned, because there is no account.


⚡ Quick Start

uv tool install openoutreach
openoutreach

That is the whole thing. A bare openoutreach onboards you if it has to, finds leads that fit, buys a verified work address for each, and emails them from your mailbox — narrating what it did as it goes. One install, one wizard, one command.

Prefer to say it out loud, or to set the size of the first run?

openoutreach run 5        # find five leads carrying an address, then send — at most 5 credits

The verbs:

openoutreach                  # onboard if needed, then find and send
openoutreach run 5            # ...with an explicit goal
openoutreach init             # onboard only — one flow, every answer, nothing spent
openoutreach init --product-docs product.md --target target.md   # ...the two long fields from files
openoutreach find 10          # ten more qualified leads → CSV on stdout — free, cannot spend
openoutreach find 10 emails   # ...carrying a work email (one credit each)
openoutreach find 0           # no work — print what you already have
openoutreach send             # mail what is already stored
openoutreach send 5           # ...until five conversations are open
openoutreach status           # what is configured, blocked and counted

Everything lives in ~/.openoutreach, so stopping and starting loses nothing: the number you ask for is more than you already have, so running it again continues where it left off. No browser, no daemon manager, no container.


🤖 Use it from Claude Code

This repo ships a Claude Code plugin, so you can pull leads without leaving your agent session:

/plugin marketplace add eracle/OpenOutreach
/plugin install openoutreach@openoutreach

The skill (skills/find-leads/SKILL.md) teaches Claude when to run find, which flags cost credits and which cannot, how to read the CSV on stdout, and what each error: means. It never buys an address you did not ask for, never sends without being asked, and never accepts the legal notice for you. Prefer skills to plugins? Copy skills/find-leads/ into ~/.claude/skills/ instead.

Not on Claude Code? The skill is a markdown file describing the CLI's own contract — nothing Claude-specific is required to use openoutreach itself. Codex, Cursor, or any other agent can call the same openoutreach find / send / run / status commands directly; point your agent's instructions file at skills/find-leads/SKILL.md and it reads the same rules.


🧩 Three packages, one product

OpenOutreach is an orchestrator. The finding and the sending are two standalone programs, and this package installs both and hosts them in one process, one database and one onboarding:

Package What it is Standalone
OpenOutFind discovery, qualification, enrichment, the CRM uvx --from openoutfind outfind find 10
OpenOutSend the outreach agent, the mailbox, the send guards uvx --from openoutsend outsend send
OpenOutreach (this) one install, one wizard, one command over both

The wizard is here because the children do not have one. Both are agent-first: they read their configuration from OPENOUTFIND_* / OUTSEND_* on every run and remember none of it, which is right for a program a script or an agent drives and wrong for a person. So this is where the questions are asked, where the answers are kept, and where they are handed to each child in its own variables.

Neither child is diminished by the bundle. Each keeps its own console script, its own settings module and its own test suite, and the contract between them is a public one:

outfind find 50 --json | outsend      # anybody's producer, anybody's receiver
outsend send                          # a separate invocation, on the mailbox's clock

openoutreach run is that same pipe, in one process — the JSON Lines still cross the boundary, they just cross it in a buffer. There is no privileged in-memory hand-off, because a second, untested path between the same two programs would make the public one a lie.

Which shape is for you: if you are an agent, a script, or a power user with your own sender, take the two CLIs and the pipe. If you want to see whether this works, take the one command.


📤 What You Get Out

The finder's deliverable is a file, and it is shaped for the tools you already send with:

openoutreach find 10 emails > leads.csv

It runs until it has ten more leads carrying an address, prints every lead you have as CSV, and exits — so the file you just wrote is always the current truth. Exit 0 means it got what you asked for; anything short still prints its rows and says why it stopped.

email, first_name, last_name, company, title, website, linkedin_url, reason, lead_id, qualified_at

Those column names are the importers', not ours. Instantly and Smartlead both require email/first_name/last_name and recognise company/title/website/linkedin_url as standard fields, so an exported file imports without column mapping. Anything else — including reason — arrives as a custom variable you can merge into a template.

  • reason is the point. Everybody exports rows; almost nobody exports why this lead.
  • There is no score column, on purpose. The model's confidence is a spend gate for the paid lookup, not a quality signal. The fit verdict is the LLM's, and it is already in the file as a sentence.
  • A lead with no email still exports. If you have no email-finder credits, you still get the qualified person, their employer and the reason.
  • A rejected lead never exports. Both rejections are excluded, always.

If you send with your own tool: turn on its import dedupe. It is opt-in on Smartlead and undocumented on Instantly, so a lead you export twice can otherwise be contacted twice.


📋 What You Need

# What Example
1 An LLM API key OpenAI, Anthropic, or any OpenAI-compatible endpoint
2 An email-finder API key (BetterContact) Free account: 40 credits, no card. Powers both discovery (Lead Finder, billed nothing) and enrichment (one credit per verified work email)
3 A product description + target market "We sell cloud cost optimization for DevOps teams at mid-market SaaS companies"
4 A mailbox to send from Its address and an app password — not your login password. Google Workspace works out of the box; any other provider names its SMTP/IMAP host and port

Onboarding asks for all four in one pass and asks only once — the answers are kept in ~/.openoutreach, and every later run exports them into the variables the children read. A question whose variable is already exported is not asked

readme truncated — read the full docs on github

Frequently asked questions

Is OpenOutreach free to use?

OpenOutreach is open source under the GPL-3.0 licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does OpenOutreach do?

Open-source AI agent for B2B lead generation — describe your product, it finds the people who fit, explains why each one does, and emails them from your mailbox

What is OpenOutreach written in?

OpenOutreach is primarily written in Python. Its source is publicly available at https://github.com/eracle/OpenOutreach, and it has 3,026 GitHub stars.