Email
Each autark user has their own AgentMail inbox provisioned at onboarding. All mail — sends, replies, inbox reads — goes through the
CLI, which is already authenticated via
~/.autark/credentials.json
. Do not call
directly. Do not use the
npm CLI.
Auth
reads the inbox token and address from
~/.autark/credentials.json
on every call. You do not need to set env vars or pass auth flags. If a command errors with
, the user hasn't finished setup — run
autark mail setup --prefix <name>
once.
/
/
are honored as overrides if set in the environment — useful only when running with a non-default inbox.
Plain text vs HTML — pick the right flag
The CLI accepts both
and
, matching the AgentMail / Mailgun / SendGrid / Resend / Postmark convention.
- — ships as . Recipient sees the bytes verbatim. Any HTML tags (, , , , etc.) show up as literal text in the recipient's inbox.
- — ships as . Recipient's email client renders it as a styled email with real anchors, paragraph breaks, etc.
The rule for outreach signatures: if you put a link in the signature / footer of the email, the link must be embedded in the word (e.g. the name "kushal" is itself the clickable link), never a bare URL on its own line. A bare-URL signature is not the shape autark sends.
To get an embedded-link signature, you have to use
—
would render the
markup as literal text in Gmail / Outlook. This is what broke on 2026-05-28: 6 cold emails went out with
<a href="https://autark.sh">kushal</a>
in
, and every recipient saw the raw markup in their Gmail. See
autark/docs/email-html-in-text-incident.md
for the postmortem.
If your send doesn't have a signature link (signup verification, test pings, system messages), plain
is fine.
Lint every draft before sending
Run
on every draft (sends
and replies) before
:
sh
autark mail lint --body @draft.txt
Exit 0 = clean. Exit 1 = violations printed as JSON, each with a
,
, and
. Treat the output as
feedback, not a gate. The rules catch common AI tells; they sometimes false-positive on a draft that's actually fine. Read each
, judge whether the rule applies to your specific message, fix the ones that land, override the ones that don't. The bar isn't "lint exit 0" — it's "would this email land as a real human note?"
Lint inspects content quality only — AI-tells, hedging, length, signature shape. It does not police markup mechanics (that's the convention above + your judgment). Lint the body you're about to ship: if you're sending
, lint the html file; if you're sending
, lint the text file. Lint reads prose either way.
What lint checks:
- structure-word — AI-tell vocabulary in the body (, , , , , , etc.). Humans writing cold email don't reach for these. Describe the thing directly.
- em-dash — any character. Strong AI tell in outbound. Use commas, periods, or new line breaks. (Override if the recipient's own writing uses them and you're mirroring tone.)
- body-url — any URL outside a markdown or HTML anchor. The product link belongs in the signature anchor; a bare URL mid-body reads as an A/B variant.
- too-many-questions — more than one . Pick the single question that gives you the most signal. (Override fine for replies answering multiple direct asks.)
- compound-question — "are you X or Y...?" patterns. Drop the and pick the more specific half.
- too-long — >400 chars before the signature (~4–6 short lines). Past that you're explaining, not asking.
- no-anchor-sig — signature has no clickable name link. Without an / in the sig, the recipient has no quick path to figure out who you are.
If most violations land and you can't write a clean draft after 2 rewrites: the issue is upstream of the regex. Re-read
~/.claude/skills/outreach/SKILL.md
and ask whether you should send at all.
Send a message — cold outreach (html, embedded-link sig)
sh
autark mail send \
--to person@example.com \
--subject "Subject" \
--html @./body.html \
--run-id $RUN_ID
html
<p>Hi Karl,</p>
<p>one sentence quoting them.</p>
<p>one sentence on what you built.</p>
<p>one specific question?</p>
<p>best,<br><a href="https://autark.sh">kushal</a></p>
Recipient sees a styled email with "kushal" as a clickable link to autark.sh. This is the default shape for any cold outreach send.
Always pass . With it,
records the autark action itself (channel=email, recipient, thread_id, message_id, subject) so you don't need a separate
. Without
, the send still works but isn't tracked — only do that for non-outreach signups/login flows where there's no autark run.
Other flags:
,
,
,
,
(each repeatable or comma-separated),
to print the payload without sending,
to override the auto-generated action title.
Response is JSON with
,
, and (when
was passed)
. Save it.
Send a message — non-outreach (plain text, no link)
For signup verifications, test pings, system messages, or any send where there is no signature link to worry about:
sh
autark mail send \
--to verify@signup-form.test \
--subject "Subject" \
--text @./body.txt
Plain
is fine here. No
because there's no autark run.
Reply in a thread
sh
autark mail reply \
--message-id "$MESSAGE_ID" \
--html @./reply.html \
--run-id $RUN_ID
Same shape rules: if your reply has a signature link, use
. If you're answering a one-liner with a one-liner and no sig link,
is fine.
is the message id of the message you're replying to (the inbound one you got, or your own original send). It's what
/
/
return.
Use
to reply to all recipients, and
autark mail forward --message-id <id> --to <addr> [--html @body.html]
to forward.
Read inbox
sh
autark mail threads [--limit 30] # list threads
autark mail thread <thread_id> # one thread + all messages
autark mail messages [--limit 30] # flat message list
autark mail message <message_id> # single message
autark mail raw <message_id> # full raw payload
autark mail attachment --message-id <id> --attachment-id <id> [--out file]
JSON output throughout. No auth flags — credentials are read from disk.
Escape hatch
If AgentMail ships a new endpoint that
doesn't wrap yet:
sh
autark mail request GET /inboxes/$EMAIL/some/new/endpoint
autark mail request POST /inboxes/$EMAIL/foo --body @payload.json
Reuses the same authenticated session. Use this only when no wrapped command fits.
Rules
- For any send whose signature contains a link, use so the link is embedded in the name. Bare-URL signatures are not the shape autark sends.
- Plain is fine for sends without a signature link (signup verifications, system pings, test sends).
- Lint every draft (sends and replies). Treat the output as feedback, override the rules that don't apply.
- Pass on every outreach send/reply so the action lands in autark and the reply-state cron can detect engagement.
- Do not guess email permutations from name + domain. Use the skill before first contact — verify the address through a concrete source (Apollo, GitHub commits, etc.).
- If the contact is high value or the source is shaky, corroborate with a second signal.
- If an address hard-bounces, suppress it and move on. Don't try nearby guesses.
- If browser work is needed for signups, verification links, or Apollo research, use the skill.
- The response (or payload) is the canonical record — + are how you find replies later. If you passed , autark already stored them under the action.