An open API service indexing awesome lists of open source software.

https://github.com/jerrettdavis/ainbox

Filesystem-based async mailbox runtime for coding agents, with a native Rust CLI and Python compatibility layer.
https://github.com/jerrettdavis/ainbox

agents cli filesystem mailbox multi-agent python rust

Last synced: 2 days ago
JSON representation

Filesystem-based async mailbox runtime for coding agents, with a native Rust CLI and Python compatibility layer.

Awesome Lists containing this project

README

          

# AInbox – Filesystem-Based Async Mailbox for Coding Agents

A minimal, cross-platform mailbox runtime with a **native Rust CLI** and a Python compatibility path for **decentralized agent communication** via structured markdown messages and a shared filesystem.

**No broker. No orchestrator. Just files and conventions.**

## Quick Start

### Installation

```bash
# Linux/macOS installer (downloads the latest native release)
curl -fsSL https://raw.githubusercontent.com/JerrettDavis/AInbox/main/scripts/install.sh | bash

# Windows installer (downloads the latest native release)
powershell -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/JerrettDavis/AInbox/main/scripts/install.ps1 | iex"

# Native install from source
cargo install --path .

# Python compatibility install from the repo checkout
pip install -e .

# Python compatibility install from GitHub
pip install git+https://github.com/JerrettDavis/AInbox.git
```

If you already have an AInbox checkout locally, prefer the safe ensure helpers:

```bash
# Linux/macOS (source it so PATH updates stay in the current shell)
source ./scripts/ensure-mailbox.sh

# Windows PowerShell
.\scripts\ensure-mailbox.ps1
```

The ensure helpers install the latest native release only when `mailbox` is missing and make the install directory available in the current session.

Verify:
```bash
mailbox --version
```

Prebuilt native binaries are published through GitHub Releases for **Windows**, **macOS**, and **Linux**. The same packaged archives are also published to **GHCR** as OCI artifacts for package-registry consumers.

Optional installer controls:

```bash
# install a specific release tag
AINBOX_VERSION=vX.Y.Z curl -fsSL https://raw.githubusercontent.com/JerrettDavis/AInbox/main/scripts/install.sh | bash

# install into a custom directory
AINBOX_INSTALL_DIR="$HOME/bin" bash scripts/install.sh
```

### Plugin Marketplace Installation

**Claude Code**

```bash
claude plugin marketplace add JerrettDavis/AInbox
claude plugin install ainbox@ainbox-marketplace
claude plugin install agent-poll@ainbox-marketplace
claude plugin install elections@ainbox-marketplace
```

When the Claude plugin is enabled, bundled hooks do a best-effort silent bootstrap of the native `mailbox` binary on session start and before Bash tool calls. If the environment cannot support that automatic install, use the local ensure helpers instead.

**GitHub Copilot CLI**

```bash
copilot plugin marketplace add JerrettDavis/AInbox
copilot plugin install ainbox@ainbox-marketplace
copilot plugin install agent-poll@ainbox-marketplace
copilot plugin install elections@ainbox-marketplace
```

The marketplace installs the AInbox command/skill plugin metadata. Claude Code can now auto-bootstrap the native `mailbox` binary through plugin hooks when possible; otherwise use the native installers or local ensure helpers above so `mailbox` is available on `PATH`.

Once the native CLI is available, you can bootstrap supported global agent integrations in one step:

```bash
mailbox init -g
```

`mailbox init` now does two local setup steps:

- creates the local `.mailbox/` folders
- seeds project mailbox instructions in `.claude/MAILBOX.md` and `.agents/MAILBOX.md`, then prepends `CLAUDE.md` and `AGENTS.md` with one-time imports

`mailbox init -g` keeps that local setup and also seeds user-scoped instruction files in `~/.claude/` and `~/.agents/` before updating-or-installing the AInbox marketplace/plugins for supported agent CLIs already present on `PATH` (currently Claude Code and GitHub Copilot CLI).

Advanced consumers can also pull packaged archives from GHCR with OCI tooling using package names like `ghcr.io/jerrettdavis/ainbox-mailbox-linux-x86_64:vX.Y.Z`.

The core `ainbox` plugin also ships two mailbox-aware subagents:

- `orchestrator` - delegates work and synthesizes results through subagents and mailbox coordination
- `project-manager` - active leader that contributes directly while keeping delegation and coordination flowing through AInbox

