|
7 | 7 | </p> |
8 | 8 |
|
9 | 9 | <p align="center"> |
10 | | - <strong>Message broker for Claude Code agents</strong> |
| 10 | + <strong>Cross-boundary messaging for Claude Code</strong> |
11 | 11 | </p> |
12 | 12 |
|
13 | 13 | <p align="center"> |
14 | | - Working with Claude in multiple tabs and sharing context between agents can be painful.<br> |
15 | | - Postino (<em>mailman</em> in Italian) gives your agents a way to talk to each other. |
| 14 | + Claude Code agents in the same team can already talk via SendMessage.<br> |
| 15 | + Postino (<em>mailman</em> in Italian) connects everything <em>outside</em> that bubble:<br> |
| 16 | + different tabs, different teams, different sessions, CI pipelines, external scripts, and humans via a web GUI. |
16 | 17 | </p> |
17 | 18 |
|
18 | 19 | <p align="center"> |
19 | | - <a href="#features">Features</a> · |
| 20 | + <a href="#why-postino">Why</a> · |
20 | 21 | <a href="#quick-start">Quick Start</a> · |
| 22 | + <a href="#examples">Examples</a> · |
21 | 23 | <a href="#mcp-tools">Tools</a> · |
22 | | - <a href="#agent-teams-example">Teams</a> · |
23 | 24 | <a href="#web-gui">GUI</a> · |
24 | 25 | <a href="#how-it-works">How It Works</a> · |
25 | 26 | <a href="#configuration">Config</a> |
@@ -83,23 +84,21 @@ npx @manuelfedele/postino uninstall |
83 | 84 |
|
84 | 85 | --- |
85 | 86 |
|
86 | | -## Features |
| 87 | +## Why Postino |
87 | 88 |
|
88 | | -**1-to-1 Messaging** — Send messages to specific agents. Messages are consumed on read, like a work queue. No duplicates, no stale data. |
| 89 | +Claude Code teams have built-in `SendMessage`. It works great inside a single team. Postino exists for everything else: |
89 | 90 |
|
90 | | -**Broadcasts** — Announce to all agents at once. Every agent sees broadcasts independently. They expire by TTL, not by reading. |
| 91 | +| Scenario | SendMessage | Postino | |
| 92 | +|:---------|:-----------:|:-------:| |
| 93 | +| Agents in the same team | Yes | Yes | |
| 94 | +| Agents in different tabs (no team) | No | **Yes** | |
| 95 | +| Agents in different teams | No | **Yes** | |
| 96 | +| Messages that survive session restarts | No | **Yes** | |
| 97 | +| External scripts/CI pushing messages to agents | No | **Yes** | |
| 98 | +| Humans sending messages via browser | No | **Yes** | |
| 99 | +| Live dashboard of all agent activity | No | **Yes** | |
91 | 100 |
|
92 | | -**Agent Discovery** — Agents auto-register with unique identities derived from the terminal session. See who's online, who has unread messages. |
93 | | - |
94 | | -**Agent Rename** — Agents can rename themselves to meaningful names like `devops-agent` or `reviewer`. The name propagates instantly. |
95 | | - |
96 | | -**Real-time Web GUI** — Browse inboxes, send messages, view broadcasts. Updates live via SSE. Works offline (no CDN dependencies). |
97 | | - |
98 | | -**Zero Config** — Each Claude Code tab gets a unique agent name automatically. No setup required beyond having Valkey/Redis running. |
99 | | - |
100 | | -**Smart Hooks** — A `UserPromptSubmit` hook checks for new messages before each prompt. Silent when there's nothing new (zero token cost). Alerts Claude when messages arrive. |
101 | | - |
102 | | -**Persistent GUI Daemon** — The web GUI runs as a standalone process, auto-started on the first session. It stays alive after all Claude Code sessions close, so you always have a dashboard. |
| 101 | +If all your agents are in one team, you don't need postino. If you work across tabs, sessions, or want external systems to reach your agents, you do. |
103 | 102 |
|
104 | 103 | --- |
105 | 104 |
|
@@ -143,57 +142,82 @@ This starts the web server and Valkey connection without MCP/stdio, so it stays |
143 | 142 |
|
144 | 143 | --- |
145 | 144 |
|
146 | | -## Agent Teams Example |
| 145 | +## Examples |
| 146 | + |
| 147 | +### CI pipeline notifying all agents |
| 148 | + |
| 149 | +A deploy script broadcasts a freeze. Every active Claude Code session sees it on the next prompt. |
| 150 | + |
| 151 | +```bash |
| 152 | +# From your CI pipeline or a shell script |
| 153 | +curl -X POST http://localhost:3333/api/broadcasts \ |
| 154 | + -H 'Content-Type: application/json' \ |
| 155 | + -d '{"from":"ci-bot","body":"Deploy freeze until Monday. Do not merge to release."}' |
| 156 | +``` |
| 157 | + |
| 158 | +Every agent's `UserPromptSubmit` hook picks this up automatically: |
| 159 | + |
| 160 | +``` |
| 161 | +[postino] 1 new broadcast(s). Call msg_read now to handle them before continuing your work. |
| 162 | +``` |
| 163 | + |
| 164 | +### Cross-tab coordination |
| 165 | + |
| 166 | +You have Claude open in three terminal tabs: one refactoring the API, one writing tests, one reviewing docs. They're not in a team, just separate sessions. |
| 167 | + |
| 168 | +``` |
| 169 | +Tab 1 (API refactor): |
| 170 | + > "Rename yourself to api-refactor and broadcast that you changed the auth middleware signature" |
| 171 | +
|
| 172 | + msg_rename("api-refactor") |
| 173 | + msg_broadcast("Breaking change: auth middleware now takes a Context instead of Request. Update callers.") |
| 174 | +
|
| 175 | +Tab 2 (tests): |
| 176 | + [postino] 1 new broadcast(s). Call msg_read now to handle them before continuing your work. |
147 | 177 |
|
148 | | -Postino shines when Claude Code agents work as a team. Each teammate gets its own MCP server and Valkey connection, enabling direct messages and broadcasts across the team. |
| 178 | + msg_broadcasts() |
| 179 | + > from: api-refactor |
| 180 | + > "Breaking change: auth middleware now takes a Context instead of Request. Update callers." |
| 181 | + |
| 182 | + (agent updates test mocks accordingly) |
149 | 183 |
|
150 | | -Here's a real session with two agents coordinating a code review: |
| 184 | +Tab 3 (docs): |
| 185 | + [postino] 1 new broadcast(s). Call msg_read now to handle them before continuing your work. |
151 | 186 |
|
| 187 | + msg_broadcasts() |
| 188 | + > (same broadcast, updates API docs) |
152 | 189 | ``` |
153 | | -You: "Spin up two agents to review the heartbeat TTL in valkey.ts" |
154 | | -
|
155 | | -┌─────────────────────────────────────────────────────────────────┐ |
156 | | -│ agent-a │ |
157 | | -│ │ |
158 | | -│ 1. msg_rename("agent-a") │ |
159 | | -│ 2. msg_send(to="agent-b", │ |
160 | | -│ "Found a bug in src/valkey.ts line 55 - │ |
161 | | -│ the heartbeat TTL should be 60 not 30. Can you review?") │ |
162 | | -│ 3. msg_broadcast("Team standup: agent-a is investigating │ |
163 | | -│ heartbeat TTL values") │ |
164 | | -│ 4. msg_whoami() │ |
165 | | -│ > agent-b: online, 1 queued message │ |
166 | | -└─────────────────────────────────────────────────────────────────┘ |
167 | | -
|
168 | | -┌─────────────────────────────────────────────────────────────────┐ |
169 | | -│ agent-b │ |
170 | | -│ │ |
171 | | -│ 1. msg_rename("agent-b") │ |
172 | | -│ 2. msg_whoami() │ |
173 | | -│ > 1 unread message, 1 unseen broadcast │ |
174 | | -│ 3. msg_read() │ |
175 | | -│ > from: agent-a │ |
176 | | -│ > "Found a bug in src/valkey.ts line 55 - │ |
177 | | -│ the heartbeat TTL should be 60 not 30. Can you review?" │ |
178 | | -│ 4. msg_broadcasts() │ |
179 | | -│ > from: agent-a │ |
180 | | -│ > "Team standup: agent-a is investigating │ |
181 | | -│ heartbeat TTL values" │ |
182 | | -│ 5. msg_send(to="agent-a", │ |
183 | | -│ "Got it, I'll review the heartbeat TTL. │ |
184 | | -│ Looks like 60s makes sense for production workloads.") │ |
185 | | -└─────────────────────────────────────────────────────────────────┘ |
| 190 | + |
| 191 | +No team setup. No shared context. Each tab works independently and stays informed. |
| 192 | + |
| 193 | +### Leave a message for the next session |
| 194 | + |
| 195 | +You're done for the day. Leave a note for tomorrow's session: |
| 196 | + |
| 197 | +```bash |
| 198 | +curl -X POST http://localhost:3333/api/messages \ |
| 199 | + -H 'Content-Type: application/json' \ |
| 200 | + -d '{"to":"agent-A1B2C3D4","body":"Pick up where I left off: the migration is half done, see TODO in db/migrate.ts"}' |
186 | 201 | ``` |
187 | 202 |
|
188 | | -Messages flow through Valkey in real time. Direct messages are consumed on read (work queue pattern), broadcasts persist for all agents. When agents shut down, they deregister and clean up automatically. |
| 203 | +Or from within Claude Code: |
189 | 204 |
|
190 | | -**What postino adds over built-in agent messaging:** |
| 205 | +``` |
| 206 | +> "Send a message to agent-A1B2C3D4: the staging deploy needs a config fix before we can test" |
| 207 | +``` |
| 208 | + |
| 209 | +Tomorrow's session starts, the hook fires: |
| 210 | + |
| 211 | +``` |
| 212 | +[postino] You are "agent-A1B2C3D4". 0 other agent(s) online. |
| 213 | +[postino] 1 unread message(s). Call msg_whoami now. |
| 214 | +``` |
| 215 | + |
| 216 | +### Human-to-agent via the web GUI |
191 | 217 |
|
192 | | -- **Cross-team / cross-session** — agents in different tabs or teams can message each other |
193 | | -- **Broadcasts** — one-to-many announcements without knowing recipients |
194 | | -- **Persistence** — messages survive agent restarts (TTL-based expiry) |
195 | | -- **Web GUI** — real-time monitoring at localhost:3333 |
196 | | -- **Hooks** — automatic inbox check on every prompt, zero token cost via HTTP |
| 218 | +Open **http://localhost:3333** in your browser. Pick an agent from the sidebar, type a message. The agent sees it on the next prompt. No CLI needed. |
| 219 | + |
| 220 | +Use this to steer agents mid-task, inject context, or send instructions without switching to the terminal. |
197 | 221 |
|
198 | 222 | --- |
199 | 223 |
|
@@ -262,13 +286,15 @@ graph LR |
262 | 286 | VK -->|pub/sub| GUI |
263 | 287 | GUI -->|SSE| Browser |
264 | 288 |
|
265 | | - H[Hook<br/>session-start.sh] -->|auto-start| GUI |
266 | | - H2[Hook<br/>check-messages.sh] -->|curl /api/check| GUI |
| 289 | + CI[CI / Scripts] -->|curl /api| GUI |
| 290 | + Browser -->|POST /api| GUI |
| 291 | +
|
| 292 | + H[Hooks] -->|curl /api/check| GUI |
267 | 293 |
|
268 | 294 | style VK fill:#e63030,color:#fff,stroke:none |
269 | 295 | style GUI fill:#2563eb,color:#fff,stroke:none |
| 296 | + style CI fill:#059669,color:#fff,stroke:none |
270 | 297 | style H fill:#d97706,color:#fff,stroke:none |
271 | | - style H2 fill:#d97706,color:#fff,stroke:none |
272 | 298 | ``` |
273 | 299 |
|
274 | 300 | ### Under the Hood |
|
0 commit comments