Metadata-Version: 2.4
Name: agent-mail-cli
Version: 0.5.0
Summary: Self-describing local inbox for coding agents
Author: JuanjoFuchs
License-Expression: MIT
Project-URL: Homepage, https://github.com/JuanjoFuchs/agent-mail-cli
Project-URL: Repository, https://github.com/JuanjoFuchs/agent-mail-cli.git
Project-URL: Issues, https://github.com/JuanjoFuchs/agent-mail-cli/issues
Project-URL: Documentation, https://github.com/JuanjoFuchs/agent-mail-cli#readme
Keywords: agents,mailbox,coordination,cli,sqlite
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Communications
Classifier: Topic :: Software Development
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build>=1.0.0; extra == "dev"
Requires-Dist: pyinstaller>=6.0.0; extra == "dev"
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: twine>=4.0.0; extra == "dev"
Dynamic: license-file

# Agent Mail CLI

[![CI](https://img.shields.io/github/actions/workflow/status/JuanjoFuchs/agent-mail-cli/ci.yml?branch=main&label=CI)](https://github.com/JuanjoFuchs/agent-mail-cli/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/actions/workflow/status/JuanjoFuchs/agent-mail-cli/release.yml?label=Release)](https://github.com/JuanjoFuchs/agent-mail-cli/actions/workflows/release.yml)
[![npm](https://img.shields.io/npm/v/%40juanjofuchs%2Fagent-mail)](https://www.npmjs.com/package/@juanjofuchs/agent-mail)
[![PyPI](https://img.shields.io/pypi/v/agent-mail-cli)](https://pypi.org/project/agent-mail-cli/)
[![Python](https://img.shields.io/pypi/pyversions/agent-mail-cli)](https://pypi.org/project/agent-mail-cli/)
[![GitHub Release](https://img.shields.io/github/v/release/JuanjoFuchs/agent-mail-cli)](https://github.com/JuanjoFuchs/agent-mail-cli/releases)
[![WinGet](https://img.shields.io/badge/WinGet-pending%20review-yellow)](https://github.com/microsoft/winget-pkgs/pull/371963)
[![npm downloads](https://img.shields.io/npm/dt/%40juanjofuchs%2Fagent-mail?label=npm%20downloads)](https://www.npmjs.com/package/@juanjofuchs/agent-mail)
[![PyPI downloads](https://img.shields.io/pepy/dt/agent-mail-cli?label=pypi%20downloads)](https://pepy.tech/project/agent-mail-cli)
[![GitHub downloads](https://img.shields.io/github/downloads/JuanjoFuchs/agent-mail-cli/total?label=github%20downloads)](https://github.com/JuanjoFuchs/agent-mail-cli/releases)
[![License](https://img.shields.io/github/license/JuanjoFuchs/agent-mail-cli)](LICENSE)

A self-describing local inbox for coding agents.

<p align="center">
  <a href="docs/agent-mail-hero.mp4">
    <img src="docs/agent-mail-hero.gif" alt="Agent Mail CLI demo" width="800">
  </a>
</p>

```bash
npx -y @juanjofuchs/agent-mail describe
```

That command is the product wedge: an agent can run it, read the JSON schema,
and learn how to send, read, acknowledge, and inspect messages without MCP
setup, a daemon, or separate documentation.

## Status

This repository is the open-source extraction of a working internal tool.
`src/agent_mail/cli.py` is the Python implementation and source of truth for
behavior. Spec 001 is the behavioral specification. Spec 002 covers Python
packaging, GitHub Release binaries, and WinGet. Spec 003 covers npm and `npx`.

## Why

Multi-agent coding workflows need coordination. Heavy systems already exist
for that: MCP servers, agent frameworks, workspace managers, and network
protocols.

Agent Mail CLI is aimed at the simpler moment:

> I am already inside Claude Code or Codex. I need this agent to send a
> handoff to that agent. I want one command that teaches both sides the
> mailbox.

## Installation

### npx

The primary experience is one command. The npm package name is scoped because
npm rejected the unscoped `agent-mail` and `agent-mail-cli` names; the installed
command remains `agent-mail`.

```bash
npx -y @juanjofuchs/agent-mail describe
```

### npm

```bash
npm install -g @juanjofuchs/agent-mail
agent-mail describe
```

The npm package also exposes `agent-mail-cli` as an alias for compatibility:

```bash
agent-mail-cli describe
```

### pipx

```bash
pipx install agent-mail-cli
agent-mail describe
```

For one-shot Python execution:

```bash
pipx run --spec agent-mail-cli agent-mail describe
```

From source:

```bash
python -m agent_mail describe
```

### WinGet

WinGet support has been submitted and is waiting on Microsoft's package review.
After approval:

```powershell
winget install JuanjoFuchs.agent-mail-cli
```

## Intended Usage

Sender:

```bash
npx -y @juanjofuchs/agent-mail send --from second-brain:main --to ccburn:worker --subject "Review spec" --body "Please read the referenced spec and report risks."
```

Recipient:

```bash
npx -y @juanjofuchs/agent-mail read ccburn:worker
```

Recipient staying reachable without a timed poll loop. `watch` blocks until mail
arrives, so waiting costs nothing — the process sleeps, not the model:

```bash
# Blocks up to 55 minutes, or returns an empty result. Use --once to check
# without blocking; the wait is in MINUTES (--timeout-minutes, floor 5).
npx -y @juanjofuchs/agent-mail watch ccburn:worker

# watch reports envelopes and marks nothing read — always follow it with read.
npx -y @juanjofuchs/agent-mail read ccburn:worker
```

The default is 55 rather than a round hour on purpose: a blocked watch makes no
API calls, so nothing refreshes the caller's prompt cache while it waits. 55
minutes is the longest wait that still wakes inside a one-hour cache window,
where the context is re-read at cache-read price instead of rewritten.

### Every result tells you what to do next

The failure that costs the most is an agent that stops watching: mail is still
accepted for it, the sender sees no error, and the only symptom is silence. So
`watch`, `read`, and `ack` each answer with `reachable` and a `next` list of
literal commands, computed from the state that call just observed:

```jsonc
// agent-mail read ccburn:worker
{
  "agent": "ccburn:worker",
  "messages": [ /* ... */ ],
  "count": 1,
  "reachable": false,
  "next": [
    "agent-mail ack ccburn:worker --all",
    "agent-mail watch ccburn:worker"
  ]
}
```

`next` shrinks as steps get done — the ack line appears only when something is
genuinely outstanding, the watch line only when nothing is armed. Guidance keyed
to state beats guidance keyed to memory: `describe` is read once at orientation,
and by the time it matters an agent is holding fifty other instructions.

Acknowledging is one call for a whole batch, so it is not a per-message chore:

```bash
npx -y @juanjofuchs/agent-mail ack ccburn:worker --all
```

Replying acknowledges what it answers, since a reply is evidence the message was
acted on:

```bash
npx -y @juanjofuchs/agent-mail send --from ccburn:worker --to second-brain:main \
  --subject "Reviewed" --body "Two risks, in the refs." --reply-to <message-id>
```

Sender checking whether a recipient is actually listening, rather than guessing
from silence:

```bash
npx -y @juanjofuchs/agent-mail status --agent ccburn:worker --fields agent,watching,last_seen
```

## Watching a fleet of agents

`agent-mail view` is a live dashboard for humans — the one command that answers
"who is stuck?" without reading a single message. It is read-only: it opens the
mailbox in read-only mode and never marks anything read, so watching cannot
consume mail addressed to an agent.

<p align="center">
  <img src="docs/view-agents.svg" alt="agent-mail view — agents panel" width="840">
</p>

Agents are ranked by frecency, so the team currently working fills the window.
`wait` is how long the oldest unread message has sat there, which is the signal
that an inbox is piling up: above, `docs:writer` was asked three times, stopped
watching 26 minutes ago, and has acknowledged nothing. Live agents are always
shown, even when they are quiet.

Press `tab` for the flow panel — directed edges, so `A ▸ B` and `B ▸ A` are
separate facts, with `!n` counting what the recipient never acknowledged:

<p align="center">
  <img src="docs/view-flow.svg" alt="agent-mail view — flow panel" width="840">
</p>

```bash
agent-mail view                    # 1s refresh, q to quit
agent-mail view --window 120       # widen the history window
agent-mail view --once             # print one frame and exit
agent-mail view --ascii --no-color # plain terminals
```

`view` is deliberately absent from `describe`: it blocks by design, and an agent
that found it in its schema would hang a turn on a TUI. It is for you, not them.

## Design Goals

- Runtime schema introspection through `describe`
- JSON output by default
- JSON errors on stderr
- Local durable mailbox state
- No registration
- No daemon
- No MCP server required for v1
- Stable storage outside npm cache (post-packaging)
- One-command install for users without the source script

### One rule the surface keeps re-learning

**A surface that lets an agent choose wrongly will be chosen wrongly. Remove the
choice, or make the wrong value unreachable — do not document your way out of
it.** The documentation had been correct and ignored for months in every case:

| The wrong choice | What was tried first | What actually worked |
|---|---|---|
| `--timeout 30` (seconds, off by 60×) | A correct 900-second default | Put the unit in the name: `--timeout-minutes`, floor 5 |
| A 24-hour TTL nobody chose | Documenting the expiry | Delete the TTL; `cleanup --older-than <days>` is now the only deletion |
| Pasting a document into the body | A `content_routing` rule since v1 | Cap the body at 2000 chars and reject, naming the fix |
| Never acknowledging | An invariant explaining ack | One call for a batch, and replying acks for free |
| Never re-arming the watch | An invariant saying "re-arm" | Every result carries `next`, computed from current state |

## Repository Structure

```text
.
├── AGENTS.md
├── CHANGELOG.md
├── CLAUDE.md
├── LICENSE
├── PROJECT_UNDERSTANDING.md
├── README.md
├── docs/
│   ├── landscape.md
│   ├── view-agents.svg
│   └── view-flow.svg
├── npm/
│   ├── bin/
│   │   └── agent-mail.js
│   ├── scripts/
│   │   └── postinstall.js
│   ├── LICENSE
│   ├── README.md
│   └── package.json
├── specs/
│   ├── 001-agent-mail-cli.md
│   ├── 002-packaging.md
│   ├── 003-npm-distribution.md
│   ├── 004-output-integrity.md
│   ├── 005-storage-transparency.md
│   ├── 006-inbox-watch.md
│   ├── 007-wrapper-resolution.md
│   ├── 008-remove-the-wrong-choices.md
│   ├── 009-rearm-state.md
│   ├── 010-messages-are-not-documents.md
│   └── 011-close-the-loop.md
├── scripts/
│   └── make_screenshots.py
└── src/
    └── agent_mail/
        ├── __init__.py
        ├── __main__.py
        ├── cli.py
        └── view.py
```

## Specs

- [specs/001-agent-mail-cli.md](specs/001-agent-mail-cli.md) — behavioral
  specification. Status: pending review.
- [specs/002-packaging.md](specs/002-packaging.md) — PyPI, GitHub Release
  binaries, and WinGet packaging.
- [specs/003-npm-distribution.md](specs/003-npm-distribution.md) — npm wrapper
  and `npx` distribution.
- [specs/004-output-integrity.md](specs/004-output-integrity.md) — UTF-8 output
  and commit-after-output durability.
- [specs/005-storage-transparency.md](specs/005-storage-transparency.md) —
  `describe` reports the mailbox it actually resolved.
- [specs/006-inbox-watch.md](specs/006-inbox-watch.md) — blocking inbox watch
  and watcher liveness.
- [specs/007-wrapper-resolution.md](specs/007-wrapper-resolution.md) — npm
  wrapper binary resolution and diagnosability.
- [specs/008-remove-the-wrong-choices.md](specs/008-remove-the-wrong-choices.md)
  — messages persist; the watch wait is bounded in minutes.
- [specs/009-rearm-state.md](specs/009-rearm-state.md) — a watch that exits
  reports that the agent is now unreachable, and what to run.
- [specs/010-messages-are-not-documents.md](specs/010-messages-are-not-documents.md)
  — body and subject length caps; `--refs` resolved to absolute paths.
- [specs/011-close-the-loop.md](specs/011-close-the-loop.md) — next-step hints on
  every command, batch acknowledgement, and the `view` dashboard.

## Naming

- Product: Agent Mail CLI
- Repo: `agent-mail-cli`
- npm package: `@juanjofuchs/agent-mail`
- Python distribution: `agent-mail-cli`
- Python import package: `agent_mail`
- Command: `agent-mail`
- Command alias from npm: `agent-mail-cli`

## License

MIT