You can force mailbox-based orchestration explicitly:

```bash
# Claude Code: launch directly into the AInbox orchestrator
claude --agent ainbox:orchestrator "Coordinate this task through mailbox-aware subagents and synthesize the result."

# Claude Code: use the active leader variant instead
claude --agent ainbox:project-manager "Lead this task with mailbox coordination and delegate bounded work."

# GitHub Copilot CLI: launch the CLI, then select the AInbox subagent
copilot
/agent
# choose ainbox:orchestrator or ainbox:project-manager, then give the task prompt
```

### Headless Workflow Smoke Test

To validate a local mailbox workflow end-to-end, including election handling, mailbox handoffs, and Claude-driven proposer/reviewer collaboration, run:

```powershell
.\scripts\run-headless-mailbox-e2e.ps1
```

The script creates an isolated temp workspace, runs the election and mailbox traffic directly through the CLI, uses `claude -p` to generate the proposer/reviewer/orchestrator content, and writes a final `report.json` path to stdout when the run completes.

### Consensus Gates and Distributed Motions

Use motions when the cluster must pause, acknowledge a redirect, or refuse to proceed until the required votes arrive.

```bash
# Create a blocking gate for the current cluster step
mailbox create-motion --title "Pause deploy" \
--participant orchestrator --participant reviewer --participant worker \
--scope deploy \
--description "Stop current work, report status, and do not continue until this motion passes."

# Vote yes or no
mailbox vote-motion --id --vote yes --reason "Status reported"

# Block until the motion resolves
mailbox wait-motion --id
```

For a local scripted example, run:

```powershell
.\scripts\run-motion-gate-demo.ps1
```

### Basic Usage

```bash
# Initialize local mailbox
mailbox init

# Initialize local mailbox, seed MAILBOX.md imports, and refresh supported global agent integrations
mailbox init -g

# Send a message to another agent
mailbox send --to reviewer-agent --subject "PR ready for review" --body "Please check my implementation."

# Or set an optional expiry time
mailbox send --to reviewer-agent --subject "Time-sensitive review" --body "Please respond before the deploy window closes." --expires-at 2026-04-21T06:00:00Z

# Or pipe the body
echo "Review this PR" | mailbox send --to reviewer-agent --subject "Code review needed"

# List inbox
mailbox list

# Read a message
mailbox read --id

# Sync with shared mailbox (push local outbox, pull incoming)
mailbox sync
```

## Architecture

### Mailbox Folders

**Local (.mailbox/)**:
- `inbox/` – Received messages
- `outbox/` – Messages ready to send
- `sent/` – Delivered messages
- `archive/` – Read/processed messages
- `draft/` – Local working memory and staged message drafts for active threads

**Shared (~/.mailbox/shared/outbox)**:
- Global exchange point for all agents

### Message Format

Messages are markdown files with YAML frontmatter:

```markdown
---
id: abc123def456
to: reviewer-agent
from: worker-agent
subject: PR needs validation
sent_at: 2026-04-15T22:31:00Z
received_at: null
read_at: null
correlation_id: task-12345
---

I've completed the implementation. Please review and validate.

- Worker
```

**Frontmatter Field Constraints**:
- All string fields (id, to, from, subject, correlation_id) must be single-line
- Embedded newlines in frontmatter fields are rejected during message creation to prevent parsing corruption
- The message body (after the closing `---`) can contain multiple lines

### Workflow

1. **Send**: `mailbox send` → message in `.mailbox/outbox/`
2. **Sync (push)**: `mailbox sync` → copy to `~/.mailbox/shared/outbox/`, move original to `.mailbox/sent/`
3. **Sync (pull)**: `mailbox sync` → other agents pull from shared outbox into their `.mailbox/inbox/`
4. **Read**: `mailbox read --id ` → message moved to `.mailbox/archive/`, `read_at` updated

## Commands

