Honest, local-first cold outreach. Research a prospect → personalize the opener → run a safe, sequenced campaign → auto-follow-up only the people who didn't reply. One shared Python core, two front-ends: a CLI and an MCP server you can drive from any MCP client.
No SaaS, no account, no required API keys. Your prospect data and your .env
never leave your machine — it's a single SQLite file you can delete and rebuild.
git clone https://github.com/Makeph/coldforge && cd coldforge
pip install -e ".[all]" # or `pip install -e .` for the zero-dep core
coldforge init
coldforge leads import examples/leads.csv
coldforge research --all
coldforge campaign create --name q3 --sequence examples/sequence.yml
coldforge campaign activate q3 --leads examples/leads.csv
coldforge campaign preview q3 # review the whole timeline first
coldforge tick --dry-run # see exactly what would sendNot on PyPI yet — install from source as above. (
pip install coldforgewill be the one-liner once it's published.)
It's a synthesis of the best ideas from a pile of open-source outreach tools, rebuilt small and honest:
| Idea | Borrowed from | How coldforge does it |
|---|---|---|
Local SQLite sending engine, sequences, A/B, safe tick worker |
cold-cli (Go) |
Re-implemented lean in Python |
| Web-search + scrape to personalize | prospect-research-mcp |
research command + research_prospect MCP tool, zero-key DuckDuckGo fallback |
| LLM-personalized emails | ProspectAI |
~150 lines, not 137k; always degrades to template fill |
| Curated reply-driving templates, silent-reply follow-up, SPF/DKIM/DMARC check | coldflow |
Original template pack + doctor + reply→cancel rule |
| "Drop your site → learn who buys it", fit-scored segments, reply triage, learn-what-works | AutoGTM tools (explee.com & co) |
icp build + leads score, reply classification, stats --by template, all local and editable |
Everything degrades gracefully: no ANTHROPIC_API_KEY → deterministic
template fill; no Tavily key → DuckDuckGo + site scrape; no SMTP → dry-run
only. You can run the entire pipeline end-to-end with an empty .env.
┌──────────────────────────────────────────────┐
│ shared core (research · personalize · │
│ templates · sequence · sender · db) │
└───────────────┬───────────────┬──────────────┘
│ │
coldforge CLI MCP server
research→send→follow research_prospect
draft_email
coldforge icp build --site acme.io # read YOUR site → who buys it (editable JSON)
coldforge leads verify # syntax / disposable / MX — invalid never sends
coldforge leads score # rank every lead 0–100 against the ICP
coldforge templates list # browse the pack
coldforge templates show sales_pain_point
coldforge research alex@acme.io # store a personalization signal
coldforge draft -l alex@acme.io -t sales_pain_point --research
coldforge lint -l alex@acme.io -t sales_pain_point # spam-filter check the copy
coldforge doctor acme.io # SPF / DKIM / DMARC, 0–100 score
coldforge reply mark alex@acme.io --text "pas intéressé" # auto-classified
coldforge suppress add cto@acme.io # do-not-contact list, honoured everywhere
coldforge stats q3 --by template # which copy earns replies → double downpip install "coldforge[mcp]"
coldforge mcp # stdio serverRegister it with your MCP client:
{
"mcpServers": {
"coldforge": { "command": "coldforge", "args": ["mcp"] }
}
}Tools exposed: research_prospect, draft_email, list_templates,
show_template, check_deliverability, build_icp, score_prospect,
lint_email, classify_reply. Now you can ask your assistant "research Alex
at Acme and draft a pain-point cold email" and it uses the same engine the
CLI does.
A sequence is a list of steps in YAML:
- template: sales_pain_point # concrete opener from the lead's data + research
wait_days: 0
condition: always
- template: followup_bump # one soft bump, same thread, only if no reply
wait_days: 3
condition: no_replyOn activate, every step is pre-scheduled for every lead. The tick worker
(run it from cron / Task Scheduler) sends what's due and enforces the
guardrails:
- Send window & days — nothing sends outside
COLDFORGE_SEND_WINDOW/COLDFORGE_SEND_DAYS(default 09:00–17:00, Mon–Fri). - Daily cap —
COLDFORGE_DAILY_LIMIT(default 40) per account. - Jittered pacing — randomised gap between real sends.
- Reply → cancel — a
no_replystep is skipped and the rest of that lead's sequence canceled the moment a reply is recorded (manually or via IMAP). - Suppression list —
coldforge suppress add(or any reply classified as an unsubscribe) removes an address from every current and future sequence, and every real send carries aList-Unsubscribeheader. - Verification gate — leads marked
invalidbyleads verifyare never scheduled and never sent to.
# typical cron line — runs the worker every 15 min during the day
*/15 9-17 * * 1-5 coldforge tick --scan-repliesEverything is optional — copy .env.example to .env and fill what you need.
| Variable | Purpose | Without it |
|---|---|---|
ANTHROPIC_API_KEY |
LLM-personalized drafts | deterministic template fill |
TAVILY_API_KEY |
high-quality research | DuckDuckGo + site scrape |
SMTP_*, COLDFORGE_FROM_* |
actually send mail | dry-run only |
IMAP_* |
auto-detect replies | mark replies manually |
COLDFORGE_DAILY_LIMIT / SEND_WINDOW / SEND_DAYS |
guardrails | sane defaults |
The AutoGTM idea — "drop your site, learn who buys it" — reduced to its honest core, running on your machine:
coldforge icp build --site acme.io # scrape your own site → ICP
coldforge leads score # every lead scored 0–100 + why
coldforge leads list # ranked, best fit firstThe ICP is a plain JSON file (~/.coldforge/icp.json) with the product
summary, the pains it removes, ranked buyer segments and match keywords — the
model proposes, you edit. With ANTHROPIC_API_KEY set, an LLM writes the
profile and judges each lead; without it, a deterministic keyword heuristic
keeps ranking usable offline.
Replies aren't binary. Each one (IMAP scan or reply mark --text "…") is
classified — interested · not_interested · unsubscribe · ooo · other —
in French and English. Unsubscribes land on the suppression list instantly;
stats shows the category breakdown, and stats --by template tells you which
copy actually earns replies so you can double down and retire the rest.
Twelve curated, plaintext, reply-tested templates across sales, sales-fr,
recruiting, partnership, warm-intro, networking, follow-up — each under ~120
words with one CTA and deliverability notes baked into the front-matter. The
sales-fr pack is a three-touch French sequence for selling to agencies
(opener → soft bump → breakup, see examples/sequence_fr.yml), with CNIL-style
B2B compliance notes. Add your own by dropping a .md file into
~/.coldforge/templates/.
git clone https://github.com/Makeph/coldforge
cd coldforge
pip install -e ".[dev]"
pytest # offline test suite, no keys neededcoldforge is a precision tool, not a spam cannon: low daily caps, send windows,
one-bump follow-ups, an explicit "say no and I'll stop" CTA in the templates,
and a doctor check so you authenticate your domain before sending. Only email
people you have a legitimate reason to contact, honour unsubscribes, and follow
the law that applies to you (CAN-SPAM, GDPR, etc.).
MIT © 2026 Aurore Biakou