puenteo
Let your coding agents talk to each other.
When you run Claude Code in one terminal, Codex in another and Gemini or Cursor in the IDE, they can't see each other. One renames a column, another breaks on it, and you end up copy-pasting context between windows. puenteo gives every session on your machine:
- 🔎 Shared memory: ranked full-text search over the history of every local agent (Claude Code, Codex, Gemini/Antigravity, Cursor, Copilot, OpenCode, Grok, Pi, Qwen, Continue, Aider, OpenHands, Goose), plus structured handoffs: goal, state, files, commits, failures.
- 💬 Live messaging: see who's running (
puenteo ps), ask another session a question and wait for its answer, broadcast to the project, share #channels.
- 🔒 Coordination: claim files or dirs so parallel agents don't edit the same code. Optional git pre-commit guard.
- 🔌 Every interface: CLI, MCP (stdio + HTTP), hooks, instant
watch, HTTP/SSE, an A2A v1.0 facade, a web dashboard and Python, set up by one puenteo install.

Codex asks Claude about a schema change and gets the answer two seconds later. Claude claims src/db, Cursor reports its frontend fix and Gemini checks a number for the release notes. All of it runs locally: one SQLite file, no daemon, no network.
Puenteo comes from Spanish puente (bridge).
No runtime dependencies · Python ≥ 3.9 · macOS · Linux · Windows · optional Rust core

