Skip to content

Open source · MIT · runs on Cloudflare Workers

Outbound email you own, end to end.

Cold outreach, newsletters and drip series from your real Gmail and SES mailboxes. Every contact, email and reply lives in your own database, and an AI agent can run all of it.

No seats. No per-contact pricing. Cloudflare’s free plan works at low volume.

The Emails page: scheduled emails across mailboxes and campaigns, with all matching emails selected
Gmail and WorkspaceAmazon SESWarm-upMailbox groupsAI personalizationDrip seriesReply categoriesDo-not-sendReply webhooksREST API64 MCP toolsThreaded replies
MCP tools for AI agents
64
a month on Workers Paid, or free at low volume
$5
seconds between sending runs
60
per-seat or per-contact fees
0

Everything outbound needs. Nothing it doesn’t.

One Worker, one database, one passcode. Here is what’s inside.

Sends that respect your limits

Every email is queued with a send time. A per-minute run sends what’s due within each mailbox’s daily limit and spacing, and auto-send spreads a big batch across as many days as it takes.

Warm-up

New mailboxes start at a few emails a day and climb to their limit on a schedule you set.

Mailbox groups

Several mailboxes send as one. Each email goes from the member with the earliest free slot, and follow-ups stay with the same address.

AI personalization

A model rewrites each email for its recipient just before sending, from their contact data and your instructions, and can skip people.

Drip series

Template steps days apart, sent to everyone on a list, including people added later. Add steps any time.

Replies, read for you

Replies are detected every minute or instantly with Gmail push, stripped of quoted history, categorized by AI against your own categories, and posted to your webhook with the whole thread.

Do-not-send, done right

STOP replies, unsubscribes, hard bounces and complaints are honoured automatically, scoped by mailbox purpose.

Once per person

A template reaches an address once, enforced by the database. Re-send to a growing list and only new people get it.

Person timeline

Every email, open, reply, list and series step for one address, across every mailbox, on one page.

Send to lists

Pick exactly who, in exactly what order.

Send to one or more lists, narrowed with the same conditions as the Contacts page, ordered by any field, and capped at the first N. The preview shows who gets it, who’s skipped and why, and the day-by-day plan before anything is queued.

  • Limits count only people who can get it, so a cap of 200 means 200 emails
  • Send the same template tomorrow to reach the next 200
  • Contact fields fill {{variables}}; missing values skip the contact
Send to lists screen in Stay in sight: Pick exactly who, in exactly what order.

AI personalization

Write it once. Each person reads their own version.

Turn on AI for a template and write instructions in plain words. Just before each email goes out, a model rewrites it using that person’s data at that moment: their fields, lists, opens and replies. Test it on a real contact first and see the cost per email.

  • Fills missing variables, like a first name from [email protected]
  • Can skip someone with a reason, such as “logged in today”
  • Never sends an email with a {{placeholder}} left in it
AI personalization screen in Stay in sight: Write it once. Each person reads their own version.

Warm-up and mailbox groups

Spread cold outreach across mailboxes, safely.

Group several mailboxes and send through the group. Each email goes from the member with the earliest free slot by its own limit, spacing and warm-up. Each mailbox has a purpose — cold outreach, newsletter or conversation — that decides how its mail is built.

  • Cold outreach: no tracking pixel, uneven spacing, a plain “reply stop” footer
  • Newsletters: one-click List-Unsubscribe, list headers, open tracking
  • Warm-up paces volume; pair it with an engagement service if you need one
Warm-up and mailbox groups screen in Stay in sight: Spread cold outreach across mailboxes, safely.

Series

Drips that keep up with your product.

Attach lists to a series and everyone on them works through the steps, a set number of days apart. Your app enrolls people by adding them to a list. New steps reach everyone who hasn’t had them, even people who had finished.

  • Delays count from when the previous email actually went out
  • Optionally stop on reply; do-not-send and bounces always stop
  • Onboarding, upgrade upsells, re-engagement — one series each
Series screen in Stay in sight: Drips that keep up with your product.

Replies and webhooks

Know who said yes before you open your inbox.

Each human reply is categorized against categories you define, like interested, not now or referral, with your outreach context in the prompt. Auto-replies and bounces are filtered out. Your webhook gets the category, the whole conversation and the metadata you sent with the email.

  • HMAC-signed webhooks with retries and manual redelivery
  • STOP in any wording goes to do-not-send, for both addresses
  • Answer in the same Gmail thread from the app, the API or an agent
Replies and webhooks screen in Stay in sight: Know who said yes before you open your inbox.

Person timeline

The whole relationship on one page.

Open any address to see every email from any mailbox, sender, list send or series, with opens, replies, list joins, series progress and do-not-send changes, newest first. It works for addresses that aren’t contacts too.

  • Fields your app keeps current, like plan or last_login, sit beside it
  • Reply in the thread straight from the timeline
  • Same data over the API and the get_activity MCP tool
Person timeline screen in Stay in sight: The whole relationship on one page.