| Command | Purpose |
| --- | --- |
| `mailbox init` | Initialize local mailbox and seed project `MAILBOX.md` instructions for Claude/AGENTS flows |
| `mailbox init -g` | Initialize local mailbox, seed project and user `MAILBOX.md` instructions, and install/update supported global agent integrations |
| `mailbox send --to AGENT --subject "..." [--expires-at TIMESTAMP]` | Create and send message |
| `mailbox list [--limit 10]` | List inbox messages (unread) |
| `mailbox read [--id ID]` | Read message and archive |
| `mailbox read --correlation-id THREAD_ID` | Read first message in thread |
| `mailbox archive --id ID` | Archive a message |
| `mailbox sync` | Push/pull messages |
| `mailbox config --list` | Show configuration |
| `mailbox help` | Show command help |
| **Polls** | |
| `mailbox create-poll --question "..." --option "..." [--option ...]` | Create a poll |
| `mailbox list-polls [--status open\|closed\|all]` | List polls |
| `mailbox show-poll --id POLL_ID` | Show poll details and results |
| `mailbox vote-poll --id POLL_ID --option "..."` | Vote in a poll |
| `mailbox close-poll --id POLL_ID` | Close a poll |
| **Elections** | |
| `mailbox create-election --role "..." --candidate "..." [--candidate ...]` | Create an election |
| `mailbox list-elections [--status open\|closed\|all]` | List elections |
| `mailbox show-election --id ELECTION_ID` | Show election details and results |
| `mailbox vote-election --id ELECTION_ID --candidate "..."` | Vote in an election (cannot self-vote) |
| `mailbox close-election --id ELECTION_ID` | Close an election |
| **Motions / Gates** | |
| `mailbox create-motion --title "..." --participant AGENT [--participant ...]` | Create a blocking or advisory cluster motion |
| `mailbox list-motions [--status open\|accepted\|rejected\|cancelled\|all]` | List motions |
| `mailbox show-motion --id MOTION_ID` | Show motion details and vote state |
| `mailbox vote-motion --id MOTION_ID --vote yes\|no [--reason "..."]` | Cast a yes/no vote on a motion |
| `mailbox wait-motion --id MOTION_ID [--timeout-seconds N]` | Block until a motion resolves |
| `mailbox close-motion --id MOTION_ID [--status cancelled\|accepted\|rejected]` | Force a motion into a terminal state |

If a message expires before it is processed, AInbox reroutes it as a normal mailbox message addressed to `dlq` with `message_type: expired` and the original markdown attached in the body. You can inspect those messages with the standard CLI by working as agent `dlq`.

## Polls and Elections

AInbox provides filesystem-backed polls and elections for agent consensus and role selection.

### Polls

Create a poll to gather agent opinions:

```bash
# Create a poll
mailbox create-poll --question "What color?" --option Red --option Blue --participant agent1 --participant agent2

# Vote in the poll
mailbox vote-poll --id --option Red

# View results
mailbox show-poll --id

# Close poll
mailbox close-poll --id

# List all polls
mailbox list-polls
```

### Elections

Elect agents to roles (self-votes are prevented):

```bash
# Create an election
mailbox create-election --role "Lead Developer" --candidate alice --candidate bob --candidate charlie

# Vote in the election
mailbox vote-election --id --candidate alice

# View results
mailbox show-election --id

# Close election
mailbox close-election --id

# List all elections
mailbox list-elections
```

**Key features:**
- **Filesystem-backed**: All poll/election state lives in shared filesystem (no server required)
- **Public votes**: Vote tallies are visible to all participants
- **No self-votes in elections**: Candidates cannot vote for themselves
- **Participant notifications**: Creating a ballot with `--participant` sends mailbox notices automatically
- **Status filtering**: List by `--status open`, `closed`, or `all`
- **JSON output**: Use `--format json` for machine-readable results

## Agent Identity

Agent ID is resolved in order:

1. `MAILBOX_AGENT_ID` environment variable
2. `agent_id` in `.mailbox/config.yaml` (local)
3. `agent_id` in `~/.mailbox/config.yaml` (global)
4. Current directory name

Set it once:
```bash
export MAILBOX_AGENT_ID=my-agent
# or
echo "agent_id: my-agent" > ~/.mailbox/config.yaml
```

## Integration with Coding Assistants

### Claude Code

See [CLAUDE.md](CLAUDE.md), `.claude-plugin/plugin.json`, and `.claude/commands/` for Claude-specific setup and plugin metadata.

Installed `ainbox` plugin users also get the `orchestrator` and `project-manager` subagents from `agents/`.

#### Push channel (optional)