Install
uv tool install puenteo
uv tool install 'puenteo[fast]'
puenteo install
puenteo install --hooks
puenteo install --dry-run
install is idempotent. It edits only its own puenteo entry in each config, backs up every file it touches (*.puenteo-bak), and puenteo uninstall reverts it.
Claude Code plugin (skills + MCP + hooks + /peers, /ask, /handoff):
claude plugin marketplace add mano7onam/puenteo
claude plugin install puenteo@puenteo
Talk to running sessions
$ puenteo ps
AGENT SESSION STATUS SEEN MAIL NAME CWD
claude 500a1d65 busy 2m ultimate-agent-4-72 ~/dev/ultimate-agent-4
* claude 87652461 busy 0s puenteo-57 ~/dev/puenteo
codex 01a11123 - 4m Finish performance tests ~/dev/ultimate-agent-4
puenteo whoami
puenteo send codex:01a11123 "Which branch has the perf tests?" --wait 300
puenteo send @reviewer "PR ready: feat/x"
puenteo send cwd:. "Refactoring src/db, keep out for 30 min"
puenteo send '#release' "v0.7 tagged"
puenteo send agent:codex "…" | puenteo send '*' "…"
puenteo inbox
puenteo reply <msg-id> "answer"
puenteo wait -t 120
puenteo watch
puenteo log -f
puenteo claim src/db --note "migration 0042"
puenteo claims --check src/db/schema.sql
Addresses: agent:session-id (a unique prefix works) · @name · #channel · agent:<vendor> · cwd:<path> · *
How messages reach a session:
| Agent | Woken while idle | While working |
|---|
| Codex | yes, pushed via codex queue | hooks / MCP inbox |
| Claude Code | yes, when the session runs puenteo watch under its Monitor tool | hooks (install --hooks) / MCP inbox |
| Gemini, Cursor, OpenCode, Copilot, Qwen, … | no; the message waits in the inbox | MCP inbox / wait |
All messages live in one local SQLite file (puenteo state dir) and nothing leaves the machine. Bodies are wrapped as untrusted peer data: agents are told that peer messages never count as user instructions or approval. A hop limit, a rate limit and a size cap keep agents from looping.
Across machines: the mesh 🌐
Sessions on different computers find each other and talk peer to peer: one to one, or many to many in rooms. There are no servers to run:
puenteo mesh up
puenteo mesh peers
puenteo send claude:8765@laptop "…"
puenteo offer "I know the payments service, can run its tests" -t payments
puenteo find "who can run payments tests"
puenteo ask <offer-id> "are tests green on main?" --wait 300
puenteo room join war-room [--secret …] && puenteo send '#war-room@*' "…"
puenteo mesh relay --port 7777
- Transports: zero-config LAN (UDP multicast + direct HTTP), public Nostr relays that get through NAT, a self-hosted relay, or a direct VPN/Tailscale peer.
- Security: every message is a signed event (BIP-340 Schnorr). Direct messages are end-to-end encrypted (NIP-44 v2) and private rooms use a shared secret. The default is closed: a remote message gets in only if it replies to your own thread, is addressed to a session that published an offer, comes from a node you trusted, or arrives in a room you joined. Rate limits and a hop limit apply across machines.
- Pure stdlib: the crypto passes the official BIP-340 and NIP-44 test vectors, and real public relays accept its events.
- Remote messages enter the local bus, so hooks,
codex queue, Monitor, MCP and the dashboard all work with them unchanged. See docs/MESH.md.
| Interface | Use it for | Command / endpoint |
|---|
| CLI | any agent with a shell, scripts | puenteo send/inbox/ps/search … (--json everywhere) |
| MCP (stdio) | Claude Code, Codex, Gemini, Cursor, OpenCode, Copilot, Qwen | puenteo mcp (installed by puenteo install) |
| Hooks | messages show up in context with no tool call | puenteo install --hooks (Claude Code, Codex) |
| Monitor / stream | wake an idle Claude session the moment mail arrives | puenteo watch (instant; Unix-socket doorbell) |
| Exec trigger | glue for anything: notify-send, Slack, scripts | puenteo watch --exec 'cmd' (message JSON on stdin) |
| HTTP REST + SSE | dashboards, editors, other languages | puenteo serve → /api/*, /api/events |
| MCP over HTTP | MCP clients that prefer HTTP | POST /mcp on puenteo serve |
| A2A v1.0 | standard agent-to-agent clients | /.well-known/agent-card.json, POST /a2a |
| Web dashboard | watching and talking to all sessions in a browser | puenteo serve --open |
| Python | your own orchestrators | puenteo.send(), for m in puenteo.listen(): …, puenteo.Bus |
| Git guard | stop commits that touch a file a peer claimed | puenteo guard install |
puenteo serve binds only to 127.0.0.1 and needs a bearer token, stored in a 0600 file (puenteo serve --print-token). It rejects any non-localhost Host or Origin header, which blocks DNS rebinding, as the MCP spec recommends for local HTTP servers.
Speed
| pure Python | with puenteo[fast] (Rust core) |
|---|
| parse transcripts (25 largest, 3.3 GB) | ~300 MB/s | 0.8–2.7 GB/s, all cores |
| cold index rebuild (807 Codex + Claude sessions, ~4 GB) | 14.8 s | 4.3 s |
| global search after new activity | ~14 s | ~2 s |
warm list (4.5k sessions) / warm search | 0.3 s / 0.25 s | same |
| message delivery (send → woken reader) | 0.8 ms median | same |
The Rust core (native/, PyO3 abi3 wheels) is optional. Without it, puenteo stays pure Python with no dependencies. A test checks that both parsers produce byte-identical output on real logs. Set PUENTEO_NATIVE=0 to force pure Python.
MCP server
puenteo mcp is a stdio MCP server with no dependencies, one process per agent session. It detects which session it serves from the parent-process chain, registers on the bus, and exposes these tools:
- history:
sessions, search, outline, pull, show
- live:
whoami, peers, send, reply, inbox, wait, thread, channels, subscribe, set_name, claim, release, claims
puenteo install registers it for Claude Code (claude mcp add -s user), Codex (codex mcp add), Gemini, Qwen, Cursor, OpenCode, Copilot and Antigravity.
Search and pull history
puenteo search "gatekeeper dmg" --exclude-self
puenteo search "topic" --cwd . --since 2026-09-01
puenteo list --cwd . -n 20
puenteo outline <ref>
puenteo pull <ref> --mode handoff
puenteo pull <ref> --query "topic" --mode query
puenteo pull <ref> --around 500 --radius 5
puenteo show <ref> --range 100:120
puenteo export <ref> -f md|html|pdf|json|zip|csv|xml|yaml|all -o out
puenteo index --stats
<ref> can be a unique id prefix, provider:id, @self, @last, @last:codex, a path, or a title substring. An ambiguous prefix fails with exit code 4 and prints the candidates; puenteo never picks one silently.
Library
import puenteo
for s in puenteo.list_sessions(limit=10, cwd="~/dev/myapp"):
print(s.provider, s.session_id, s.title)
hits = puenteo.search("gatekeeper dmg", exclude_session="my-current-id")
msgs = puenteo.pull(hits[0].session.session_id, query="dmg", mode="query")
puenteo.export_session("019f7a24", fmt="md", output="chat.md")
from puenteo.bus import Bus
with Bus() as bus:
bus.send("claude:8765…", "@reviewer", "PR ready")
for m in bus.inbox("codex:01a1…"):
print(m.sender, m.body)
Providers
| Provider | Store |
|---|
| Claude Code | ~/.claude/projects/**/*.jsonl (meta entries skipped, streamed fragments merged) |
| Codex | ~/.codex/sessions/**/rollout-*.jsonl + state_*.sqlite titles; subagents keep their own ids |
| Gemini CLI | ~/.gemini/tmp/** |
| Antigravity | ~/.gemini/antigravity/brain/*/…/transcript*.jsonl |
| Grok | ~/.grok/sessions/**/chat_history.jsonl |
| Pi | ~/.pi/agent/sessions/**/*.jsonl |
| Qwen Code | ~/.qwen/projects/**/chats/* |
| Cursor | macOS ~/Library/Application Support/Cursor · Linux ~/.config/Cursor · Windows %APPDATA%\Cursor |
| Continue | ~/.continue/sessions/** |
| Aider | .aider.chat.history.md (scan with --cwd or PUENTEO_AIDER_ROOTS) |
| OpenHands | ~/.openhands/openhands.db |
| Goose | ~/.config/goose · Windows %APPDATA%\goose |
Live detection (ps) covers Claude Code (~/.claude/sessions), Codex (thread locks), Grok, Junie, and any agent that runs the puenteo MCP server or hooks.
Where things live
| What | Path (macOS / Linux / Windows) | Override |
|---|
| Search index + metadata cache | ~/Library/Caches/puenteo · ~/.cache/puenteo · %LOCALAPPDATA%\puenteo\Cache | PUENTEO_HOME, PUENTEO_NO_INDEX=1, PUENTEO_NO_CACHE=1 |
| Message bus | ~/Library/Application Support/puenteo/bus.db · ~/.local/state/puenteo · %LOCALAPPDATA%\puenteo\State | PUENTEO_BUS |
| Identity | detected automatically | PUENTEO_SESSION=agent:id, --as |
Extend it
New agent store, MCP tool, delivery channel (Slack, IDE…) or live detector? Write a plugin. It's an ordinary package with entry points, and you don't have to fork anything. See docs/PLUGINS.md and the template in examples/puenteo-example-plugin. Run puenteo plugins to see what's loaded.
Contributions to the core, from individuals, companies and AI agents, go through the same gates: CI on 3 OSes, a zero-dependency check, a security scan, DCO sign-off and code-owner review. See CONTRIBUTING.md and GOVERNANCE.md.
Development
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
.venv/bin/python -m pytest -q
PUENTEO_LIVE_TESTS=1 .venv/bin/python -m pytest -q
See docs/PLAN.md for the roadmap.
License
MIT · mano7onam/puenteo