Skip to content
Sales
Skill

/find-leads

Find qualified B2B leads with OpenOutreach — run `openoutreach find N [emails]`, read the CSV it prints on stdout, and hand the rows to whatever sends. Use when the user wants leads, prospects, an ICP-matched contact list, or asks what a campaign already has. Also covers

BOOST
From plugin
openoutreach
3.2k1 skill
Install
$ npx -y skills add eracle/OpenOutreach --skill find-leads --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/find-leads

Context preview

The summary Claude sees to decide when to auto-load this skill.

Find qualified B2B leads with OpenOutreach — run `openoutreach find N [emails]`, read the CSV it prints on stdout, and hand the rows to whatever sends. Use when the user wants leads, prospects, an ICP-matched contact list, or asks what a campaign already has. Also covers

SKILL.md

find-leads.SKILL.md
name: find-leads
description: Find qualified B2B leads with OpenOutreach — run `openoutreach find N [emails]`, read the CSV it prints on stdout, and hand the rows to whatever sends. Use when the user wants leads, prospects, an ICP-matched contact list, or asks what a campaign already has. Also covers first-run setup (`openoutreach init`), `openoutreach status`, when a lookup costs money, and the verbs that actually send mail (`send`, `run`) — which you never run unasked.
user-invocable: true
argument-hint: [N] [emails]

Finding leads with OpenOutreach

OpenOutreach is a self-hosted CLI lead finder. You describe a product and a target market once; each run discovers candidates from a licensed data source, has an LLM judge each one against that ICP, **writes down why**, and prints every lead it has as CSV on stdout.

It is one bounded command: ask for an amount, get rows, exit. **There is no daemon, no background job, no file the tool writes for the operator, and nothing to poll.** If you find yourself wanting to tail a log or wait for something, you have the wrong model of this tool.

**It can also send** — `send` mails what is stored, and `run` is find-then-send in one pass. Both put mail in strangers' inboxes under the user's own identity, so **never run either one unless the user asked for mail to go out.** `find` is the default answer to "get me leads"; its deliverable is a CSV for whatever they already send with.

Is it installed?

openoutreach status          # human summary
openoutreach status --json   # the same document, for you to parse

If the command is missing, run it through `uvx` instead — `uvx openoutreach ...` — or install it with `pip install openoutreach`. Inside a checkout of the repo, `python manage.py <verb>` is the same entry point.

`status` never blocks and never spends. It answers `onboarding` (complete or which `OPENOUTFIND_*` variables are missing), the counts, the credit balance, anything `blocked`, and a `next_action` — start there whenever you are unsure what state the user is in. It reports the finding half; the sending half reports itself when `send` runs.

Setup, if `status` says onboarding is incomplete

openoutreach init            # interactive wizard on a TTY; environment otherwise

`init` creates the database, asks for whatever this install has not been told, and stops **before spending anything**. It is one flow over both halves — the finding first, then what only the sending needs. Every answer can come from the environment instead of a prompt, which is what makes a headless setup possible:

| Step | Environment variables | |------|----------------------| | campaign | `OPENOUTFIND_PRODUCT_DOCS`, `OPENOUTFIND_CAMPAIGN_TARGET` | | llm | `OPENOUTFIND_AI_MODEL`, `OPENOUTFIND_LLM_API_KEY` | | bettercontact | `OPENOUTFIND_BETTERCONTACT_API_KEY` | | account | `OPENOUTFIND_OPERATOR_EMAIL`, `OPENOUTFIND_OPERATOR_COUNTRY` | | the sender | `OUTSEND_OPERATOR_NAME` (who signs the mail), `OUTSEND_MAILBOX_ADDRESS`, `OUTSEND_MAILBOX_PASSWORD` (the provider's **app password**), optional `OUTSEND_BOOKING_LINK` |

**A variable you export is an answer already given**, and the wizard skips that question rather than asking for it again. The fields both halves share — what you sell, who for, the model and its key — are asked once and exported under each child's own name (`OPENOUTFIND_PRODUCT_DOCS` and `OUTSEND_PRODUCT_DOCS` are the same answer), so there is no second copy to keep in step. On a machine with no TTY, an incomplete install fails naming every variable that would have completed it.

The product description and target market are pages of prose, so pass them as files rather than shell-quoted strings — quoting a markdown paragraph on a command line corrupts it quietly:

openoutreach init --product-docs product.md --target target.md

**Never guess the mailbox credentials** — ask the user for them.

**`init` is the only verb that asks.** `find` creates the database if it has to, but it never prompts: given an unconfigured install it stops with `onboarding_incomplete`, naming every variable that would have satisfied it. So run `init` when the user has not configured anything — it fails cheaply, before any work.

The work verb you reach for

openoutreach find 10                 # ten more qualified leads — free, and cannot spend
openoutreach find 10 --emails        # ...and buy an address for whatever cleared the gate
openoutreach find 10 emails          # ten more *carrying* a verified email (≤10 credits)
openoutreach find 0                  # no work at all — just print what is already there

Three things about `N` that are easy to get wrong:

  • **`N` is how many *more*, not a total.** A store with 30 leads answers `find 10` by working

until it has 40. Runs are fully resumable; re-running continues rather than restarting.

  • **`find 0` does no work and spends nothing.** It is how you re-export, or answer "what do we

have?" without running a job.

  • **`N` is a budget when the unit is `emails`.** The provider bills one credit per verified hit, so

`find 10 emails` is capped at ten credits by construction — the number typed is in the same unit as the invoice.

What costs money

Discovery and qualification are free (they cost only the user's own LLM key). **The address lookup is the only paid step**, and it is opt-in:

  • a bare `find N` **cannot** spend a credit, however many leads are queued past the confidence gate;
  • `--emails` permits buying for whatever is ready;
  • the `emails` unit implies `--emails`, because a goal counted in addresses cannot be met without

buying them.

**Do not add `emails` or `--emails` unless the user asked for email addresses.** If they said "find me leads", run the free form and tell them the paid form exists. A lead with no address still exports — the row carries the person, the company and the reason with a blank `email`.

Other flags

| Flag | What it does

Read more
Ships withopenoutreach

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.

Get the whole plugin
Stats
3,196
Stars
590
Forks
Active
Maintenance
Python
Language
GPL-3.0
License
8d ago
Last commit
10y ago
Created
7h ago
Added

Repo: eracle/OpenOutreach