agent-team-mail (atm)
agent-team-mail is the retained 1.0 CLI and core library for local ATM
mailbox workflows.
This repository is now the source of truth for publishing:
agent-team-mail
agent-team-mail-core
The installed command remains atm.
What 1.0 Includes
The retained 1.0 release scope is the daemon-free CLI/core pair:
agent-team-mail — the atm CLI
agent-team-mail-core — the core Rust library used by the CLI
This release line continues to consume the published sc-observability family
for retained logging and health reporting:
sc-observability
sc-observability-types
sc-observability-otlp
This repo does not publish the retired legacy daemon, MCP, TUI, or CI-monitor
artifacts as part of the retained 1.0 surface.
Installation
GitHub Releases
Download the latest release from
GitHub Releases.
Published archives:
| Platform | Archive |
|---|
| Linux (x86_64) | atm__x86_64-unknown-linux-gnu.tar.gz |
| macOS (Intel) | atm__x86_64-apple-darwin.tar.gz |
| macOS (Apple Silicon) | atm__aarch64-apple-darwin.tar.gz |
| Windows (x86_64) | atm__x86_64-pc-windows-msvc.zip |
Extract the archive and place atm or atm.exe somewhere on your PATH.
Homebrew
brew tap randlee/tap
brew install randlee/tap/agent-team-mail
crates.io
cargo install agent-team-mail
The library crate is also published as:
cargo add agent-team-mail-core
winget
winget install randlee.agent-team-mail
winget is a new required 1.0 Windows channel rather than a historical
parity channel from the old repo. Public winget installability may lag by
1-2 days after release because Microsoft reviews new submissions and updates
before they become broadly visible.
Build From Source
git clone https://github.com/randlee/atm-core.git
cd atm-core
cargo install --path crates/atm --bin atm
Quick Start
ATM works against the local Claude team mailbox layout under ~/.claude/teams.
Typical flows:
Send a message
atm send teammate "Hello from ATM"
atm send teammate@other-team "Cross-team message"
atm send teammate "Please confirm" --requires-ack
Read your mailbox
atm read
atm read --all --no-mark
atm read --pending-ack-only
Acknowledge or clear messages
atm ack "Acknowledged"
atm clear
Inspect health and retained logs
atm doctor
atm log snapshot --level warn
Manage teams
atm teams
atm members my-team
atm teams add-member my-team teammate
atm teams backup my-team
atm teams restore my-team --from backup.tar.gz --dry-run
Run atm --help or atm --help for the full command surface.
CLI Surface
The retained CLI includes:
send
read
ack
clear
log
doctor
teams
members
The teams command also contains retained team-administration subcommands:
add-member
backup
restore
Configuration Notes
ATM resolves runtime identity and team context from the current CLI/config
surface and uses the local Claude team directory layout for mailbox storage.
Post-Send Hook
atm send can run an optional post-send hook configured in .atm.toml:
[[atm.post_send_hooks]]
recipient = "team-lead"
command = ["scripts/atm-nudge.sh", "team-lead"]
[[atm.post_send_hooks]]
recipient = "arch-ctm"
command = ["scripts/atm-nudge.sh", "arch-ctm"]
Behavior:
- Each
[[atm.post_send_hooks]] rule binds one recipient and one command.
recipient matches either one exact member name or * for all recipients.
- Multiple matching rules all run, in config order.
- If
command[0] is path-like, ATM resolves it relative to the directory containing .atm.toml.
- Bare executables like
bash, python3, or tmux use normal PATH resolution.
- Recipient non-match is silent.
- ATM rejects retired
post_send_hook, post_send_hook_senders, post_send_hook_recipients, and post_send_hook_members keys with migration guidance.
- ATM sets
ATM_POST_SEND to a JSON payload with {from, to, sender, recipient, team, message_id, requires_ack} plus optional task_id when present.
- The hook gets 5 seconds to complete.
- Hook stderr is suppressed. Hook stdout may optionally return one JSON object with
level, message, and optional fields for ATM to log.
- For troubleshooting hook diagnostics, combine
--stderr-logs with ATM_LOG=debug to surface debug-level hook results on stderr.
- If the hook exits non-zero, fails to start, or times out,
atm send still succeeds and prints a warning.
Example ATM_POST_SEND payload:
{
"from": "team-lead@atm-dev",
"to": "arch-ctm@atm-dev",
"sender": "team-lead",
"recipient": "arch-ctm",
"team": "atm-dev",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"requires_ack": true
}
Example tmux auto-nudge hook for a Codex pane:
#!/usr/bin/env bash
set -euo pipefail
readarray -t fields < <(python3 - <<'PY'
import json, os
payload = json.loads(os.environ["ATM_POST_SEND"])
print(payload["to"].split("@", 1)[0])
print(payload["to"].split("@", 1)[1])
PY
)
recipient="${fields[0]}"
team="${fields[1]}"
tmux send-keys -t "$recipient" "You have unread ATM messages. Run: atm read --team $team" Enter
Optional structured hook result on stdout:
{"level":"debug","message":"arch-ctm nudged on pane %42","fields":{"pane_id":"%42"}}
Useful docs in this repo:
Development
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace