Skip to main content

interlink/
lib.rs

1//! Agent-to-agent messaging for Claude Code and Codex CLI.
2//!
3//! Claude Code and Codex CLI agents each run an MCP server: outbound is the
4//! `send_message` tool. Claude inbound is delivered by default to a local inbox that a
5//! background `interlink-mcp wait` listener drains (plain `claude`, no flags), with
6//! native `notifications/claude/channel` push as an opt-in enhancement (`interlinked`
7//! / `INTERLINK_CHANNELS=1`). A small **bus** routes messages between agents and
8//! buffers for agents that are offline.
9//! Codex CLI uses the same protocol and trust gate, with local lifecycle hooks
10//! binding the MCP instance to a thread and [`codex`] delivering through its queue.
11//!
12//! ## Trust
13//!
14//! An agent's identity is its **Ed25519 public key** ([`identity`]); names are
15//! local petnames. Every message is signed, and the channel server verifies the
16//! signature and checks the sender against an allowlist *before* pushing —
17//! so an unverified message never reaches the model.
18//!
19//! Authority comes from the server's `instructions` string, which lands in
20//! the host's MCP context. The peer's text is untrusted data that parameterises
21//! an action; it never authorises one. An ungated channel is a prompt-injection
22//! vector.
23//!
24//! ## Pieces (each behind a feature)
25//!
26//! - [`identity`] — keys, signing, verification, the peer allowlist.
27//! - [`bus`] — the broker: per-recipient queues with `POST /send`, `GET /recv`.
28
29#[cfg(feature = "agent")]
30pub mod agent;
31
32#[cfg(feature = "bus")]
33pub mod bus;
34
35#[cfg(feature = "agent")]
36pub mod codex;
37
38#[cfg(feature = "agent")]
39pub mod delivery;
40
41#[cfg(feature = "identity")]
42pub mod identity;
43
44#[cfg(feature = "agent")]
45pub mod policy;
46
47#[cfg(feature = "agent")]
48pub mod policy_store;
49
50#[cfg(feature = "agent")]
51pub mod pairing;
52
53#[cfg(feature = "agent")]
54pub mod inbox;
55
56#[cfg(feature = "agent")]
57pub mod state;
58
59pub mod route;
60
61#[cfg(feature = "persist")]
62pub mod store;
63
64/// Unix milliseconds.
65pub fn now_ms() -> u64 {
66    std::time::SystemTime::now()
67        .duration_since(std::time::UNIX_EPOCH)
68        .unwrap_or_default()
69        .as_millis() as u64
70}