One tool for three kinds of email.

Each mailbox declares what it’s for, and the mail it sends is built to match. You don’t need a separate tool for newsletters or for talking to customers.

Cold outreach

One-to-one emails to people who haven’t heard from you.

  • No tracking pixel or bulk headers
  • Spacing jittered up to 60%
  • Suggested 30 a day, 1 every 8 minutes

Newsletter

Bulk mail to people who signed up.

  • One-click List-Unsubscribe
  • Open tracking and list headers
  • Ideal on SES at 1,000 a day

Conversation

Back-and-forth with people who wrote to you.

  • No footer, no tracking
  • Still answers people who left a newsletter
  • Ideal for an agent replying to leads

MCP

Built for AI agents from day one.

Point Claude, Cursor or any MCP client at your deployment and it can do everything you can in the app: import contacts, write templates, preview a send, schedule it through a group, read the replies and answer them in the thread.

64 MCP tools
Streamable HTTP at /mcp, one Bearer passcode.
Senders with descriptions
Agents read when to use each identity and pick the right one.
Full REST API
OpenAPI 3 spec and Swagger UI at /api-docs.
Webhooks out
Replies land in your CRM or agent with category and thread.
An agent in Claude Code previewing and scheduling a list send over MCP
claude mcp add --transport http outbound https://<your-worker>/mcp \
  --header "Authorization: Bearer <PASSCODE>"

Running in about 30 minutes.

You need a Cloudflare account and a Google account to send from. Everything else is optional.

  1. 1

    Clone and create the database

    One D1 database holds everything: contacts, emails, replies, settings.

    git clone https://github.com/yusufnb/stay-in-sight
    cd stay-in-sight && npm install
    npx wrangler d1 create cms-outbound
    npm run db:migrate
  2. 2

    Set a passcode and deploy

    The passcode protects the app, the API and MCP. It’s the only setting you can’t change in the app later.

    npx wrangler secret put PASSCODE
    npm run deploy
  3. 3

    Connect Gmail

    Create a Google OAuth client with the Gmail API, paste it into Settings, and click Connect Google mailbox. Add an OpenRouter key for AI, and SES for newsletters, whenever you like.

    # redirect URI shown in the app:
    https://<your-worker>/oauth/google/callback

What it costs to run

Cloudflare Workers + D1
Free at low volume, $5/mo on Workers Paid
Gmail or Google Workspace
The mailboxes you already have
Amazon SES (optional)
AWS’s per-email pricing
AI via OpenRouter (optional)
About $0.0004 per email with a small model

Full walkthrough, including Gmail push, SES and one-command tenant deploys: the setup guide.

How it compares

Hosted tools like lemlist, Instantly and Smartlead are faster to start and come with lead databases and warm-up networks. Stay in sight trades those for ownership, no seat pricing and an agent-first API.

Stay in sightlemlistInstantlySmartlead
Where your data livesYour own Cloudflare D1 databaseVendor cloudVendor cloudVendor cloud
How you payNothing for the software; hosting from $0Monthly, per userMonthly plansMonthly plans
Source codeOpen, MIT licensedClosedClosedClosed
Agent access64-tool MCP server + REST APIAPIAPIAPI
Newsletters with one-click unsubscribeYes, newsletter mailboxesNot the focusNot the focusNot the focus
Built-in lead databaseNo, bring your ownYesYesYes
Warm-upVolume ramp onlyEngagement networkEngagement networkEngagement network
See the full comparison

Questions

Is it really free?

The software is MIT licensed and costs nothing. You pay Cloudflare for hosting (the free plan works at low volume; Workers Paid is $5 a month), your existing Gmail or Workspace, and, if you use them, Amazon SES and an OpenRouter model for AI.

Does it send through Gmail’s API or SMTP?

Gmail mailboxes connect with OAuth and send through the Gmail API, so emails sit in your Sent folder and replies thread normally. SES mailboxes send through SES’s API, with tracked reply addresses routed back to the Worker by Cloudflare Email Routing.

Will it hurt my deliverability?

It is built to avoid that: per-mailbox daily limits and spacing that are always on, warm-up, jittered spacing for cold outreach, no tracking pixel on cold mail, one-click unsubscribe on newsletters, and automatic do-not-send for STOP replies, bounces and complaints. Your sending practices still matter most.

Can several people use it?

It has one passcode for the app, the API and MCP, so it suits a founder, a small team sharing access, or an agent. There are no per-user roles. Deploy a separate tenant per client with one command if you run outreach for others.

Where do I get leads?

Bring your own: import a CSV, or have your app or agent add contacts through the API or MCP with any fields you like. Every field becomes a {{variable}} and is visible to AI personalization.

How do AI agents use it?

Add the /mcp endpoint to Claude Code, Cursor or any MCP client with your passcode as a Bearer token. Agents can preview and schedule sends, manage lists and series, read categorized replies and answer them in the thread.

Keep your pipeline in sight.

Deploy it to your own Cloudflare account today. Your mailboxes, your data, your rules.