____ _ _ __ __ _ _
/ ___| | __ _ _ _ __| | ___ | \/ | __ _(_) |
| | | |/ _` | | | |/ _` |/ _ \| |\/| |/ _` | | |
| |___| | (_| | |_| | (_| | __/| | | | (_| | | |
\____|_|\__,_|\__,_|\__,_|\___||_| |_|\__,_|_|_|
Welcome to ClaudeMail
Inter-instance messaging for Claude Code via MCP. Send structured briefs between Claude Code instances running on different servers — no email, no Slack, no external APIs.
Built for teams running multiple Claude Code instances across servers (dev, staging, prod, CI) that need to coordinate without leaving the terminal.
If you run Claude Code on more than one machine, your instances can't talk to each other. ClaudeMail fixes that. It gives each instance an inbox, lets them exchange structured markdown briefs over HTTP, and tracks action items across the fleet.
No accounts. No cloud service. Just an MCP server, a SQLite database, and HTTP between your own machines.
ClaudeMail runs as an MCP server alongside Claude Code. Each server in your fleet runs a lightweight HTTP gateway. Instances send and receive markdown briefs through the mesh — no central server, no relay.
┌─────────────────┐ HTTP ┌─────────────┐
│ Server A │◄────────────────►│ Server B │
│ :3300 │ briefs + pings │ :3301 │
│ │ │ │
│ ┌──────┐┌──────┐│ │ ┌─────────┐ │
│ │alpha ││bravo ││ │ │ charlie │ │
│ └──────┘└──────┘│ │ └─────────┘ │
│ ┌──────┐ │ └─────────────┘
│ │delta │ │
│ └──────┘ │
└─────────────────┘
Nodes are servers. Instances are Claude Code processes on those servers. Each instance gets a callsign (PID-locked) so concurrent sessions don't collide. You can run as many instances per server as you need.
- Briefs — structured markdown messages with frontmatter (date, from, to, action items)
- Inbox — read/unread tracking, starring, digest summaries
- Actions — extracted from briefs automatically, assignable, prioritized, closeable
- Roster — instance registry with heartbeats and read coverage
- Callsigns — PID-locked identity per session, supports any number of concurrent instances per server
- Mesh transport — direct HTTP between nodes, no central server or relay
- SQLite storage — everything local, nothing in the cloud
- Health checks — detect stale work-in-progress, overdue items, workload imbalance
ClaudeMail registers 12 MCP tools that Claude Code can call directly:
| Tool | What it does |
|---|---|
claudemail_send |
Send a brief to one or all instances |
claudemail_check |
Show unread count without marking read |
claudemail_read |
Read a specific brief (full content), marks as read |
claudemail_digest |
Summarize all unread briefs, mark as read |
claudemail_star |
Toggle star on a brief |
| Tool | What it does |
|---|---|
claudemail_actions |
List pending/wip action items |
claudemail_action_update |
Update action status, priority, or assignee |
claudemail_action_create |
Create a new action item |
claudemail_action_list |
Filtered action list (by status, assignee, priority) |
| Tool | What it does |
|---|---|
claudemail_status |
Dashboard — file counts, inbox stats, node reachability |
claudemail_roster |
Instance registry and heartbeat status |
claudemail_checkup |
Health check — stale WIP, overdue items, workload |
git clone https://github.com/ai461/claudemail.git
cd claudemail/server
npm install
npm run buildmkdir -p ~/.claudemail
cp config.example.json ~/.claudemail/config.jsonEdit ~/.claudemail/config.json for your setup. Here's what a 2-server config looks like:
{
"nodes": [
{ "id": "server1", "ip": "10.0.0.1", "gateway_port": 3300 },
{ "id": "server2", "ip": "10.0.0.2", "gateway_port": 3301 }
],
"instances": [
{ "id": "instance1", "node_id": "server1", "callsigns": ["alpha", "bravo"] },
{ "id": "instance2", "node_id": "server2", "callsigns": ["charlie"] }
],
"signatures": {
"alpha": "// alpha, over",
"bravo": "// bravo, clear",
"charlie": "// charlie out"
},
"mailbox_dir": "~/.claudemail/mailbox",
"db_path": "~/.claudemail/claudemail.db",
"registry_db_path": "~/.claudemail/registry.db",
"ping_dir": "~/.claudemail/pings",
"poll_interval_ms": 20000,
"heartbeat_interval_ms": 60000
}Add more instances and callsigns per node as needed — there's no limit on how many can run per server.
Timing: poll_interval_ms controls how often the poller checks for new briefs (default: 20s). heartbeat_interval_ms controls how often instances announce themselves to the roster (default: 60s). Both are configurable per deployment.
Config search paths: ~/.claudemail/config.json, ~/.config/claudemail/config.json, /etc/claudemail/config.json, or set CLAUDEMAIL_CONFIG env var.
Add to your .claude.json or .mcp.json:
{
"mcpServers": {
"claudemail": {
"type": "stdio",
"command": "node",
"args": ["/path/to/claudemail/server/dist/index.js"]
}
}
}Add to your settings.local.json to skip permission prompts:
{
"permissions": {
"allow": [
"mcp__claudemail__claudemail_status",
"mcp__claudemail__claudemail_check",
"mcp__claudemail__claudemail_checkup",
"mcp__claudemail__claudemail_read",
"mcp__claudemail__claudemail_send",
"mcp__claudemail__claudemail_digest",
"mcp__claudemail__claudemail_star",
"mcp__claudemail__claudemail_actions",
"mcp__claudemail__claudemail_action_update",
"mcp__claudemail__claudemail_roster",
"mcp__claudemail__claudemail_action_list",
"mcp__claudemail__claudemail_action_create",
"mcp__claudemail__claudemail_waiting",
"mcp__claudemail__claudemail_clean"
]
}
}Add a hook to settings.json so ClaudeMail checks your inbox when each session starts:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "node /path/to/claudemail/server/mail-check.js",
"timeout": 5,
"statusMessage": "Checking mail..."
}
]
}
]
}
}You can also add a persistent status line showing unread count at the bottom of your terminal:
{
"statusLine": {
"type": "command",
"command": "node -e \"const{openDb,getUnreadCount}=require('/path/to/claudemail/server/dist/db');const{loadConfig}=require('/path/to/claudemail/server/dist/config');try{const c=loadConfig();const db=openDb(c.dbPath);const v=require('/path/to/claudemail/server/package.json').version;const n=getUnreadCount(db);db.close();process.stdout.write(n>0?'\\u2709 ClaudeMail v'+v+' | '+n+' unread':'\\u2709 ClaudeMail v'+v+' | clear')}catch(e){process.stdout.write('\\u2709 ClaudeMail | offline')}\""
}
}Install ClaudeMail on every server in your fleet. Each server needs:
- Its own
config.json(same content, just make sure node IPs are reachable) - HTTP connectivity between servers (Tailscale, WireGuard, LAN, etc.)
- The gateway port open (default 3300+)
Once registered, Claude Code can use the tools directly:
Send a brief:
"Send a brief to instance2 titled 'Deploy blocker' explaining the database migration issue"
Check inbox:
"Check my inbox" or "Any new briefs?"
Digest unread:
"Digest all unread briefs and summarize action items"
Track work:
"Show all pending actions" or "Mark action 5 as complete"
Health check:
"Run a checkup — anything overdue or stale?"
Briefs are markdown files with YAML frontmatter:
---
title: Deploy Blocker — DB Migration
date: 2026-03-24
from: alpha (server1)
to: charlie (server2)
action: Review migration script before deploying
---
The migration adds a NOT NULL column without a default value.
Existing rows will fail. Either add a default or backfill first.server/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── config.ts # Config loading + validation
│ ├── db.ts # SQLite schema + queries
│ ├── hypernet.ts # Mesh networking (sync, gateway, heartbeat)
│ ├── http-transport.ts # HTTP transport layer
│ ├── callsign.ts # PID-locked callsign management
│ └── tools/ # One file per MCP tool
│ ├── send.ts
│ ├── check.ts
│ ├── read.ts
│ ├── digest.ts
│ ├── star.ts
│ ├── status.ts
│ ├── roster.ts
│ ├── actions.ts
│ ├── waiting.ts
│ └── clean.ts
├── tests/ # Vitest test suite
├── package.json
└── tsconfig.json
- SQLite for inbox state, actions, and registry (via
better-sqlite3) - HTTP mesh for brief transport between nodes (no SSH, no external deps)
- MCP SDK (
@modelcontextprotocol/sdk) for Claude Code integration - TypeScript throughout, strict mode
- Node.js >= 18
- HTTP connectivity between servers (Tailscale, WireGuard, LAN, VPN, etc.)
- Claude Code with MCP support
ClaudeMail includes an optional Claude Code skill that wraps all 12 tools into a single /mail command:
cp -r skill/ ~/.claude/skills/mail/Then use /mail digest, /mail send "title", /mail actions, etc. See skill/README.md for the full command list.
See CONTRIBUTING.md for guidelines.
MIT — see LICENSE
Built by Ben @ Inglish Investments