{"id":51293058,"url":"https://github.com/vbcherepanov/a2abridge","last_synced_at":"2026-06-30T12:03:03.170Z","repository":{"id":356743100,"uuid":"1233781209","full_name":"vbcherepanov/a2abridge","owner":"vbcherepanov","description":"One open A2A 1.0 mesh for Claude Code, Codex, Cursor, Cline, Continue and Gemini.","archived":false,"fork":false,"pushed_at":"2026-05-19T08:07:53.000Z","size":168,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T10:54:47.029Z","etag":null,"topics":["a2a","ai-agents","claude-code","cline","codex-cli","cursor","linux-foundation","mcp","multi-agent","protocol-bridge"],"latest_commit_sha":null,"homepage":"https://a2a-protocol.org/latest/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vbcherepanov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["vbcherepanov"],"custom":["https://PayPal.Me/vbcherepanov"]}},"created_at":"2026-05-09T10:55:39.000Z","updated_at":"2026-05-19T08:07:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vbcherepanov/a2abridge","commit_stats":null,"previous_names":["vbcherepanov/a2abridge"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/vbcherepanov/a2abridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbcherepanov%2Fa2abridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbcherepanov%2Fa2abridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbcherepanov%2Fa2abridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbcherepanov%2Fa2abridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbcherepanov","download_url":"https://codeload.github.com/vbcherepanov/a2abridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbcherepanov%2Fa2abridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34965643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a2a","ai-agents","claude-code","cline","codex-cli","cursor","linux-foundation","mcp","multi-agent","protocol-bridge"],"created_at":"2026-06-30T12:03:02.171Z","updated_at":"2026-06-30T12:03:03.136Z","avatar_url":"https://github.com/vbcherepanov.png","language":"Go","funding_links":["https://github.com/sponsors/vbcherepanov","https://PayPal.Me/vbcherepanov"],"categories":[],"sub_categories":[],"readme":"# a2abridge\n\n## Stop copy-pasting between your AI coding agents.\n\nClaude in your IDE, Codex in a terminal, Cursor in another window —\nall isolated by default. **a2abridge** wires them into a single\n[A2A 1.0](https://a2a-protocol.org/latest/) mesh: peers find each\nother, share an inbox, send each other tasks, and survive across\nmachines with mTLS. No vendor lock-in — runs on the open Linux\nFoundation standard.\n\n[![Build](https://github.com/vbcherepanov/a2abridge/actions/workflows/build.yml/badge.svg)](https://github.com/vbcherepanov/a2abridge/actions/workflows/build.yml)\n[![Release](https://img.shields.io/github/v/release/vbcherepanov/a2abridge?display_name=tag\u0026sort=semver)](https://github.com/vbcherepanov/a2abridge/releases)\n[![Go Reference](https://pkg.go.dev/badge/github.com/vbcherepanov/a2abridge.svg)](https://pkg.go.dev/github.com/vbcherepanov/a2abridge)\n[![Go Report Card](https://goreportcard.com/badge/github.com/vbcherepanov/a2abridge)](https://goreportcard.com/report/github.com/vbcherepanov/a2abridge)\n[![A2A Protocol 1.0](https://img.shields.io/badge/A2A%20Protocol-1.0-1f6feb)](https://a2a-protocol.org/latest/specification/)\n[![Linux Foundation](https://img.shields.io/badge/Linux%20Foundation-LF%20AI%20%26%20Data-0f1f3d)](https://lfaidata.foundation/)\n[![Go 1.25](https://img.shields.io/badge/Go-1.25-00ADD8?logo=go)](https://go.dev/)\n[![macOS · Linux · Windows · WSL2](https://img.shields.io/badge/OS-macOS%20%7C%20Linux%20%7C%20Windows%20%7C%20WSL2-success)]()\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Sponsor](https://img.shields.io/badge/Sponsor-%F0%9F%92%9B-pink)](https://github.com/sponsors/vbcherepanov)\n\n---\n\n## The pain it solves\n\nYou have several AI coding agents on the same machine: Claude in the IDE, Claude in a terminal, Codex CLI, Cursor, maybe Cline or Gemini CLI. They are **isolated by default**. There is no built-in way for \"Codex finished refactoring the API\" to reach the Claude session that owns the frontend, except you copy-pasting between windows.\n\nExisting solutions are either:\n\n- **vendor-locked** — Anthropic Agent Teams talks Claude↔Claude only;\n- **closed protocols** — CCB, claude-multi-agent-bridge, ruflo: each invents its own wire format, you cannot bring a third-party A2A agent in;\n- **enterprise-only** — ruflo's federation is great but designed for 100+ agent swarms with central queens.\n\n`a2abridge` takes a different angle: **wrap each agent into a standard [A2A 1.0](https://a2a-protocol.org/latest/specification/) peer**. Discovery is local; transport is plain JSON-RPC 2.0 + SSE; the wire is the open Linux Foundation spec. Any A2A-compliant agent (yours, third-party, future Google ADK, LangGraph, CrewAI, etc.) can join the same mesh on the same laptop.\n\n## Why A2A and not a custom protocol\n\nIn August 2025 [IBM's ACP merged into Google's A2A](https://lfaidata.foundation/communityblog/2025/08/29/acp-joins-forces-with-a2a-under-the-linux-foundations-lf-ai-data/) under the Linux Foundation. By April 2026 there are 150+ supporting organizations and v1.2 is the current stable release; native A2A is in Google ADK, LangGraph, CrewAI, LlamaIndex Agents, Semantic Kernel, AutoGen. A2A won the protocol war. Your bridge should speak the protocol the rest of the industry speaks.\n\n## Comparison\n\n|                       | a2abridge | [Anthropic Agent Teams](https://code.claude.com/docs/en/agent-teams) | [CCB](https://github.com/bfly123/claude_codex_bridge) | [claude-multi-agent-bridge](https://github.com/yakub268/claude-multi-agent-bridge) | [ruflo](https://github.com/ruvnet/ruflo) |\n|---|---|---|---|---|---|\n| **Open protocol** | A2A 1.0 (LF) | Closed | Closed | Closed | Closed |\n| **Cross-vendor agents** | Any A2A peer | Claude only | Claude/Codex/Gemini/Droid | Claude only | Claude (via plugins) |\n| **Transport** | JSON-RPC 2.0 + SSE over HTTP | Internal mailbox | Unix sockets + tmux | Flask HTTP + SSE + SQLite | WebSocket + mTLS |\n| **Discovery** | Local directory + Agent Card | Built-in lead/teammate | Project `.ccb/` registry | Single Flask server | Federation registry |\n| **Cross-machine** | Yes (mTLS+ed25519, opt-in) | No | No | No | Yes (zero-trust) |\n| **Push notifications** | Yes (A2A 1.0 §9.5 webhooks) | Idle hooks | Polling | SSE | WebSocket |\n| **Install footprint** | Single Go binary, `~10 MB` | Built into Claude Code | Python 3.10+ + tmux | Python + Flask + Chrome ext | npm/Node + 32 plugins |\n| **Cross-platform install** | macOS / Linux / Windows / WSL2 (one cmd) | macOS-leaning (tmux) | install.sh + install.ps1 | Python | npm |\n| **Lifecycle** | Per-agent bridge dies with MCP stdio session — no orphans | Lead-managed | Daemon `ccbd` per project | Single shared server | Distributed |\n| **MCP stdio for IDE** | Yes (any MCP client) | N/A (native) | Yes (delegation registry) | Yes (Claude Desktop) | Yes |\n| **Production state** | v3.x | Experimental flag | v6.x | v1.x | v0.5+ |\n\n`a2abridge` is **not** trying to be ruflo (we are not building a 100-agent federated swarm) and **not** Agent Teams (we are not a built-in Claude feature). The niche is exactly: \"cross-vendor, open-protocol, single-laptop mesh that any new A2A agent can drop into.\"\n\n## What you get\n\n1. **Each running agent is an A2A peer.** Agent Card on `/.well-known/agent-card.json`, full JSON-RPC 2.0 binding (`message/send`, `message/stream`, `tasks/get`, `tasks/list`, `tasks/cancel`, `tasks/resubscribe`, `tasks/pushNotificationConfig/*`, `agent/getAuthenticatedExtendedCard`), TaskState/Message/Part/Artifact, error codes per spec §8, header `A2A-Version: 1.0`.\n2. **Local directory** for zero-config discovery on your machine. Run as a system service (launchd / systemd-user / Windows Service) — same UX on every OS.\n3. **MCP tools** plugged into your IDE: `a2a_whoami`, `a2a_list_agents`, `a2a_send_message`, `a2a_send_streaming`, `a2a_get_task`, `a2a_cancel_task`, `a2a_inbox`, `a2a_complete_task`.\n4. **One-line install** that detects every supported IDE on your machine and registers the MCP server with `.bak` backups of your configs.\n5. **Skill `a2a-bridge`** for Claude Code that loads only when relevant — no globally-loaded rules eating tokens on every session.\n\n## Use cases — what this actually unlocks\n\n### 1. Cross-stack contract changes propagate without copy-paste\n\nYou change a JSON shape in `backend/api.go`. Your Claude Code session\nrunning there fires off:\n\n```\na2a_send_message peer_url=\u003cfrontend-claude\u003e text=\"[backend-3a2f] FYI:\nGET /orders now returns `currency` (string, ISO 4217). Was implicit USD.\"\n```\n\nThe frontend Claude session sees that line **at the top of your next\nprompt** (via the UserPromptSubmit hook), so before it touches\n`useOrders.ts` it already knows the field is required. No Slack ping,\nno PR review delay.\n\n### 2. One refactor, several agents fan out the work\n\n```\nYou (in Claude Code, IDE):\n  Refactor the payment module. Delegate the Go service to Codex,\n  the Vue checkout to the Cursor session, and have the Cline session\n  audit the migration once Go finishes.\n\nClaude:\n  → a2a_send_message peer_url=\u003ccodex\u003e text=\"...\"     # Go service\n  → a2a_send_message peer_url=\u003ccursor\u003e text=\"...\"    # Vue checkout\n  Tracks both task IDs; when Codex completes, fires off the\n  Cline audit task with Codex's diff attached.\n```\n\nThree agents working concurrently, one human in the loop.\n\n### 3. An always-online agent picks up tasks while you sleep\n\n```\n$ a2abridge worker start --cmd claude --prompt \"You are a maintenance\n  agent. Drain a2a_inbox and address every request. If unsure, reply\n  with a question and stop.\"\n```\n\nNow any peer (yours or a teammate's) can `a2a_send_message` to that\nworker URL and get a reply hours later — even after you've closed every\nIDE window. The worker survives reboots if you `a2abridge service\ninstall` the directory daemon.\n\n### 4. ADK / LangGraph / CrewAI agents drop into the same mesh\n\na2abridge is the **open-protocol** bridge — third-party agents that\nspeak A2A 1.0 are first-class peers without glue code. See\n[`docs/integrations/`](docs/integrations/) for working examples with\nGoogle ADK 1.0, LangGraph 0.4.7+, CrewAI 0.95+ and LlamaIndex 0.13+.\n\n### 5. Cross-machine federation (laptop ↔ desktop ↔ remote dev box)\n\nSet `A2A_TLS_CERT` / `A2A_TLS_KEY` / `A2A_TRUST_ROOTS` on each side,\noptionally `A2A_MDNS=1` for LAN auto-discovery, and your home Mac talks\nto your office Linux box over mTLS-authenticated A2A. ed25519 cert\ngeneration is one command (`a2abridge cert generate`). See [Security\nmodel](#security-model) below.\n\n## Quick start\n\n### macOS / Linux / WSL2\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/\u003cowner\u003e/a2abridge/main/install.sh | bash\n```\n\n### Windows (PowerShell as user, no admin)\n\n```powershell\niwr -useb https://raw.githubusercontent.com/\u003cowner\u003e/a2abridge/main/install.ps1 | iex\n```\n\n### What the installer does\n\n1. Downloads the right binary from GitHub Releases for your `os/arch` and verifies its SHA256 against the release's `checksums.txt` before installing.\n2. Drops it into `~/.a2abridge/bin/a2abridge` and `chmod +x`.\n3. Detects installed IDEs and writes the MCP block to each one's config — with timestamped `.bak` next to the original:\n   - Claude Code → `~/.claude.json` (hooks stay in `~/.claude/settings.json`)\n   - Codex CLI → `~/.codex/config.toml`\n   - Cline (VS Code) → `~/.config/Code/User/settings.json` (`cline.mcpServers`)\n   - Continue → `~/.continue/config.json`\n   - Cursor → `~/.cursor/mcp.json`\n   - Gemini CLI → `~/.gemini/settings.json`\n4. Registers `a2abridge directory` as a user-level system service (`launchd` / `systemd --user` / Windows Service) and starts it on `127.0.0.1:7777`.\n5. Installs the `a2a-bridge` skill into `~/.claude/skills/a2a-bridge/` and adds `~/.claude/hooks/a2a-inbox-hook.sh` (so other agents' messages show up in your prompt).\n6. Runs `a2abridge doctor` to verify everything is healthy.\n\nTo preview without making changes: `a2abridge install --dry-run`.\n\n## First run — Hello World between two agents\n\nAfter the installer completes, here's the 3-step verification that\neverything is wired correctly. Two terminal windows are enough.\n\n**Terminal 1 — open Claude Code in any project**\n\n```bash\ncd ~/some/project\nclaude    # or just open VS Code with the Claude Code extension\n```\n\nIn the chat, type:\n\n```\nWhat's my A2A label and which peers are online?\n```\n\nClaude will call `a2a_whoami` (returns its own Agent Card with a stable\nlabel like `claude-ttys000`) and `a2a_list_agents` (returns the list of\npeers — empty for now since you only have one bridge running).\n\n**Terminal 2 — open Codex CLI in another project**\n\n```bash\ncd ~/another/project\ncodex\n```\n\nType:\n\n```\nList the A2A peers you can see.\n```\n\nCodex calls `a2a_list_agents` — and now sees the Claude bridge from\nTerminal 1. Send it a message:\n\n```\nSend \"ping from codex\" to the claude-ttys000 peer.\n```\n\nCodex calls `a2a_send_message`. The message is queued in Claude's inbox.\n\n**Terminal 1 — type any prompt**\n\nThe UserPromptSubmit hook drains the inbox automatically and prepends\nthe message above your prompt:\n\n```\nYou have 1 unread A2A message(s):\n- from `codex-ttysXXX` (task ABC...): ping from codex\n```\n\nClaude can now `a2a_complete_task task_id=ABC text=\"pong\"` and Codex\nwill see the reply on its next turn (the SSE fast-path delivers it in\n~milliseconds).\n\n**Verify directly via curl** (always works, regardless of IDE state):\n\n```bash\ncurl http://127.0.0.1:7777/agents | jq .\n# → list of registered peers and their URLs\n\nPEER_URL=$(curl -s http://127.0.0.1:7777/agents | jq -r '.[0].url')\ncurl \"$PEER_URL/.well-known/agent-card.json\" | jq .\n# → that peer's Agent Card\n```\n\nIf anything looks wrong, run `a2abridge doctor` — it tells you exactly\nwhich check failed and how to fix it.\n\n## Per-agent setup notes\n\nThe `a2abridge install` step writes the right MCP block into each\ndetected IDE's config. This section explains what that block looks like\nper IDE so you can verify by hand or wire it up manually.\n\n### Claude Code (`~/.claude.json` + `~/.claude/settings.json`)\n\nThe MCP server registration goes into `~/.claude.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"a2a\": {\n      \"command\": \"/Users/\u003cyou\u003e/.a2abridge/bin/a2abridge\",\n      \"args\": [\"bridge\"],\n      \"env\": {\n        \"A2A_DIRECTORY\": \"http://127.0.0.1:7777\",\n        \"A2A_BIND\": \"127.0.0.1:0\",\n        \"A2A_NAME\": \"claude-ide\",\n        \"A2A_MODEL\": \"claude-opus-4-7\",\n        \"A2A_SKILLS\": \"go,php,vue,refactor,review\"\n      }\n    }\n  }\n}\n```\n\nThe hook block stays in `~/.claude/settings.json`:\n\n```json\n{\n  \"hooks\": {\n    \"UserPromptSubmit\": [{\n      \"matcher\": \"*\",\n      \"hooks\": [{\n        \"type\": \"command\",\n        \"command\": \"/Users/\u003cyou\u003e/.claude/hooks/a2a-inbox-hook.sh\"\n      }]\n    }]\n  }\n}\n```\n\nThe hook script auto-injects the inbox before every prompt. Restart\nClaude Code after editing.\n\n### Codex CLI (`~/.codex/config.toml`)\n\n```toml\n[mcp_servers.a2a]\ncommand = \"/Users/\u003cyou\u003e/.a2abridge/bin/a2abridge\"\nargs = [\"bridge\"]\n\n[mcp_servers.a2a.env]\nA2A_DIRECTORY = \"http://127.0.0.1:7777\"\nA2A_BIND = \"127.0.0.1:0\"\nA2A_NAME = \"codex\"\nA2A_SKILLS = \"code,plan\"\n```\n\nVerify with `codex mcp list` — `a2a` should be listed as `enabled / stdio`.\n\n### Cursor (`~/.cursor/mcp.json`)\n\nSame shape as Claude Code's `mcpServers` block. Restart Cursor.\n\n### Cline (VS Code)\n\nCline reads MCP from\n`\u003cvs-code-globalStorage\u003e/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`,\nnot VS Code's main `settings.json`. The installer drops the block there\nautomatically.\n\n### Continue\n\nContinue 1.x reads MCP servers from\n`~/.continue/mcpServers/\u003cname\u003e.yaml`. The installer writes\n`a2a.yaml` there with the equivalent fields.\n\n### Gemini CLI (`~/.gemini/settings.json`)\n\nSame `mcpServers` shape as Claude Code. After a restart, `gemini /mcp`\nwill list the `a2a` server.\n\n### Two instances of the same IDE on the same host\n\nOverride `A2A_ID` and `A2A_NAME` per-window so they don't fight for the\nsame directory entry:\n\n```bash\nA2A_ID=claude-ide-main A2A_NAME=claude-ide claude  # window 1\nA2A_ID=claude-term     A2A_NAME=claude-term claude # window 2\n```\n\nWithout overrides, the second window will quietly overwrite the first\nin the directory.\n\n## Manual install (no curl)\n\n```bash\ngit clone https://github.com/\u003cowner\u003e/a2abridge ~/PROJECT/a2abridge\ncd ~/PROJECT/a2abridge\ngo build -o ~/.a2abridge/bin/a2abridge ./cmd/a2abridge\n~/.a2abridge/bin/a2abridge install --ide auto\n```\n\n## Architecture\n\n```\n                            ┌─────────────────────────────┐\n                            │   a2abridge directory       │  user-level system service\n                            │   :7777 (loopback)          │  (launchd · systemd-user · WinSvc)\n                            │   POST /register            │\n                            │   GET  /agents              │\n                            └────────▲────────────────────┘\n                                     │ heartbeat / advertise own URL\n              ┌──────────────────────┼──────────────────────┐\n              │                      │                      │\n   ┌──────────┴──────────┐ ┌─────────┴───────────┐ ┌────────┴───────────┐\n   │ Claude Code (IDE)   │ │ Claude Code (term)  │ │ Codex CLI / Cursor │\n   │ ─ MCP stdio         │ │ ─ MCP stdio         │ │ ─ MCP stdio        │\n   │     ↕               │ │     ↕               │ │     ↕              │\n   │ a2abridge bridge    │ │ a2abridge bridge    │ │ a2abridge bridge   │\n   │ http://127.0.0.1:N  │ │ http://127.0.0.1:M  │ │ http://127.0.0.1:K │\n   │ A2A server + client │ │ A2A server + client │ │ A2A server + client│\n   └──────────┬──────────┘ └─────────┬───────────┘ └────────┬───────────┘\n              │                      │                      │\n              └──────────  JSON-RPC 2.0 + SSE  ──────────────┘\n                       (peers talk to peers, directly)\n```\n\n- One binary, multiple subcommands. `a2abridge directory` runs as a daemon. `a2abridge bridge` is launched as MCP stdio server by your IDE — its lifecycle equals your IDE session.\n- Per-agent state lives in `./.a2a/` inside your current working directory (inbox, label, logs). Out-of-cwd state lives under `~/.a2abridge/`.\n- All loopback by default. Cross-machine federation is opt-in (mTLS + ed25519) — see [Security model](#security-model).\n\n## Subcommands\n\n| Command | What |\n|---|---|\n| `a2abridge install [--ide auto\\|claude-code,codex,...] [--dry-run] [--apply]` | Detect IDEs, write MCP configs (`.bak` backups), install service, install skill, register UserPromptSubmit hook |\n| `a2abridge directory [--addr 127.0.0.1:7777]` | Run discovery service (used by the system service unit) |\n| `a2abridge bridge` | Run as MCP stdio server (used by IDEs, do not call manually) |\n| `a2abridge service {install\\|start\\|stop\\|restart\\|status\\|uninstall}` | Manage the directory daemon under launchd / systemd-user / Windows Service |\n| `a2abridge doctor` | Health check: directory ping, ports, IDE configs, skill, hook, version |\n| `a2abridge update [--check]` | Self-update from the latest GitHub release (SHA256-verified against `checksums.txt`) with rollback on failure |\n| `a2abridge uninstall [--purge] [--keep-service]` | Remove the MCP block from every IDE config, skill, hook, and service (`.bak` unless `--purge`) |\n| `a2abridge cert generate [--cn \u003cname\u003e] [--dir \u003cpath\u003e]` | Produce an ed25519 self-signed cert + key for federation |\n| `a2abridge completion {bash\\|zsh\\|fish\\|powershell}` | Emit a tab-completion script for your shell |\n\n## MCP tools\n\n| Tool | Maps to | Use |\n|---|---|---|\n| `a2a_whoami` | own Agent Card | \"who am I to other agents\" |\n| `a2a_list_agents` | `GET /agents` on directory | list peers + their cards |\n| `a2a_send_message` | `message/send` | fire-and-forget or blocking task |\n| `a2a_send_streaming` | `message/stream` | wait for completion via SSE |\n| `a2a_get_task` | `tasks/get` | poll a previously sent task |\n| `a2a_cancel_task` | `tasks/cancel` | cancel a running task |\n| `a2a_inbox` | local inbox | fetch unread incoming messages |\n| `a2a_complete_task` | `message/send` reply + state→`completed` | answer an incoming task |\n\n## Skill (Claude Code)\n\nThe installer drops a skill into `~/.claude/skills/a2a-bridge/`. It auto-loads when your prompt contains triggers like *\"a2a\"*, *\"another agent\"*, *\"smoke test peers\"*, *\"FYI to backend\"*, *\"broadcast\"*. The skill teaches Claude:\n\n- the inbound flow (poll inbox before answering you, classify FYI vs request-for-action),\n- when to send proactive FYI to peers (API contract changes, schema changes, infra changes),\n- the self-label format `\u003cbasename-cwd\u003e-\u003c4hex\u003e` so peers know who is talking,\n- how to use each MCP tool with real examples.\n\nWithout the skill, Claude has the tools but no idea when to use them. With the skill, you do not need to ask \"check inbox\" — it does it on its own.\n\n## Configuration\n\nSet per-bridge environment in your IDE config (the installer fills sensible defaults):\n\n| Env | Default | Meaning |\n|---|---|---|\n| `A2A_DIRECTORY` | `http://127.0.0.1:7777` | URL of the directory service |\n| `A2A_BIND` | `127.0.0.1:0` | bind addr/port (`:0` = random free port) |\n| `A2A_ADVERTISE_HOST` | `127.0.0.1` | host to advertise to the directory |\n| `A2A_NAME` | derived from binary path | human-readable name shown to peers |\n| `A2A_ID` | `\u003cname\u003e-\u003cpid\u003e` | stable id for the peer |\n| `A2A_MODEL` | unset | model id reported in Agent Card (`claude-opus-4-7`, `gpt-5`, ...) |\n| `A2A_SKILLS` | unset | comma-separated capability tags |\n| `A2A_STATE_DIR` | `./.a2a` | per-project inbox/label/log directory |\n\nCross-machine federation: `A2A_TLS_CERT`, `A2A_TLS_KEY`, `A2A_TRUST_ROOTS` (required once cert/key are set), `A2A_PEER_ALLOW`.\n\n## How the inbox flow actually works\n\nThe hardest thing to internalise is **when** peers see messages. Here's\nthe model in 5 lines:\n\n1. Peer A calls `a2a_send_message peer_url=\u003cB\u003e` — task lands in B's\n   `Store` and B's `inbox` file (`./.a2a/inbox-\u003cppid\u003e.json`).\n2. B's UserPromptSubmit hook reads the inbox **on B's next prompt**\n   from the human user — and prepends it to the system prompt.\n3. B answers the human. Within that turn (or the next) B can call\n   `a2a_complete_task task_id=...` to reply to A.\n4. The reply lands as a `completed` Task on A's bridge. The bridge's\n   SSE subscriber sees it instantly (or, fallback, the 5-second poller).\n5. A gets a synthetic message in **its** inbox: \"ОТВЕТ от B на твой\n   вопрос «...»\" — which prints on A's next prompt the same way.\n\nSo end-to-end latency is **one prompt from the recipient + one from\nthe sender** to see the reply. That is the same delay you'd have over\nDM with a colleague — the bridge doesn't wake idle agents, it just\nmakes sure neither side misses the message.\n\n## Troubleshooting\n\n```bash\na2abridge doctor\n```\n\nOutput is a table of checks, each PASS/WARN/FAIL with a fix hint. Typical failures:\n\n- **directory not running** → `a2abridge service start`\n- **port 7777 in use** → `a2abridge service uninstall \u0026\u0026 a2abridge install --directory-port 7778`\n- **IDE config missing the MCP block** → re-run `a2abridge install --ide claude-code`\n- **inbox stale** → `rm -rf ./.a2a/inbox` (the bridge will rebuild on next message)\n- **two Claude windows clobbering each other in the directory** → set distinct `A2A_ID` env per window\n\nLogs:\n\n- macOS: `~/Library/Logs/a2abridge/directory.log`\n- Linux: `journalctl --user -u a2abridge-directory.service`\n- Windows: `Get-EventLog -LogName Application -Source a2abridge-directory`\n- Per-bridge: `./.a2a/bridge.log`\n\n## Compatibility\n\n| Platform | Service supervisor | Tested |\n|---|---|---|\n| macOS 13+ (Intel and Apple Silicon) | launchd | yes |\n| Ubuntu 22.04+ / Debian 12+ / Fedora 40+ | systemd --user | yes |\n| Arch / openSUSE / RHEL 9+ | systemd --user | best-effort |\n| Windows 11 | Windows Service Manager | yes |\n| WSL2 (Ubuntu) with `systemd=true` | systemd --user inside WSL | yes |\n| WSL2 without systemd | Windows-side service + `wsl.exe` shim | yes |\n\n| AI agent | MCP integration | Verified |\n|---|---|---|\n| Claude Code | `~/.claude.json` (hooks in `~/.claude/settings.json`) | yes |\n| Codex CLI | `~/.codex/config.toml` | yes |\n| Cline (VS Code) | `cline.mcpServers` in VS Code settings | yes |\n| Continue | `~/.continue/config.json` | yes |\n| Cursor | `~/.cursor/mcp.json` | yes |\n| Gemini CLI | `~/.gemini/settings.json` | yes |\n| Aider | `aider.conf.yml` (bridge mode) | best-effort |\n| Any A2A 1.0 peer | direct JSON-RPC | yes |\n\n## Security model\n\n- **Loopback by default.** Directory and bridges bind `127.0.0.1`. Other users on the machine cannot see your peers.\n- **PII / secret screen** before `a2a_send_message`: 11 regex detectors (AWS access key, GitHub PAT, Anthropic / OpenAI / Google / Stripe / Slack tokens, JWT, PEM private keys, ...). Matches are replaced with `[REDACTED:\u003cname\u003e]` and surfaced in MCP metadata. The message still goes through with redacted text — the secret never leaves the bridge.\n- **mTLS + ed25519 federation** (opt-in cross-machine): set `A2A_TLS_CERT`, `A2A_TLS_KEY`, `A2A_TRUST_ROOTS`, `A2A_PEER_ALLOW` and the bridge serves over TLS 1.3 with required client certs and an allow-list match on peer CN/SAN. `A2A_TRUST_ROOTS` is mandatory once cert/key are set — the bridge refuses to start without it (no silent fallback to the system pool). Keys are generated by `a2abridge cert generate`.\n- **Verified releases.** Every GitHub release ships a `checksums.txt`; `a2abridge update` and the `install.sh` / `install.ps1` scripts verify the binary's SHA256 against it before swapping anything in.\n- **User hook scripts**: drop `~/.a2abridge/hooks/{on-inbound,on-outgoing-reply}.sh` (or `.ps1`/`.cmd` on Windows) and the bridge fires them on every inbound message and outbound reply (5-second timeout, JSON on stdin, fields in `A2A_EVENT_*` env vars).\n- **No telemetry.** Period.\n\n## Roadmap\n\n### v1.0.0 — shipped\n- [x] Single binary with subcommands (directory, bridge, install, uninstall, update, service, doctor, cert, completion)\n- [x] `kardianos/service` cross-platform supervisor (launchd · systemd-user · Windows Service · WSL2)\n- [x] `a2abridge install` with auto-detection of 6 IDEs and `.bak` backups\n- [x] `install.sh` + `install.ps1` one-line installers\n- [x] `a2abridge doctor` — 9-check health audit\n- [x] Project-local `./.a2a/` state with `~/.a2abridge/state/\u003cppid\u003e` fallback\n- [x] Skill `a2a-bridge` + UserPromptSubmit hook shipped via installer\n- [x] SSE fast-path for outbound replies (`tasks/resubscribe`) with polling fallback\n- [x] PII / secret screen before send (11 regex detectors)\n- [x] User hook scripts on `on-inbound` / `on-outgoing-reply`\n- [x] Push Notifications per A2A 1.0 §9.5 (4 RPC methods + webhook delivery)\n- [x] HTTP+REST convenience API under `/v1/` (non-spec extension; the spec binding is JSON-RPC at `POST /`)\n- [x] mTLS + ed25519 federation (opt-in cross-machine)\n- [x] `a2abridge cert generate` for ed25519 self-signed cert/key\n- [x] Self-update + uninstall + shell completion\n- [x] 35 test cases under `-race`, GitHub Actions test + release matrix\n\n### v1.1.0 — shipped\n- [x] mDNS / DNS-SD cross-machine discovery (`A2A_MDNS=1`)\n- [x] `a2abridge service install --federation` one-step cert + service install\n- [x] Push notification retry with exponential backoff (5xx + network errors)\n\n### v2.0.0 — shipped\n- [x] `a2abridge worker {start|stop|status|attach}` — always-online Claude in detached tmux\n- [x] Integration docs for Google ADK 1.0, LangGraph, CrewAI, LlamaIndex Agents — see [docs/integrations/](docs/integrations/)\n\n### v2.1 — next (open)\n- [ ] gRPC binding per A2A 1.0 §7.2 (deferred — needs `protoc` toolchain in CI)\n- [ ] Enterprise SSO / SCIM for the directory in multi-team installs\n- [ ] Signed-manifest WAN discovery (alternative to mDNS for cross-internet peers)\n\n## FAQ\n\n**Does this require an Anthropic / OpenAI API key?**\nNo. Each peer is whatever LLM your IDE is already using on its own\nsubscription. a2abridge is just the wire between them — it never calls\nan LLM API itself.\n\n**How many tokens does this burn?**\nZero on its own. The bridge does HTTP, not LLM calls. Your IDE pays for\nthe prompts it generates when it decides to use `a2a_*` tools — same\nbilling as any other tool call.\n\n**What if I already have other MCP servers in my Claude config?**\nThe installer merges the `a2a` entry into the existing `mcpServers`\nmap without disturbing anything else, and creates a `.bak.\u003ctimestamp\u003e`\nof the original file. Run `a2abridge install --dry-run` to preview.\n\n**Does it work over a corporate VPN / behind a proxy?**\nSingle-machine setup is loopback-only — no proxy involved. Cross-machine\nmode (mTLS) goes over plain HTTPS, so any proxy that lets you reach a\npeer's IP and port works. mDNS won't traverse most VPNs — use the\ndirectory daemon over an internet-reachable IP instead.\n\n**Does it leak my code / messages anywhere?**\nNo telemetry, no third-party calls. Default loopback bind is `127.0.0.1`\n— other users on the machine cannot see your peers. Outbound messages\npass through an 11-pattern PII screen that strips AWS / GitHub / API\nkeys / JWTs / PEM blocks before they leave the bridge.\n\n**Can I disable the auto-injecting hook?**\nYes. Either delete `~/.claude/hooks/a2a-inbox-hook.sh`, or remove the\n`hooks.UserPromptSubmit` block from `~/.claude/settings.json`, or run\n`a2abridge uninstall --keep-service` (preserves the directory daemon\nbut rolls back the hook + skill + IDE configs).\n\n**Why is my second Claude window invisible to peers?**\nBoth windows share the same default `A2A_ID`, so the second one\noverwrites the first in the directory. Set distinct `A2A_ID` /\n`A2A_NAME` per window — see [Per-agent setup notes](#per-agent-setup-notes).\n\n**Does Cline / Continue / Cursor really work?**\nYes — they all support MCP stdio servers with the same `mcpServers`\nshape. The installer writes the right path for each one. Run\n`a2abridge doctor` to confirm.\n\n**What happens if the directory daemon crashes?**\nBridges keep running; they just lose discovery for new peers. Existing\n`peer_url` references still work (they're cached in the inbox / task\nmetadata). When the daemon comes back, bridges auto-re-register on\ntheir next 30-second heartbeat. If you're running cross-machine with\nmDNS, peers keep finding each other directly via DNS-SD even with the\ndaemon down.\n\n**Why JSON-RPC and not gRPC?**\nJSON-RPC works in every browser fetch / cURL script and needs no\nprotoc toolchain. gRPC binding (A2A 1.0 §7.2) is on the roadmap for\nv2.1 — open issue if you'd use it, otherwise we skip it.\n\n## Contributing\n\nIssues and PRs welcome. The code base is small (~2k LOC of Go) and the spec is fixed, so contributions are easy to scope.\n\n```bash\ngit clone https://github.com/\u003cowner\u003e/a2abridge\ncd a2abridge\ngo test ./...\ngo build ./cmd/a2abridge\n./a2abridge doctor\n```\n\nConventional Commits, English subjects, no AI co-authors.\n\n## Specification compliance\n\n`a2abridge` is implemented against [A2A Protocol Specification 1.0](https://a2a-protocol.org/latest/specification/):\n\n- Agent Card (§5) on `/.well-known/agent-card.json`\n- JSON-RPC 2.0 binding (§7) at `POST /` with spec method names: `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`, `tasks/resubscribe`, `agent/getAuthenticatedExtendedCard`, plus `tasks/list` as a documented non-spec extension\n- TaskState enum (§6.4): `submitted`, `working`, `completed`, `failed`, `canceled`, `input-required`, `rejected`, `auth-required`\n- Message / Part / Artifact (§6.1–6.6) with roles `user` / `agent` and the spec Part union on the wire: `{\"kind\":\"text\",\"text\":...}` / `{\"kind\":\"file\",\"file\":{...}}` / `{\"kind\":\"data\",\"data\":...}`\n- Stream one-of: `task | message | statusUpdate | artifactUpdate`\n- Error codes from §8 (`-32001 TaskNotFound`, `-32003 PushNotificationNotSupported`, `-32004 UnsupportedOperation`, ...)\n- Header `A2A-Version: 1.0`\n- Push Notifications (§9.5) — `tasks/pushNotificationConfig/set`, `get`, `list`, `delete` plus webhook delivery on every state change\n- HTTP+REST convenience API mirroring all RPC verbs at `/v1/...` (non-spec extension — the spec-defined binding is JSON-RPC at `POST /`)\n- mTLS server/client auth with ed25519 cert generation\n\n**Upgrading from pre-3.0:** the legacy proto-style method names (`a2a.SendMessage`, `a2a.GetTask`, ...) are still accepted by the server as deprecated aliases, and the old Agent Card path `/.well-known/a2a` is still served as an alias of `/.well-known/agent-card.json` — but new clients should use the spec names and path only.\n\nNot yet implemented: gRPC binding (§7.2).\n\n## Support the project\n\na2abridge is MIT-licensed and free, but it's also a one-developer\nproject that runs on weekends. If it saves you copy-paste between\nagents, consider chipping in:\n\n- 💛 [GitHub Sponsors](https://github.com/sponsors/vbcherepanov) — recurring or one-off, GitHub-native\n- 💸 [PayPal](https://PayPal.Me/vbcherepanov) — one-shot donations\n\nSponsors get their name in the repo `README` and direct line for\nfeature requests.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n\n## Credits\n\nBuilt on the open work of:\n- [Linux Foundation A2A project](https://github.com/a2aproject/A2A) — protocol specification\n- [`mark3labs/mcp-go`](https://github.com/mark3labs/mcp-go) — MCP server SDK\n- [`kardianos/service`](https://github.com/kardianos/service) — cross-platform service supervisor\n- [`google/uuid`](https://github.com/google/uuid)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbcherepanov%2Fa2abridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbcherepanov%2Fa2abridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbcherepanov%2Fa2abridge/lists"}