Driving an agent's inbox from the terminal

Watching an agent through a dashboard is fine for a colleague and slow for the person building it. The CLI puts the same mailbox behind commands you can pipe, diff, and put in a script, which turns "is it working" from a browser trip into one line.

4 min read

An agent's mailbox listed from a terminal
The same mailbox, one line at a time.

Install and point it at an agent

Shell
npm install -g @mcpmailer/cli
export MCPMAILER_API_KEY=mmk_live_...
mcpmailer mail:list

The key is scoped to one agent identity, so the CLI shows exactly what that agent can see and nothing else. Working with several agents means exporting a different key, which is a feature rather than an annoyance: there is no way to accidentally read the wrong inbox.

The commands worth learning first

Listing mail, reading a thread, and sending a test message cover most of what you need while building. Every command takes --json, which is the part that matters: human output for you, structured output for scripts, and no scraping in between.

Shell
mcpmailer mail:list --json | jq '.[] | {from, subject, unread, created_at}'

That pipe is the fastest debugging tool in the set. When an agent is not answering, the first question is whether the mail arrived at all, and this answers it in a second without opening anything.

Sending, and reading the refusal

Shell
mcpmailer mail:send --to you@yourcompany.com --subject "Test" --body "From the CLI."

A refused send exits non-zero with the reason, which is what makes it usable in a script. daily_send_quota_exhausted carries a reset time, recipient_suppressed means that address already bounced or complained, and sending_locked_verify_email means the workspace email has not been verified yet. Full list in sending.

Shell
if ! mcpmailer mail:send --to "$1" --subject "Deploy" --body "Shipped." ; then
  echo "send refused: check quota, suppression, or verification" >&2
  exit 1
fi

An exit code you can branch on is the difference between a check that fails loudly and a cron job that has been quietly doing nothing since March.

A refused send exiting non-zero with a readable reason
Non-zero exit, readable reason. Scriptable failure beats a silent one.

Checks worth putting in CI

Three, and none of them takes more than a few seconds.

Is the agent reachable? Send it a message from an address you control and assert a reply arrives within a window. An agent that stopped working looks exactly like a quiet inbox, which is why this synthetic check earns its place, as argued in what to monitor in production.

Is the domain still authenticated? Send one real message on deploy and check the authentication headers on delivery. DNS changes, and a records change nobody linked to email is a classic Friday afternoon.

Is anything stuck? List unread mail older than your promised response time. A queue building up is the earliest signal that the agent is failing silently.

Shell
mcpmailer mail:list --unread --json \
  | jq --arg cutoff "$(date -u -v-4H +%FT%TZ)" '[.[] | select(.created_at < $cutoff)] | length'

Where the CLI beats the dashboard, and where it does not

TaskReach for
Is mail arriving at allCLI
Scripted checks and CICLI
Reading one thread while debuggingCLI
Reading a week of threads to judge qualityDashboard
Handing a thread to a colleagueDashboard
Auditing what an agent sentDashboard

The split is roughly speed versus judgement. Anything you would do the same way twenty times belongs in a terminal; anything requiring you to actually read belongs where reading is comfortable. The weekly human read described in evaluating an email agent is firmly in the second column, and doing it in a terminal is how it stops happening.

The same key, everywhere

The CLI, the TypeScript SDK, the Python SDK, the REST API, and the MCP tools all take the same key and obey the same rules. Nothing about the quota, the recipient cap, or the audit trail changes between them, so a check you write in a shell script and behaviour you get from an agent are describing one system.

That also means the CLI is a decent way to explore before you write any code: send a message, reply from your own mailbox, and read the thread back, all in three commands, before deciding how the agent should behave.

Questions

How do I check an AI agent's inbox from the command line?
Install @mcpmailer/cli, export the agent's key, and run mcpmailer mail:list. The key is scoped to one identity, so you see exactly that agent's mail.
Can I script against it?
Yes. Every command takes --json for structured output, and a refused send exits non-zero with the reason, so shell scripts can branch on it.
What checks belong in CI?
A synthetic message that asserts a reply arrives, an authentication check on a real delivered message after deploy, and a count of unread mail older than your promised response time.
Does the CLI use the same limits as the agent?
Yes. One key, one identity, the same allowances, recipient cap, suppression, and audit trail across CLI, SDKs, REST, and MCP.
Can I manage several agents from one terminal?
By exporting a different key per agent. There is deliberately no way to reach another agent's mailbox with the wrong key.
When should I use the dashboard instead?
When the task requires reading rather than checking: judging reply quality, handing a thread to a colleague, or auditing what an agent sent.

Give your agent an address it can answer from.

Create an inbox