Skip to content
 
 

Latest commit

 

History

18 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

agent-channel

Let two or more AI coding agents — Claude Code, Codex, or OpenCode — talk to each other across separate sessions over a shared, file-based named channel.

No server, no daemon, no API keys. Agents append JSON lines to /tmp/claude-channels/<channel>.ndjson and each keeps its own durable cursor. On macOS/BSD the receive path blocks on kqueue filesystem events, so an agent can wait for a peer message with zero CPU and zero model inference until something actually arrives — then wake exactly once.

agent A  ──send──▶  /tmp/claude-channels/demo.ndjson  ◀──wait/listen──  agent B
   ▲                                                                       │
   └──────────────────────────── replies ─────────────────────────────────┘

What's in the box

A single Python helper (scripts/channel.py, identical across all three) plus a harness-specific SKILL.md that teaches the agent how to drive it:

Harness Skill source
Claude Code plugins/channel/skills/channel (also installable as a plugin)
Codex codex/channel
OpenCode opencode/channel

Two agents on different harnesses interoperate as long as they share the same /tmp/claude-channels/<channel>.ndjson path.

Install

Claude Code (plugin — recommended)

/plugin marketplace add fl4p/agent-channel
/plugin install channel@agent-channel

Then just ask: "go on channel demo as alice and watch it".

Claude Code (plain skill, no plugin)

git clone https://github.com/fl4p/agent-channel ~/agent-channel
ln -s ~/agent-channel/plugins/channel/skills/channel ~/.claude/skills/channel

Codex

git clone https://github.com/fl4p/agent-channel ~/agent-channel   # if not already
ln -s ~/agent-channel/codex/channel ~/.codex/skills/channel

OpenCode

git clone https://github.com/fl4p/agent-channel ~/agent-channel   # if not already
ln -s ~/agent-channel/opencode/channel ~/.config/opencode/skills/channel

Pi

Reuses the OpenCode skill.

git clone https://github.com/fl4p/agent-channel ~/agent-channel   # if not already
ln -s ~/agent-channel/opencode/channel ~/.pi/agent/skills/channel

Optional, install the fl4p/pi-bash-background extension for non-blocking background listening:

git clone https://github.com/fl4p/pi-bash-background ~/pi-bash-background
ln -s ~/pi-bash-background/src/index.ts ~/.pi/agent/extensions/bash-background.ts

Usage

Ask the agent in natural language — it invokes the skill itself:

  • "open channel demo as alice and tell me when the other agent says something"
  • "send 'build is green' on channel demo"
  • "watch channel demo in the background"
  • "leave the channel"

You never run channel.py by hand; the skill drives it for the agent.

Receive primitives

  • stream (preferred for Codex wake_on_output, Claude Code Monitor, and OpenCode monitor). Launched under a host that wakes on background command output. It keeps running, blocks on real filesystem events, and prints one flushed line for each peer message. Codex support is the local exec_command.wake_on_output fork for openai/codex#22003.
  • wait (preferred for background-exit hosts, 0-token). Launched as a background command in harnesses that re-invoke the agent on background-command exit (Claude Code). It blocks on real filesystem events until a peer message lands, prints it, exits — waking the agent exactly once with zero idle CPU: kqueue on macOS/BSD, inotify on Linux (glibc and musl/Alpine). Windows, and any host where neither watcher can be set up, fall back to a short bounded sleep poll — same behavior, just a little idle CPU instead of true event blocking.
  • listen --timeout 30 (portable). Foreground bounded listen for harnesses without background output/exit wake-up. Re-run while actively waiting.
  • watch-start (legacy). A detached watcher that only logs and posts desktop notifications; it never wakes the agent on its own.

Two-party assumption. wait and stream treat any left the channel message as terminal and stop watching. This is correct for the usual two-agent channel; on a channel with three or more participants, the first departure ends the watch even if other peers are still active. Re-arm if you need to keep following a multi-party channel after a peer leaves.

Harness support. Stock Codex still needs foreground listen; the local Codex fork adds output wake-up via exec_command.wake_on_output, so it should use stream, not background wait. Claude Code supports background-exit wait. Upstream OpenCode needs monitor/background tooling; the local fork and PR anomalyco/opencode#33806 add that path. Messaging itself works everywhere regardless.

Protocol

Shared transcript — append-only NDJSON, one JSON object per line:

/tmp/claude-channels/<channel>.ndjson
{"from":"alice","ts":1234567890,"text":"hello"}

Each agent tracks its position in a sibling cursor file (/tmp/claude-channels/<channel>.<agent>.cursor) so nothing is seen twice and agents never re-read their own messages.

Platform support

Pure Python 3 standard library, no third-party deps.

OS Messaging (send/listen/wait/leave) Wake mechanism watch-* daemon Desktop notifications
macOS ✅ kqueue events (0 CPU) ✅ ✅ (osascript)
Linux (glibc) ✅ inotify events (0 CPU) ✅ — (no-op)
Linux (musl/Alpine) ✅ inotify events (0 CPU) ✅ — (no-op)
Windows ✅ bounded sleep poll ✅ — (no-op)

wait/listen block on native filesystem events with zero idle CPU on macOS (kqueue) and Linux (inotify). Anywhere a watcher can't be set up — Windows, or an exotic host — they degrade to a short bounded sleep poll: identical behavior, just a little idle CPU.

Notes:

  • The channel directory is /tmp/claude-channels on macOS/Linux and %TEMP%\claude-channels on Windows. Set the CHANNEL_DIR environment variable to override it — required only if two agents would otherwise compute different paths (e.g. a macOS and a Windows agent on the same host).
  • Desktop notifications (--desktop) are macOS-only; elsewhere they silently no-op and the channel still works.
  • An earlier MCP-broker implementation of this idea is deprecated in favor of the file-based approach here — no extra process, no polling, instant wake.

Tested on: macOS (kqueue), Linux glibc (python:3-slim) and musl (python:3-alpine) — both confirmed holding an inotify fd at zero idle CPU and waking on a peer send — and Windows Python (via Wine: %TEMP% path, ctypes pid_alive, and the detached watch-* daemon all verified).

License

MIT — see LICENSE.

About

File-based named channels for talking between AI coding agents (Claude Code, Codex, OpenCode) across sessions — zero-server, kqueue-backed wake-up.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages