Cofounder CLI
Company inboxes, reading and sending mail, drafts, email campaigns to CRM contacts, your own mail domain, and email from your app.
The company gets its own inboxes. Agents read threads, reply, and send from them, and once the company has its own domain they can email CRM contacts in bulk.
Inboxes
Before managed setup, you can choose the name and role used by all playbook workers:
| MCP | CLI | API |
|---|---|---|
agent_identity_set | cofounder agent-identity set --name <name> --role <role> | PUT /cofounder-cli/v1/company/agent-identity |
agent_identity_get | cofounder agent-identity get | GET /cofounder-cli/v1/company/agent-identity |
Setup generates the inbox handle from the name. For example, Alex Chen becomes alex.chen@<company-mail-domain>.
It removes accents, replaces separators with dots, and limits handles to 64 characters.
Names without ASCII letters or digits get a stable agent-<hash> handle. The sender name keeps the chosen spelling.
Identity is optional. Setup uses hello when you skip it. Without a saved identity, agent-identity get returns null.
Later identity changes reach the next playbook turn. They do not rename inboxes or change existing setup runs.
Verification judges keep their judging instructions. Use email provision to create additional inboxes on a verified company domain.
| MCP | CLI | API |
|---|---|---|
email_provision | cofounder email provision --local-part <name> | POST /cofounder-cli/v1/company/email |
email_get | cofounder email status | GET /cofounder-cli/v1/company/email/status |
The first inbox is free; each extra inbox costs $2 a month while it's
active. Without a domain, the inbox goes on the company's trial domain. Pass
--mail-domain <domain> to use a domain the company owns in Cofounder, or
--mail-domain-id for a mail domain you set up below. Running provision
again with the same name and domain returns the same inbox.
If custom-domain verification is pending, the error receipt includes
provider_dns_records with the required record names, values, and MX priorities.
Publish missing records at your current DNS provider, then retry with the same
mailbox name and domain. Existing domains and inboxes are reused.
email status shows today's sending against your limits and
bounces on app email over the last seven days. App and inbox email share a
limit of 1,000 recipients a day, which resets at midnight UTC.
Read and send
| MCP | CLI | API |
|---|---|---|
email_threads_list | cofounder email threads <inbox-id> | GET /cofounder-cli/v1/company/email/threads |
email_threads_get | cofounder email read <inbox-id> <thread-id> | GET /cofounder-cli/v1/company/email/threads/{thread_id} |
email_threads_attachments_get | cofounder email attachment <inbox-id> <thread-id> <attachment-id> --out <path> | GET /cofounder-cli/v1/company/email/threads/{thread_id}/attachments/{attachment_id} |
email_messages_send | cofounder email send <inbox-id> --to <emails> --subject <text> --body-file <path> | POST /cofounder-cli/v1/company/email/messages |
email_threads_reply | cofounder email reply <inbox-id> <thread-id> --message <message-id> --to <emails> --body <text> | POST /cofounder-cli/v1/company/email/threads/{thread_id}/reply |
email_drafts_create | cofounder email draft create <inbox-id> --to <emails> --subject <text> --body <text> | POST /cofounder-cli/v1/company/email/drafts |
email_drafts_list | cofounder email draft list <inbox-id> | GET /cofounder-cli/v1/company/email/drafts |
email_drafts_send | cofounder email draft send <inbox-id> <draft-id> | POST /cofounder-cli/v1/company/email/drafts/{draft_id}/send |
attachment returns a link to the file; --out downloads it instead.
reply needs the message id from email read. Recipient lists are
comma-separated. Mail to a CRM contact marked do-not-contact is refused.
If a send or reply fails with a 503, retry with the same --idempotency-key
and content and it won't go out twice. Drafts have no key: if a
draft send result is unclear, run draft list before retrying; a draft
that's gone or shows send_status scheduled or sending was already accepted.
Have your agent write drafts when you want to review mail before it goes out.
Each command also has a flag form that picks the inbox with --resource
(its address or id) and uses the company's default inbox when you leave it
out:
cofounder email threads list
cofounder email threads get --thread-id <id>
cofounder email threads attachments get --thread-id <id> --attachment-id <id>
cofounder email messages send --to <email> --subject <text> --body <text>
cofounder email threads reply --thread-id <id> --message-id <id> --to <email> --body <text>
cofounder email drafts create --to <email> --subject <text> --body <text>
cofounder email drafts list
cofounder email drafts send --draft-id <id>Use your own mail domain
| MCP | CLI | API |
|---|---|---|
email_domains_create | cofounder email domains create --resource <domain> | POST /cofounder-cli/v1/company/email/domains |
email_domains_verify | cofounder email domains verify --mail-domain-id <id> | POST /cofounder-cli/v1/company/email/domains/{mail_domain_id}/verify |
email_domains_list | cofounder email domains list | GET /cofounder-cli/v1/company/email/domains |
email_domains_get | cofounder email domains get --mail-domain-id <id> | GET /cofounder-cli/v1/company/email/domains/{mail_domain_id} |
email_domains_setup_link_get | cofounder email domains setup-link get --mail-domain-id <id> | GET /cofounder-cli/v1/company/email/domains/{mail_domain_id}/setup-link |
--resource accepts the company's domain name, resource key, or resource UUID,
as in cofounder domains commands (see Domains). Add
--subdomain-label to put mail on a subdomain. create returns the provider's
DNS records and publishes missing records when Cofounder manages the active
zone. If DNS is hosted elsewhere, or a record conflicts with an existing mail
setup, publish or reconcile the returned records at that provider, then run
verify. A verified mail domain
has no inboxes yet. Create them with
cofounder email provision --local-part <name> --mail-domain-id <id>.
For external DNS, setup-link get can return a signed link to review and approve
AgentMail's records with a supported DNS provider. Keep the link private. If it
reports an existing mail provider, review the MX changes before approving: the
template can replace that provider's records. Unsupported providers still use
the returned manual_records. Cofounder-managed DNS uses the existing automatic
record setup instead. After either handoff or manual setup, run verify to
confirm the records; opening the link does not complete verification.
Email campaigns
A campaign sends one message to a list of CRM contacts, each as its own
email, from news.<your-domain>. Campaigns need a paid plan and go to at
most 5,000 contacts. Every contact must have consent recorded for their
current primary email, and must not be marked do-not-contact or blocked from
receiving email. One ineligible contact blocks the whole send.
| MCP | CLI | API |
|---|---|---|
email_campaigns_setup | cofounder email campaign sender setup --resource <domain> | POST /cofounder-cli/v1/company/email/campaign/setup |
email_campaigns_preview | cofounder email campaign audience preview --domain-binding-id <domain-id> --contact-id <id> | POST /cofounder-cli/v1/company/email/campaign/preview |
email_campaigns_drafts_create | cofounder email campaign drafts create --name <name> --content <json> | POST /cofounder-cli/v1/company/email/campaign/drafts |
email_campaigns_drafts_list | cofounder email campaign drafts list | GET /cofounder-cli/v1/company/email/campaign/drafts |
email_campaigns_drafts_get | cofounder email campaign drafts get --draft-id <id> | GET /cofounder-cli/v1/company/email/campaign/drafts/{draft_id} |
email_campaigns_drafts_update | cofounder email campaign drafts update --draft-id <id> --expected-revision <n> --name <name> --content <json> | PUT /cofounder-cli/v1/company/email/campaign/drafts/{draft_id} |
email_campaigns_drafts_preview | cofounder email campaign drafts preview --draft-id <id> | GET /cofounder-cli/v1/company/email/campaign/drafts/{draft_id}/preview |
email_campaigns_drafts_test_send | cofounder email campaign drafts test --draft-id <id> --expected-revision <n> --request-key <key> | POST /cofounder-cli/v1/company/email/campaign/drafts/{draft_id}/test |
email_campaigns_drafts_launch | cofounder email campaign drafts launch --draft-id <id> --expected-revision <n> --request-key <key> | POST /cofounder-cli/v1/company/email/campaign/drafts/{draft_id}/launch |
email_campaigns_send | cofounder email campaign send --request-key <key> --domain-binding-id <domain-id> --contact-id <id> --subject <text> --text <text> ... | POST /cofounder-cli/v1/company/email/campaign/send |
email_campaigns_receipts_list | cofounder email campaign list | GET /cofounder-cli/v1/company/email/campaign |
email_campaigns_receipts_get | cofounder email campaign get --campaign-id <id> | GET /cofounder-cli/v1/company/email/campaign/{campaign_id} |
email_campaigns_receipts_request_keys_get | cofounder email campaign get-by-key --request-key <key> | GET /cofounder-cli/v1/company/email/campaign/by-key/{request_key} |
Run sender setup once with the domain's name, resource key, or resource UUID
from cofounder domains list: it sets up the news. sender and adds an
unsubscribe footer. It publishes missing DNS records in a Cofounder-managed
zone or returns records for you to publish at your provider. Its notices explain
the next action; sending requires Mailtrap DNS verification and compliance
approval. audience preview checks a contact list without writing anything. A
draft's --content holds the audience, sender, and message:
For preview, direct sending, and draft content, domain_binding_id is the source
company domain's binding ID from cofounder domains get --resource <domain>.
The sender binding ID returned by sender setup identifies the separate
Mailtrap sender and is not the source domain ID.
{
"domain_binding_id": "<domain-id>",
"contact_ids": ["<crm-contact-id>"],
"sender_name": "Acme",
"contact_email": "hello@acme.com",
"postal_address": "1 Main St, Springfield, CA 94000",
"subject": "We just launched",
"text": "Plain-text body",
"html": "<p>HTML body</p>"
}Then work through the draft:
drafts previewshows who would be left out and why, plus the finished email with its footer. Nothing is sent.drafts testsends one copy to your own email, once per version of the draft.drafts launchsends the campaign. A draft launches once and then can't be edited; start a new draft for the next campaign.
--expected-revision is the draft's current version number from
drafts get or drafts preview; each edit makes a new version and clears
its test. --request-key is a key you choose and save: retrying with it
returns the saved result instead of sending again, and get-by-key finds the
campaign by it. campaign send skips the draft and sends straight away, with
the content as flags.
If launch fails before sender and audience checks finish, retry the same draft revision with the same request key. A campaign receipt becomes available once those checks succeed; the draft's next step identifies the appropriate retry or receipt read.
Results show which recipients the email provider accepted, which is not the same as delivered. If part of a send has an unknown outcome, the campaign stops there and is never retried automatically.
Email from your app
| MCP | CLI | API |
|---|---|---|
email_app_email_setup | cofounder email setup --app-binding-id <app-id> --idempotency-key <key> | POST /cofounder-cli/v1/company/app-email/setup |
email_app_email_setups_get | cofounder email setups get --job-id <job-id> | GET /cofounder-cli/v1/company/app-email/setups/{job_id} |
email_auth_smtp_setup | cofounder email auth smtp setup --source-domain-binding-id <domain-id> | POST /cofounder-cli/v1/company/email/auth/smtp/setup |
email_auth_smtp_get | cofounder email auth smtp get | GET /cofounder-cli/v1/company/email/auth/smtp |
email_auth_smtp_migrate | cofounder email auth smtp migrate --previous-sending-domain-binding-id <id> --source-domain-binding-id <domain-id> | POST /cofounder-cli/v1/company/email/auth/smtp/migrate |
email_auth_urls_get | cofounder email auth urls get | GET /cofounder-cli/v1/company/email/auth/urls |
email_auth_urls_update | cofounder email auth urls update --site-url <url> --redirect-url <url> | PATCH /cofounder-cli/v1/company/email/auth/urls |
email setup starts a durable job for the selected product app. <app-id> is
the id at the end of the app's managed:vercel_project:<id> resource. Choose an
--idempotency-key and reuse it when retrying the same request; that returns the
same job. Use email setups get --job-id <job-id> to read its state and current
sender readiness.
Cofounder checks app-email policy and billing, then prepares the routed owned sender or a shared sender fallback. If the sender is not ready, the job returns provider notices without issuing a credential. Follow the notices, then start setup again with a new idempotency key after sender readiness converges.
Once a sender is ready, setup creates or recovers one live email:send key
bound to the product app and writes COFOUNDER_APP_EMAIL_API_KEY and
COFOUNDER_APP_EMAIL_SEND_URL to the app's Vercel Production environment. The
key itself is never shown. Repeated or interrupted setup reuses the same
encrypted credential, and other keys keep working. An acknowledged environment
write and a requested redeploy do not confirm that a running deployment loaded
the key; verify that before relying on app email.
email auth smtp setup sends your app's Supabase sign-up and sign-in emails
from the company's verified domain, or from a shared sender if you leave out
--source-domain-binding-id. auth smtp get shows how that's set up without
sending anything. auth smtp migrate moves an app from the shared sender to
your own domain: pass the current shared sender as
--previous-sending-domain-binding-id. Add --project-target staging_branch
to any of these to work on the staging branch instead of production.
New managed setup runs configure the shared Auth
sender automatically. The company inbox and
app email API key are separate. Older setups can use email auth smtp setup
after provisioning a verified sender. If setup reports an uncertain credential
write, reconcile the recorded provider state before retrying.
If SMTP setup is interrupted after the candidate credential is saved, repeat setup for the same sender and project to resume installation or cleanup. Cofounder retains the old credential until Supabase acknowledges the replacement and its settings are read back. This confirms configuration, not email delivery. A lost Mailtrap token-creation response or an interrupted sender migration can still require reconciliation. Setup preserves externally configured SMTP settings.
email auth urls get reads where those auth emails send users: the Supabase
Auth site URL and the allowed redirect URLs. email auth urls update repairs
them: set --site-url to the app's deployed URL and pass
<site-url>/auth/callback in --redirect-url so sign-up and
password-recovery links return to the app. redirect-url replaces the whole
allow list.