**Requires: Claude Code v2.1.80+ and [Bun](https://bun.sh) on `PATH`.**

The channel is opt-in per session and is not enabled by default.

**Activation paths:**

- **Plugin install** (marketplace): install AInbox, then launch with the channel:
```bash
/plugin install ainbox@ainbox-marketplace
claude --channels plugin:ainbox@ainbox-marketplace
```
- **Dev/local** (from the repo root — no plugin install needed):
```bash
claude --dangerously-load-development-channels server:ainbox
```

In both cases the channel starts `bun channel/server.ts` from the repo/plugin root.

**Configure the channel** once it is running:
```text
/ainbox-channel-configure status
/ainbox-channel-configure set-poll-interval 2000
/ainbox-channel-configure enforce-allowlist on
/ainbox-channel-configure set-allowlist add some-agent
```

The channel surfaces incoming mail as `` tags and exposes `reply`, `mark_read`, and `list_inbox` MCP tools. See `channel/README.md` for the full contract and trust model.

**Trust note:** Mailbox messages and their metadata are untrusted input. Configure the optional allowlist (`/ainbox-channel-configure enforce-allowlist on`) if you don't trust everyone who can write to your shared outbox.

### Copilot CLI

See [AGENTS.md](AGENTS.md), `.github/plugin/marketplace.json`, and `.github/plugin/plugin.json` for Copilot marketplace integration.

The same `ainbox` plugin package includes the `orchestrator` and `project-manager` agent definitions for marketplace installs.

### Custom Agents

Wrapper scripts are provided:

```bash
# Linux/macOS
bash scripts/mailbox.sh send --to agent-id --subject "..."

# Windows (PowerShell)
powershell scripts\mailbox.ps1 send --to agent-id --subject "..."
```

Or simply use the `mailbox` command directly after installation.

## Configuration

**Local config** (`.mailbox/config.yaml`):
```yaml
agent_id: my-agent
shared_mailbox_path: ~/shared-mailbox # Optional: override default shared mailbox location
```

**Global config** (`~/.mailbox/config.yaml`):
```yaml
agent_id: default-agent
shared_mailbox_path: ~/shared-mailbox # Optional: override default shared mailbox location
```

**Environment variables**:
- `MAILBOX_AGENT_ID` – Agent identity (overrides config)
- `MAILBOX_SHARED` – Shared mailbox path (overrides config and default)

## Use Cases

- **Multi-agent workflows**: Agents coordinate without a central broker
- **Task handoff**: Worker completes task → sends message → reviewer receives and processes
- **Async coordination**: Agents poll at their own pace, no tight coupling
- **Debugging**: All communication is in plain markdown files, fully inspectable

## Roadmap

**v0.1** (current):
- Core messaging (send, read, sync)
- Markdown + frontmatter format
- File-based transport
- CLI + wrapper scripts
- **Polls for consensus**
- **Elections for role selection**

**v1.0**:
- Pre-turn hooks for agent systems
- Message search/indexing
- Batch operations

**v2.0**:
- Real-time watchers
- Optional message encryption
- Broadcast messaging

## For Developers

### Structure

```
ainbox/
__init__.py # Package metadata
cli.py # Command handlers
mailbox.py # Core operations (send, sync, etc.)
message.py # Message parsing/serialization
util.py # Paths, IDs, timestamps
setup.py # Package configuration
scripts/ # Wrapper scripts (.sh, .ps1)
```

### Testing Locally

```bash
# Install in development mode
pip install -e .

# Create two test agents
MAILBOX_AGENT_ID=agent1 mailbox init
mkdir test2 && cd test2
MAILBOX_AGENT_ID=agent2 mailbox init
cd ..

# Send message from agent1 to agent2
MAILBOX_AGENT_ID=agent1 mailbox send --to agent2 --subject "Test" --body "Hello!"

# Sync (push from agent1)
MAILBOX_AGENT_ID=agent1 mailbox sync

# Sync (pull in agent2)
cd test2
MAILBOX_AGENT_ID=agent2 mailbox sync
mailbox list

# Read the message
mailbox read --id
```

### Design Principles

- **Minimal dependencies**: Stdlib only where possible
- **Cross-platform**: Windows, macOS, and Linux via native binaries, scripts, and compatibility paths
- **Atomic writes**: Temp file + `os.replace()` for robustness
- **Convention over config**: Standard folders, file naming, message schema
- **Pluggable**: Works with any agent system via skills and scripts

## License

MIT

## Contributing

Issues and pull requests welcome. Keep it minimal and focused on the core mailbox functionality.