TypeScript CLI / Outreach Automation

Relay turns one company domain into a controlled outreach run.

A multi-stage cold-outreach pipeline that discovers lookalike companies, finds senior decision-makers, verifies work emails, checks policy constraints, and sends personalized emails.

Demo Video

See the pipeline run from the command line.

The demo shows Relay accepting a seed domain, progressing through discovery and verification, presenting a review step, and producing a run summary.

Pipeline Flow

Five stages, one controlled campaign.

01

Company Discovery

Ocean.io searches for lookalike companies based on the input company domain.

02

Decision-Makers

Prospeo finds senior contacts such as founders, C-suite leaders, VPs, directors, and heads.

03

Email Verification

Anymail Finder resolves and validates work emails from contact LinkedIn profiles.

04

Safety Gate

The policy engine checks send caps, missing content, and recontact cooldown rules.

05

Personalized Dispatch

Brevo sends the rendered Handlebars email in live mode, while dry-run mode records the attempt and forwards one sample to the simulation inbox for inspection.

Architecture

Built as a modular CLI with durable local state.

Relay separates command handling, orchestration, provider clients, safety policy, email rendering, and database repositories so each stage stays testable and recoverable.

Progress Recovery

Runs are stored in SQLite with stage checkpoints. If a run fails or is interrupted, Relay detects saved companies, contacts, and emails, then resumes from the next incomplete stage.

  • Run status and stage tracking
  • Provider logs for diagnostics
  • Summary JSON for final reporting

Provider Boundary

Dedicated clients handle Ocean.io, Prospeo, Anymail Finder, and Brevo requests.

Database Cache

Previous completed runs can supply companies, contacts, and emails without repeat API calls.

Safety Policy

Outbound candidates are filtered by send limits, cooldown windows, and template integrity.

Dry-Run Default

Real sending requires `--live`; otherwise records are stored as simulated sends.

Usage

Install, configure, run.

Setup

npm install
npm run prisma:generate
npm run prisma:push

Dry Run

npm run relay -- run stripe.com

Live Run

npm run relay -- run stripe.com --live --no-cache