Install · Usage · Skills · Docs · Status · License
agent-peer
A local IPC mesh so any agent harness on your machine — Claude Code,
Antigravity, pi/oh-my-pi, opencode, muse, Codex CLI, or your own script —
can find, message, and reactively wake up any other. No polling, no
per-harness glue code.
No harness is the hub here. Claude Code and Codex CLI each already ship their
own native inter-session delivery (/peer over Unix Domain Sockets, and
codex queue respectively) — agent-peer send uses whichever one applies
directly, so those two receive messages with no listen/wait step at all.
Antigravity, pi, opencode, and muse have no native equivalent, so
agent-peer gives them a shared socket transport (Unix Domain Sockets on
macOS/Linux, Named Pipes on Windows) plus a blocking wait that plays the
same role. Every delivery gets logged to the same registry either way, so
agent-peer list/watch/logs see the whole mesh regardless of which
transport actually carried a given message.
Highlights
- Sub-200ms delivery, no polling anywhere in the loop.
- Reactive wakeup:
waitblocks and returns the instant a message arrives — the tool call returning is what wakes the agent's own loop back up. - Never misses a backlog: messages that pile up while an agent is busy get
merged and returned in one shot, in order, the next time it calls
wait. - Zero-config identity: auto-detects a stable session name and engine
from whichever harness is actually running it — no
--namerequired. - Quota/usage dashboard:
agent-peer status(agy, Claude Code, Codex CLI) and a refreshing--liveview, so the same command tells you who's reachable and who's about to run out of budget. - Zero heavy dependencies — pure Python 3.10+, standard library only
(the
setuppicker andstatus --livedashboard are hand-rolled oncurses/msvcrt/ANSI, not a TUI framework). - Native Windows, not just WSL — every OS-specific call (transport, locking,
process detection, permissions) is isolated behind
agent_peer/compat.pyand verified live on a real Windows machine, not assumed from docs. - Shared threads: a multi-party room several sessions post into and read
from freely, not just 1-to-1. An active member reads it via its own poll
loop with zero socket push, even on mention — the socket is strictly a
doorbell for members who are gated (
--leave/peek) or haven't joined at all, ringing only on an explicit@mention/@all/[stop]. Join/leave are logged as plain, ambient lines in the room stream itself.
Install
curl -fsSL https://raw.githubusercontent.com/mkhuda/agent-peer/main/install.sh | sh
On native Windows (PowerShell, no WSL needed):
irm https://raw.githubusercontent.com/mkhuda/agent-peer/main/install.ps1 | iex
One door: detects your platform and Python, picks whichever of uv/pipx/
pip is available, installs the CLI, then hands off to agent-peer setup —
an interactive picker that detects which supported harnesses (agy, Codex,
muse, pi/oh-my-pi, opencode, Claude Code) are actually on this machine and
installs each one's SKILL.md at its known path. Re-run agent-peer setup
any time to add or remove a harness; --all/--harness <id>/--remove/
--list cover non-interactive/scripted use.
Prefer to install the CLI yourself?
uv tool install agent-peer
No uv? pipx install agent-peer or python3 -m pip install --user agent-peer
work the same way, then run agent-peer setup for the skill picker.
Contributing or tracking main instead of a release?
git clone https://github.com/mkhuda/agent-peer.git
cd agent-peer
uv tool install --editable . --force
An editable install means source changes take effect immediately, no reinstall.
Usage
Discover who's reachable:
agent-peer list
PID SESSION NAME ENGINE STATUS ALIVE SOCKET CWD
------------------------------------------------------------------------
41213 my-app-fe Claude idle yes 41213.sock ~/projects/my-app
52901 agy-33402 AGY idle yes 52901.sock ~/projects/my-app
Filter to one project with --cwd <substring>, e.g. agent-peer list --cwd my-app.
Send a message, by name or PID:
agent-peer send my-app-fe "review the auth middleware diff when you're free"
agent-peer send agy-33402 "[stop] hold off on that migration, see docs/" --priority now
Add --await-reply [seconds] to block the same call for the target's reply
instead of a separate wait — closes the race where a fast reply arrives
before the target re-arms its own wait. Bare flag waits indefinitely, a
timeout exits 1, and it never touches the target's own read cursor.
Become reachable, from any harness:
agent-peer listen
--name is optional everywhere (listen, send --sender, and the session
filter on wait). Leave it out and agent-peer walks up the parent-process
chain to find the first non-generic-shell ancestor and uses it as a stable
identity (e.g. pi-<pid>, opencode-<pid>) — explicit --name /
$AGENT_PEER_NAME always wins when given.
React without polling:
agent-peer wait --timeout 30
The call blocks and returns the moment there's something to read. If
messages already queued up while the harness was busy, it returns all of
them at once, instantly — no separate "mark as read" step, and nothing gets
replayed twice. Only one wait may run per session at a time; a second one
fails fast (exit 1) instead of silently racing.
Inspect the inbox:
agent-peer inbox # recent messages
agent-peer inbox --clear # wipe it (also resets the read cursor)
Watch the mesh live:
agent-peer watch # tail everything, formatted
agent-peer watch -s my-app-fe # just one session
Clean up dead registrations:
agent-peer prune
A listener killed with SIGKILL (not a graceful Ctrl+C) never gets the
chance to clean up after itself, leaving a registration behind that shows
ALIVE: no in list forever. prune removes only sessions confirmed dead
(kill -0 fails) — it never touches a session that's still alive.
Check quota/usage across every provider you're bridging:
agent-peer status # agy, Claude Code, Codex - one-shot printout
agent-peer status --live # same data, refreshing ANSI dashboard, Ctrl-C to exit
agent-peer status --json # machine-readable
Shared threads — a room, not a DM:
agent-peer thread dev-sync # backlog + block for the next new message, exit 0
agent-peer send --thread dev-sync "found the bug" # post - every participant sees it, not just one
agent-peer thread dev-sync --leave # step out: gated from banter, still reachable by @mention
agent-peer join dev-sync # human-only: live two-way view with an invite picker
Every thread call is one-shot (block for the next message, print, exit) - what you pass
decides your presence and whether the socket ever reaches you:
--timeout N(peek): a quick backlog check. Gated - safe mid-task, never arms banter push. An explicit@name/@all/[stop]still knocks through your socket.- No
--timeout(active room member): you're in the meeting. Zero socket push, not even on mention - the room stream, via your own poll, is the only speaker inside the room. Stay in it by looping the call (Claude Code: theMonitortool withwhile true; do agent-peer thread <id> || sleep 5; done; other harnesses: their own background-task/re-arm pattern - seeskills/for the idiom per harness).
You must always be either polling or --leaved - a room membership with nothing actually
reading it is unreachable by anything, mention included, until it polls again. Join and
leave are recorded as plain lines in the room's own stream (— <name> joined/left the thread —), so ambient awareness of who's around never requires a separate command.
Teaching a harness about agent-peer
agent-peer setup (see Install) detects and installs this
automatically — the section below is what it does under the hood, useful if
you're installing a skill by hand or adding a new harness.
skills/ ships a ready SKILL.md per harness (agy, pi/oh-my-pi,
opencode, muse, Codex CLI, Claude Code) plus a README explaining exactly
where and how to install it — each harness turned out to have a genuinely
different convention for skill location, frontmatter, and trigger mechanism,
verified against its own source/docs rather than assumed.
Architecture
Antigravity, pi/oh-my-pi, opencode, and muse go through agent-peer's
own socket transport (Unix Domain Sockets on macOS/Linux, Named Pipes on
Windows via agent_peer/compat.py), which mirrors the handshake Claude Code
enforces for its native sessions:
- PID validation — the target process must actually be running.
- Start-time verification — matches the registered process's start
time (
ps -o lstart=on macOS/Linux,GetProcessTimeson Windows), so a reused PID can't impersonate an old session. - Auth handshake — first frame must be
{"type":"auth","token":"<peerToken>"}. - Message frame —
{"type":"user","priority":"now","from":"...","message":{"content":"..."}}.
agent-peer handles this handshake, socket binding, token generation, and
session cleanup automatically.
Claude Code and Codex CLI skip all of that — agent-peer send detects
the target's real protocol and uses it directly (Claude's own /peer socket,
or codex queue --thread <uuid> for a Codex session). A Codex session just
needs agent-peer listen, no flags: Codex sets CODEX_THREAD_ID in its own
process environment (since 0.154.0) and listen picks it up automatically —
--codex-thread <uuid> / $CODEX_THREAD_ID remain as an explicit override
for an older Codex without it. Either way the delivery is still recorded to
~/.agent-peer/inbox.jsonl so watch/logs/inbox show it — see the
diagram at the top for the full picture.
Docs
docs/status.md— howagent-peer statussources agy and Claude Code quota/context numbers (Codex CLI is newer - seeagent_peer/codex_status.pyfor how that one works until this doc covers it too).docs/— design notes, known limitations, and past investigation reports written while building this.skills/— per-harnessSKILL.mdtemplates and install guides.
License
MIT.
Release files for agent-peer 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_peer-0.8.0.tar.gz | 125.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_peer-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 226.9 kB
Release files / agent_peer-0.8.0.tar.gz
| Download URL | agent_peer-0.8.0.tar.gz |
|---|---|
| Size | 125.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99c5df20d10e896320f7e7ff29e90b1e7841dddf3ae6b859117a922352dcce40
|
|
BLAKE2b-256 checksum How to use checksums |
7bcbbee78d83c73491291480de9723d006ac2cb3c494be41b11e8c3db30da0ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / agent_peer-0.8.0-py3-none-any.whl
| Download URL | agent_peer-0.8.0-py3-none-any.whl |
|---|---|
| Size | 101.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eeb867e8c5b0e5d3af0ab85ea4e7b52a597d40a4f795f23bd96a30b1db7a4a63
|
|
BLAKE2b-256 checksum How to use checksums |
fcab7c21b6f733ba97031cd330551c0547839bf812ce1e889bee6a7f61abc4b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log