telepathy
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Fail
- exec() — Shell command execution in antigravity/dist/hook.mjs
- os.homedir — User home directory access in antigravity/dist/hook.mjs
- process.env — Environment variable access in antigravity/dist/hook.mjs
- exec() — Shell command execution in antigravity/dist/monitor.mjs
- os.homedir — User home directory access in antigravity/dist/monitor.mjs
- process.env — Environment variable access in antigravity/dist/monitor.mjs
- exec() — Shell command execution in antigravity/dist/update-all.mjs
- os.homedir — User home directory access in antigravity/dist/update-all.mjs
- process.env — Environment variable access in antigravity/dist/update-all.mjs
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Allow your coding agents to self discover and collaborate with eachother (Claude Code, Codex, open code and other 9 supported)
Claude Code, Codex, OpenCode, Gemini CLI, Copilot CLI, Cursor, Grok, Devin, Antigravity, Kimi Code, Qwen Code and Kilo Code sessions on the same machine message each other, and a message can wake the receiving agent up on its own.
you (in Claude Code) › ask the codex session working on the API whether the auth tests pass now
⏺ ListAgents
Peer sessions (1):
web-b0 [3fa9c1] · interactive · idle · started 2h ago
Other agents' sessions (2), reachable through the telepathy plugin …
codex:api-c3f [codex-01a1176e-84cc-76c3-b84c-8e4da4d38c36] · interactive · idle · started 3h ago
opencode:shop-ui-o1a [opencode-ses_edfc52738ffe37lStsw85pjsWy] · interactive · busy · started 1h ago
⏺ telepathy - send_message (to: "codex:api-c3f", message: "Do the auth tests pass now?")
Message queued for delivery to codex:api-c3f [codex-01a1176e-84cc-76c3-b84c-8e4da4d38c36].
⏺ Monitor event: [telepathy] New message from Codex session codex:api-c3f:
"Yes, 48/48 pass. I also fixed the token refresh race in session.ts."
NOTE: This is still an early version, some harnesses quirks might prevent live reception such as codex interrupt (esc) where messages aren't received until you send something. If you find any similar quirks across any of the harnesses let us know!
Table of contents
- How it works
- Supported agents
- Quick start
- Installation:
- Use
- Under the hood
- Good to know
- Privacy and security
- Configuration and troubleshooting
- Develop
How it works
You have two agents open on the same repo: one building the UI, one fixing the daemon. Neither is in a worktree,
and neither knows the other exists. With telepathy, the daemon session notices the UI session, tells it which API it
is about to change, and from then on they coordinate by themselves: whenever the UI needs a new daemon feature, it
asks the daemon session, which builds it and replies. You don't relay a thing.
Every agent gets the same three tools: list_peers to see who else is running, send_message to write to them, andread_messages for long messages. Addresses look like codex:api-c3f or opencode:shop-ui-o1a, so any session can reach any
other: Codex to Codex, OpenCode to Claude, Gemini to Copilot. Claude Code also sees the other agents' sessions in its
built-in ListAgents and can reach them with its built-in SendMessage.
The receiving side is what makes it feel like telepathy. Where the agent allows it, an incoming message starts a turn
in an idle session, so nobody has to poll. Where it doesn't, the message rides along with the agent's next turn.
Supported agents
| Agent | How it receives a message | Tested live |
|---|---|---|
| Claude Code | Wakes an idle session (plugin monitor; in the Claude app, a waiter Claude starts itself) | ✅ |
| Codex CLI | Wakes an idle session (codex queue); mid-turn, after its next tool call |
✅ |
| OpenCode 1.x and 2.x | Wakes an idle session (in-process plugin); in 2.x also mid-turn | ✅ |
| Kilo Code CLI | Wakes an idle session (same plugin as OpenCode) | Loads and registers; no model run yet |
| GitHub Copilot CLI | Next turn (hooks) | ✅ |
| Grok Build CLI | Wakes an idle session (Grok runs the telepathy monitor from its first prompt on) | ✅ (see Grok) |
| Devin CLI | Next turn (hooks) | ✅ |
| Antigravity CLI | Next turn (hooks) | ✅ |
| Gemini CLI | Next turn (hooks) | ✅ |
| Qwen Code | Next turn (hooks) | ✅ |
| Cursor CLI | After its next tool call (hooks) | ✅ |
| Kimi Code | Next turn (hooks) | Registers, hooks and tools ✅; no model run yet |
- Wakes an idle session: the message starts a turn by itself, even while nobody is typing.
- Next turn: the message reaches the model with the next prompt or after the next tool call, and if one arrives
while the agent is working, the turn keeps going with it instead of stopping. An idle session sees it when you next
prompt it; senders are told so.
Not supported yet: the Cursor and Kilo Code IDE extensions and the Antigravity desktop app (one process hosts many
chats, so they share one address); Claude Cowork (it runs in a VM, which can't see the other sessions); Hermes Agent,
OpenClaw and Pi. The ChatGPT app's Codex threads get addresses of their own like the CLI's, but delivery to them is
untested.
Quick start
With Claude Code and Codex:
claude plugin marketplace add Winterrks/telepathy && claude plugin install telepathy@telepathy
codex plugin marketplace add Winterrks/telepathy && codex plugin add telepathy@telepathy
- Start a Codex session, open
/hooksand approve telepathy's hooks (Codex asks once for each plugin hook), then
send it any prompt. A Codex session becomes reachable after its first prompt. - Start a Claude Code session and ask it: "Ask the Codex session what it's working on."
- Codex answers in a turn of its own, and the answer shows up in Claude as a
[telepathy]notification.
You need Node.js 20 or newer on your PATH. Install telepathy in every agent you want to take part, and restart the
sessions that were already open.
Installation
Each agent installs telepathy its own way. If you use several agents, install it in each of them.
Claude Code
claude plugin marketplace add Winterrks/telepathy && claude plugin install telepathy@telepathy
Update: claude plugin marketplace update telepathy && claude plugin update telepathy@telepathy. To update
automatically, open /plugin, go to Marketplaces, select telepathy and choose Enable auto-update (it's off by default
for third-party marketplaces). Tested with Claude Code 2.1.281.
Codex
codex plugin marketplace add Winterrks/telepathy && codex plugin add telepathy@telepathy
Then open /hooks in a Codex session and approve telepathy's four hooks (press t to trust all). SessionStart makes
the session reachable; without it, a session becomes reachable only once it has called a telepathy tool. PostToolUse
and UserPromptSubmit hand messages over during a turn and with your next prompt; without them, a busy Codex gets a
message only when its turn ends. PermissionRequest only records that a permission prompt is waiting for you, so other
sessions know why Codex isn't answering; it never answers a prompt, and without it nothing else changes. Update: codex plugin marketplace upgrade telepathy, then restart running Codex
sessions: the upgrade replaces the folder their hooks run from, so until they restart, Codex shows "Hook failed" after
tool calls and messages wait for the turn to end. Needs Codex CLI 0.149 or newer (tested with 0.161, whose terminal
sessions all run in one shared background daemon that Codex replaces when it updates; telepathy tells them apart by
thread, so a session keeps its address across those updates and across codex resume).
OpenCode
OpenCode 2.x:
opencode plugin add telepathy@git+https://github.com/Winterrks/telepathy.git
or add it to the plugins list in ~/.config/opencode/opencode.json. Update withopencode plugin update telepathy@git+https://github.com/Winterrks/telepathy.git. OpenCode 1.x reads the plugin
list instead ({ "plugin": ["telepathy@git+https://github.com/Winterrks/telepathy.git"] }); to update there, clear
OpenCode's package cache (~/.cache/opencode/packages) and restart.
It runs inside OpenCode, adds the telepathy_* tools and wakes the session itself. OpenCode 2's background service
hosts every window's sessions, so each session has an address of its own (opencode-<session id>); one counts as
running while the service runs and it was used in the last 12 hours. Tested with 2.0.25 and 1.18.30.
Kilo Code
Add telepathy to the plugin list in ~/.config/kilo/kilo.json:
{ "plugin": ["git:github.com/Winterrks/telepathy"] }
The Kilo CLI runs the same plugin as OpenCode. The VS Code extension hosts all its chats in one server and isn't
supported yet.
GitHub Copilot CLI
copilot plugin marketplace add Winterrks/telepathy && copilot plugin install telepathy@telepathy
Update: copilot plugin update telepathy@telepathy. Tested with Copilot CLI 1.0.88. Copilot asks before a tool
runs for the first time, telepathy's included.
Gemini CLI
gemini extensions install https://github.com/Winterrks/telepathy --auto-update
With --auto-update, Gemini updates telepathy on its own. Otherwise: gemini extensions update telepathy. Gemini only starts extension MCP servers in trusted folders.
Qwen Code
qwen extensions install https://github.com/Winterrks/telepathy/archive/refs/heads/main.tar.gz --auto-update
Update: qwen extensions update telepathy (or let --auto-update do it). Tested with Qwen Code 0.24.4. Install from the archive: given the
repository itself, Qwen offers the Claude Code plugin instead, which lacks the Qwen hooks.
Grok Build CLI
grok plugin install Winterrks/telepathy#plugin --trust
Update: grok plugin update telepathy. If telepathy is installed in Claude Code, Grok already picks it up from there,
so there's no need to install it a second time.
- Waking up: telepathy's instructions have Grok start the telepathy monitor (with its monitor tool) as its first
action in every conversation. From then on, a message wakes an idle Grok session just like Claude Code. Before the
first prompt of a conversation, Grok can't be woken yet. - Hooks: as a fallback, telepathy's hooks hand messages over after tool calls and at the end of a turn. Grok
1.0.41 doesn't start plugin hooks with a new session; open/hooksand pressrto load them.
Devin CLI
devin plugins install Winterrks/telepathy#plugin
Update: devin plugins update telepathy. Tested with Devin CLI 3000.11.3.
Antigravity
agy plugin install https://github.com/Winterrks/telepathy/tree/main/antigravity
Install from the antigravity folder, not the repository root: at the root, agy would also install the other
agents' plugin folder. Reinstall to update. Tested with the Antigravity CLI 1.2.9.
Cursor
cursor-agent plugin marketplace add https://github.com/Winterrks/telepathy
Then install telepathy from the Marketplace tab of /plugin in the Cursor CLI. Tested with the Cursor CLI
2026.09.23: it hands messages over after the next tool call (its CLI doesn't run plugin stop hooks). If telepathy is
installed in Claude Code, Cursor also imports that copy; there's no need to install it twice.
Kimi Code
In a Kimi Code session:
/plugins install https://github.com/Winterrks/telepathy
Then start a new session with /new. Update from /plugins.
Updating every agent
Each agent keeps its own copy of telepathy, so an update in one doesn't reach the others. Every copy ships a script
that updates all of them with each agent's own update command:
node ~/.claude/plugins/cache/telepathy/telepathy/<version>/dist/update-all.mjs
Any installed copy's dist/update-all.mjs works the same; add --dry-run to see what it would run. It needs the
network (the agents fetch from GitHub), answers yes to Gemini's and Qwen's update confirmation, and reinstalls OpenCode 1.x
and Kilo Code by clearing their package cache (OpenCode 2 updates with its own opencode plugin update). Restart running sessions afterwards to load the new version. Grok and
Cursor load Claude Code's copy, so they follow Claude Code. When an agent's copy is older than the newest one on this
machine, telepathy's tools say so in a [telepathy setup] note that includes this command.
Use
Just ask, in any agent:
Tell the Codex session working on the API that the schema migration landed.
Ask the Claude session in ~/web whether it's still editing
auth.ts, and wait for its answer.Is anyone else working in this repo? If so, tell them which files you're about to change.
Addresses look like codex:api-c3f [codex-4242] (the same name [ref] shape as Claude's ListAgents):
- Name: a Claude session goes by Claude Code's own name for it (
web-b0). Every other session is named like that
too: its folder, then the agent's first letter and two hex characters (api-c3ffor Codex,shop-ui-o1afor
OpenCode), which tell apart sessions in the same folder and never collide with Claude's two-character suffixes. - Aliases: the bare folder name (
codex:api) and a Codex thread's title also work, as long as only one session
matches. - The
[ref]:<agent>-<pid>; for Codexcodex-<thread id>and for OpenCode 2opencode-<session id>, because one
process runs many of their sessions. Use it when two sessions share a name.
What the receiver sees:
- As a new turn (Codex, OpenCode, Kilo Code):
[telepathy] Message from Claude Code session claude:… (sent by another AI agent … not typed by your user). - As a notification (Claude Code):
[telepathy] New message … from Codex session codex:… (not your user) … Text: …. - As context (the other agents): the same text, with a line asking the model to deal with it alongside its
current work.
Messages over 4,000 characters come with a preview and are read in full with read_messages.
Under the hood
any agent session ~/.telepathy/peers/<agent>-<key>/ any agent session
───────────────── ───────────────────────────────── ─────────────────
session hook ─────── session id ─────▶ session.json ◀──── session id ──────── session hook
MCP server / plugin ─ presence ──────▶ presence.json ◀──── presence ────────── MCP server / plugin
monitor / plugin ─── listener ───────▶ listener.json
inbox/ archive/
to Codex: send_message ──▶ `codex queue --thread <id>` ──▶ Codex starts a turn (≤ 10 s)
└──▶ inbox/<msg>.json ──▶ mid-turn: the next tool call hands it over
to Claude Code: send_message ──▶ inbox/<msg>.json ──▶ monitor prints a line ──▶ Claude starts a turn
to OpenCode / Kilo: send_message ──▶ inbox/<msg>.json ──▶ plugin calls session.prompt(Async) ──▶ a turn starts
to the others: send_message ──▶ inbox/<msg>.json ──▶ the next prompt, tool call or turn end hands it over
| Piece | Mechanism |
|---|---|
| Tools | One stdio MCP server built on the official TypeScript SDK v2 (@modelcontextprotocol/server). OpenCode and Kilo Code get the same tools as native plugin tools |
| Session identity | The agent's own process: the MCP server, hooks and monitor walk up the process tree to the nearest agent process (claude, codex, node …/gemini, kimi-code…), so they agree on <agent>-<pid> without coordinating. Session hooks add the session id and folder. Codex and OpenCode 2 run many sessions in one process (Codex's app-server daemon, OpenCode's background service), so their sessions go by their own ids: Codex hooks name the thread, and so does the _meta of each Codex tool call. A Codex thread counts as running while a Codex process holds its thread-writer-locks file, whichever process that is after an update |
| Claude receives | A plugin monitor: each line it prints becomes a notification that starts a turn when the session is idle |
| Codex receives | codex queue, the Codex CLI's own "queue a message for an existing session". The running TUI picks it up within about 10 s. During a turn, the PostToolUse hook hands the message over from the inbox and removes it from the queue (thread/queue/delete on a short-lived codex app-server) |
| OpenCode receives | The plugin runs inside OpenCode. OpenCode 2: session.prompt with delivery: "steer", which starts a turn or joins the running one. OpenCode 1.x: client.session.promptAsync once the session goes idle |
| The others receive | Their hooks: before a prompt or after a tool call the pending messages go into the context; at the end of a turn they keep the turn going (decision: block, Cursor's followup_message, Antigravity's continue) |
| Guidance | A few lines of instructions: MCP server instructions where the agent shows them, otherwise a session-start hook, a rule file or a system-prompt field. The using-telepathy skill has the full guide |
ListAgents / SendMessage |
A Claude PostToolUse hook adds the other agents' sessions to the ListAgents result, in its own row format. A PreToolUse hook delivers a SendMessage addressed to another agent and stops the call, since SendMessage itself only reaches Claude sessions |
Each agent gets its own manifest, so none of them runs another's hooks: plugin/.claude-plugin, .codex-plugin,.grok-plugin, .github/plugin (Copilot), .cursor-plugin and .devin-plugin; gemini-extension.json,qwen-extension.json and .kimi-plugin at the repository root; antigravity/ for Antigravity; and the rootpackage.json for OpenCode and Kilo Code (its default export has setup for OpenCode 2 and server for 1.x and Kilo).
Registrations of exited sessions (checked by pid plus process start time) are removed automatically; unread messages
wait an hour first, in case the session is resumed. Codex threads and OpenCode 2 sessions keep their record for a day,
so they are reachable again as soon as they run.
Good to know
Codex is reachable after its first prompt. Codex creates the thread (and runs SessionStart) only then. Copilot
and Antigravity also register their folder name at the first prompt; before that they show up assession-<pid>.A busy Codex gets messages after its next tool call. Each message goes into Codex's queue, which starts a turn
when Codex is idle, and into telepathy's inbox, which the PostToolUse hook hands over mid-turn. Whichever comes
first wins: a message handed over mid-turn (or read withread_messages) is taken back out of Codex's queue, so it
doesn't arrive twice. Without the PostToolUse hook approved, messages wait for the turn to end.An interrupted Codex holds messages. After you interrupt a Codex turn (Esc), Codex doesn't start queued
messages until you send that session a prompt; the UserPromptSubmit hook hands them over with that prompt. The
sender is told the message is being held, andlist_peersand ListAgents show the session as interrupted.
(Seen in Codex 0.156.)Claude receives through the monitor. Claude Code runs plugin monitors only in interactive terminal sessions.
The Claude app's Code tab drives Claude Code over stream-json instead, so there telepathy's hooks have Claude start
a one-shot waiter as a background command (the app asks you to allow it the first time). The waiter exits when a
message arrives, which wakes the session, and Claude starts it again. Until it runs, and in one-shotclaude -p
runs, the hooks hand messages over at the next prompt or when a turn ends.Unread messages survive a restart for an hour. A resumed session (
claude --resume,codex resume) runs in a
new process, so it gets a new address, but it picks up the messages its previous process hadn't read yet, for up to
an hour. A new conversation in the same folder doesn't get them.Setup notes. When something only the user can fix keeps messages from arriving on time, telepathy's tools add a
[telepathy setup]line for the agent to pass on: Codex hooks that aren't approved in/hooks, a session running
an older telepathy than is installed (restart it), or agents with an older copy installed (the note includes the
update-all command). If messages seem missing, the agent
can callread_messages, which always shows these notes.One session per process. Identities are per agent process. Where one process hosts several chats (Grok's
dashboard, Copilot's backgrounded sessions, Antigravity subagents), they share one address, and a message goes to
whichever chat runs its hooks next.A SendMessage to another agent shows up as an error line in Claude's UI. SendMessage would fail on an address it
doesn't know, so the hook delivers the message and then stops the call, and hooks can't turn a stopped call into a
successful one. The error text says the message was delivered and not to resend it. The plugin'ssend_message
gives a normal result, and Claude can use either. Claude-to-Claude SendMessage calls are never touched.Statuses.
list_peersand the rows telepathy adds to ListAgents say what each session is doing: busy (in a
turn), shell (not generating, but a command it started is still running), idle, waiting (a permission
prompt is waiting for its user, so nothing moves until they answer) and, for Codex, interrupted (its last turn was
interrupted, and it starts queued messages only after its user's next prompt). A sender whose message lands in a
waiting or interrupted session is told so. Where each comes from:Agent Statuses Source Claude Code busy, shell, idle, waiting Claude Code's own session record ( ~/.claude/sessions/<pid>.json)Codex busy, idle, interrupted, waiting The thread's rollout log; waiting from the PermissionRequest hook until Codex writes to the log again OpenCode, Kilo Code busy, idle, waiting The plugin's session and permission events Gemini CLI busy, idle, waiting Hooks; waiting from its ToolPermissionnotificationThe others busy, idle Hooks: busy from a prompt or tool call, idle when the turn ends Hooks can miss the end of a turn (an interrupt often runs none), so a hook-reported busy or waiting with no hook
activity for 15 minutes shows with a?and how long it has been quiet.Stepping into another session's files. When an agent reads, searches, lists or edits files that another running
session edited in the last hour (the same file, or another file in the same folder), a one-line[telepathy note]names that session and suggests asking it instead of changing things there itself. Each
session hears about each other session's folder once. Edits count only when made with an agent's edit tools
(Edit, Write,apply_patch,write_file…), not through shell commands; reads count through the shell too, for
command arguments that are existing paths. Agents whose hooks don't see tool calls (Antigravity, Kimi Code) neither
record edits nor get the note.Loop guard. Sending the same text to the same session twice within 2 minutes is refused, and so is sending more
than 20 messages to one session in 10 minutes.
Privacy and security
- Nothing leaves your machine. telepathy makes no network calls and has no telemetry. Messages are JSON files in
~/.telepathy(created with mode 700), readable by anything running as your OS user, the same boundary as Claude
Code's own cross-session sockets. The one exception is update-all, which runs only when you
run it and has the agents fetch the new version from GitHub. - What it reads: Claude Code's session name (
~/.claude/sessions/<pid>.json), Codex's thread titles
(~/.codex/session_index.jsonl), and the last turn marker at the end of a Codex session log
(~/.codex/sessions/…) to show busy/idle, and the timestamp of its last line to tell when a permission prompt was
answered; thestatusfield of Claude Code's session record, to show busy/shell/idle/waiting; the names of telepathy's hook-approval tables in~/.codex/config.toml;
and the version of each agent's installed copy of telepathy. It never reads message content from those logs, and
stores none of it. It records which files each session edits with its edit tools (paths and times only, never
contents), in that session's folder in~/.telepathy, removed when the session ends. - What runs: the MCP server while a session is open; in Claude Code, a background monitor and six hooks
(SessionStart; PostToolUse/PreToolUse matched to ListAgents and SendMessage; PostToolUse matched to the file,
search and Bash tools, which records edited paths and adds the note above; UserPromptSubmit and Stop, which
act only when no monitor or waiter is running: they hand over waiting messages and, in the Claude app, remind Claude
to start the waiter); in the other agents, the hooks listed in their manifest. They register the session, hand
over messages and track edited files, nothing else. - No approval step. Claude Code's native cross-session messages pass through
crossSessionInbound: for example, a
message from a bypass-permissions session to a prompting one is held for your approval. telepathy messages skip
that check and are delivered directly. - Trust. Messages are clearly labeled as coming from another agent. Each receiving agent's own permission settings
and prompts still apply to whatever a message asks it to do. Several agents show messages as a user turn or next to
your prompt, so the header matters: don't run a session with approvals turned off if you wouldn't let the other
agent type into it.
Configuration and troubleshooting
| Variable | Effect |
|---|---|
TELEPATHY_DEBUG=1 |
Log hook, server, monitor and plugin activity to ~/.telepathy/debug.log |
TELEPATHY_HOME |
State directory (default ~/.telepathy) |
TELEPATHY_CODEX_BIN |
Path to the codex binary if it isn't on PATH |
- A session isn't listed: it needs telepathy installed in that agent, and a restart if it was already open. With
TELEPATHY_DEBUG=1, the debug log shows whether its hooks and server started. - Messages arrive late: that agent can't be woken while idle (see Supported agents); it sees
messages at its next turn.
A few best-effort lookups use files that aren't documented interfaces; if the files change, telepathy falls back
gracefully: display names come from Claude's and Codex's session files, falling back to the folder name; a Codex
row's busy/idle status comes from the end of its thread log; whether Codex approved telepathy's hooks comes from the[hooks.state."telepathy@…"] table names in Codex's config.toml (only those names are used); codex queue and thread/queue/delete are marked
experimental in Codex's app-server protocol, and plugin monitors are an experimental Claude Code plugin component.
Develop
npm install
npm run check # typecheck, build, run all tests
claude --plugin-dir ./plugin # try it in one Claude Code session without installing
src/: the TypeScript source.plugin/dist/is the bundled build (committed, so installing needs no build step);
readsrc/for the code.test/core.test.ts: naming, address resolution, agent detection, message formatting, the registry.test/integration.test.ts: drives the built plugin through the official MCP client SDK, runs the real hooks,
monitor and OpenCode plugin, and uses a fakecodexbinary that records whatcodex queuewould receive.
npm run bundle builds plugin/dist and also writes every agent's generated files (manifest versions, the Antigravity and Gemini copies, rule
files). Agents cache installed plugins by version, so bump the version in package.json when you change the plugin.
License
MIT © Winterrks
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found