{"id":47745302,"url":"https://github.com/runloopai/agent-axon-client-ts","last_synced_at":"2026-04-15T05:00:21.617Z","repository":{"id":348651336,"uuid":"1199167816","full_name":"runloopai/agent-axon-client-ts","owner":"runloopai","description":"Axon-backed ACP and Claude agent clients for Runloop broker agents","archived":false,"fork":false,"pushed_at":"2026-04-10T19:23:48.000Z","size":1128,"stargazers_count":0,"open_issues_count":12,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T19:28:23.278Z","etag":null,"topics":["acp","agent","axon","claude","runloop","sdk","typescript"],"latest_commit_sha":null,"homepage":"https://runloop.ai","language":"TypeScript","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/runloopai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","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":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"runloopai"}},"created_at":"2026-04-02T05:25:48.000Z","updated_at":"2026-04-10T19:18:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/runloopai/agent-axon-client-ts","commit_stats":null,"previous_names":["runloopai/agent-axon-client-ts"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/runloopai/agent-axon-client-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runloopai%2Fagent-axon-client-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runloopai%2Fagent-axon-client-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runloopai%2Fagent-axon-client-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runloopai%2Fagent-axon-client-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/runloopai","download_url":"https://codeload.github.com/runloopai/agent-axon-client-ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runloopai%2Fagent-axon-client-ts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31824118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T18:05:02.291Z","status":"online","status_checked_at":"2026-04-15T02:00:06.175Z","response_time":63,"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":["acp","agent","axon","claude","runloop","sdk","typescript"],"created_at":"2026-04-03T00:42:46.915Z","updated_at":"2026-04-15T05:00:21.607Z","avatar_url":"https://github.com/runloopai.png","language":"TypeScript","funding_links":["https://github.com/sponsors/runloopai"],"categories":[],"sub_categories":[],"readme":"# @runloop/agent-axon-client\n\n[![CI](https://github.com/runloopai/agent-axon-client-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/runloopai/agent-axon-client-ts/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/@runloop/agent-axon-client)](https://www.npmjs.com/package/@runloop/agent-axon-client)\n[![Docs](https://img.shields.io/badge/docs-TypeDoc-blue)](https://runloopai.github.io/agent-axon-client-ts/)\n[![codecov](https://codecov.io/gh/runloopai/agent-axon-client-ts/branch/main/graph/badge.svg)](https://codecov.io/gh/runloopai/agent-axon-client-ts)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n\u003e **Alpha — subject to change.** This SDK is in early development. APIs, interfaces, and behavior may change without notice between versions.\n\nTypeScript SDK for connecting to coding agents (Claude Code, OpenCode, etc.) running inside [Runloop](https://runloop.ai) devboxes via the Axon event bus.\n\n## Key Concepts\n\nBefore getting started, it's helpful to understand these core concepts:\n\n- **Runloop** — A cloud platform that provides on-demand development environments (devboxes) where coding agents can run.\n- **Devbox** — An isolated Linux container/environment running in Runloop's cloud where coding agents execute. It has a filesystem, can run commands, and persists for the duration of your session.\n- **Axon** — A bidirectional message bus that enables real-time communication between your application and an agent running in a Runloop devbox. Think of it as a WebSocket-like channel for agent control.\n- **Broker Mount** — A devbox configuration that connects an Axon channel to an agent binary, specifying which agent to run (opencode, claude, etc.), the protocol to use (acp, claude_json), and launch arguments.\n\nIn short: **Runloop** hosts **devboxes** where agents run; a **broker mount** connects that agent to **Axon**; and **Axon** is the message bus your app uses to control it.\n\n## Prerequisites\n\n- [Node.js](https://nodejs.org) \u003e= 22.0.0\n- A [Runloop](https://runloop.ai) API key\n  - Sign up for free at [platform.runloop.ai](https://platform.runloop.ai) (includes $50 in credits)\n  - Navigate to [Settings](https://platform.runloop.ai/settings) → API Keys\n  - Create an API key (starts with `ak`_)\n  - Set environment variable: `export RUNLOOP_API_KEY=ak_your_key`\n- An [Anthropic](https://console.anthropic.com) API key (**only required for Claude module examples**)\n  - Sign up at [console.anthropic.com](https://console.anthropic.com)\n  - Go to API Keys section\n  - Create new key (starts with `sk-ant-`)\n  - Set environment variable: `export ANTHROPIC_API_KEY=sk-ant-your_key`\n\n## Installation\n\n```bash\nnpm install @runloop/agent-axon-client @runloop/api-client\n```\n\n`@runloop/api-client` is a required peer dependency — it provides the `RunloopSDK` instance and Axon types used by both modules.\n\nIf you're using the Claude module, also install:\n\n```bash\nnpm install @anthropic-ai/claude-agent-sdk\n```\n\n## Status \u0026 Roadmap\n\n### Supported Features by Protocol\n\n\n| Capability                                   | Claude | ACP |\n| -------------------------------------------- | ------ | --- |\n| Send prompts / messages                      | ✅      | ✅   |\n| Streaming responses                          | ✅      | ✅   |\n| Tool use / tool results                      | ✅      | ✅   |\n| Cancel / interrupt turns                     | ✅      | ✅   |\n| Permission / control requests (auto-approve) | ✅      | ✅   |\n\n\n*Auto-approve only for now, permission request flow pending\n\n### Coming Soon\n\n\n| Status     | Description                                                                                                                                |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------ |\n| 🚧 Planned | **Agent installation** — support for automatically getting agents installed on the devbox                                                  |\n| 🚧 Planned | **Devbox state-transition events** — expose devbox lifecycle state changes (creating → running → suspended → …) as first-class Axon events |\n| 🚧 Planned | **Axon subscribe over WebSockets** — WebSocket transport for Axon subscriptions, enabling browser clients without a backend proxy          |\n\n\n### Known Issues\n\n\n| Status | Description                                                                                                                          |\n| ------ | ------------------------------------------------------------------------------------------------------------------------------------ |\n| 🐛 Bug | Suspend and resume of a devbox will not work correctly at the moment, this will be fixed soon.                                       |\n\n\n## Modules\n\nThe SDK has two independent modules — pick the one that matches your agent's protocol:\n\n\n| Module     | Import path                         | Protocol                                                                | Use when                                        |\n| ---------- | ----------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------- |\n| **ACP**    | `@runloop/agent-axon-client/acp`    | [Agent Client Protocol](https://agentclientprotocol.com) (JSON-RPC 2.0) | Using OpenCode, or Claude via ACP               |\n| **Claude** | `@runloop/agent-axon-client/claude` | Claude Code SDK wire format                                             | Using Claude Code with native SDK message types |\n\n\n### Which module should I use?\n\n**Use the ACP module when:**\n\n- You want agent-agnostic code that works with multiple agents (OpenCode, Claude via ACP, future agents)\n- You need a standardized JSON-RPC 2.0 protocol\n- You want maximum compatibility and flexibility\n\n**Use the Claude module when:**\n\n- You're specifically using Claude Code\n- You want native Claude SDK message types\n- You need Claude-specific features\n\n**Note:** The modules have different APIs and are not directly interchangeable. Choose based on your agent and requirements.\n\n## Usage\n\n### ACP module\n\n```typescript\nimport { ACPAxonConnection, PROTOCOL_VERSION, isAgentMessageChunk } from \"@runloop/agent-axon-client/acp\";\nimport { RunloopSDK } from \"@runloop/api-client\";\n\nconst sdk = new RunloopSDK({ bearerToken: process.env.RUNLOOP_API_KEY });\n\nconst axon = await sdk.axon.create({ name: \"acp-transport\" });\nconst devbox = await sdk.devbox.create({\n  mounts: [\n    {\n      type: \"broker_mount\",\n      axon_id: axon.id,\n      protocol: \"acp\",\n      agent_binary: \"opencode\",\n      launch_args: [\"acp\"],\n    },\n  ],\n});\nconst agent = new ACPAxonConnection(axon, devbox, {\n  onDisconnect: async () =\u003e {\n    await devbox.shutdown();\n  },\n});\n\nawait agent.connect();\nawait agent.initialize({\n  protocolVersion: PROTOCOL_VERSION,\n  clientInfo: { name: \"my-app\", version: \"1.0.0\" },\n});\n\nagent.onSessionUpdate((sessionId, update) =\u003e {\n  if (isAgentMessageChunk(update)) process.stdout.write(update.message);\n});\n\nconst session = await agent.newSession({ cwd: \"/home/user\", mcpServers: [] });\nawait agent.prompt({\n  sessionId: session.sessionId,\n  prompt: [{ type: \"text\", text: \"Hello!\" }],\n});\n\nawait agent.disconnect();\n```\n\n### Claude module\n\n```typescript\nimport { ClaudeAxonConnection } from \"@runloop/agent-axon-client/claude\";\nimport { RunloopSDK } from \"@runloop/api-client\";\n\nconst sdk = new RunloopSDK({ bearerToken: process.env.RUNLOOP_API_KEY });\n\nconst axon = await sdk.axon.create({ name: \"claude-transport\" });\nconst devbox = await sdk.devbox.create({\n  mounts: [{\n    type: \"broker_mount\",\n    axon_id: axon.id,\n    protocol: \"claude_json\",\n    agent_binary: \"claude\",\n  }],\n});\n\nconst conn = new ClaudeAxonConnection(axon, devbox, { model: \"claude-sonnet-4-5\" });\nawait conn.connect();\nawait conn.initialize();\n\nawait conn.send(\"What files are in this directory?\");\n\nfor await (const msg of conn.receiveResponse()) {\n  console.log(msg.type, msg);\n}\n\nawait conn.disconnect();\n```\n\n### Timeline events\n\nBoth modules provide a unified timeline event stream — the recommended way to build chat UIs that need a single chronological view of protocol messages, system events (turn start/end), and custom events.\n\nEvery timeline event has `{ kind, data, axonEvent }` where `kind` is a discriminant (`\"acp_protocol\"` / `\"claude_protocol\"`, `\"system\"`, or `\"unknown\"`), `data` is the typed payload, and `axonEvent` is the raw Axon event with full metadata.\n\n**ACP — handling protocol events:**\n\n```typescript\nimport { SYSTEM_EVENT_TYPES } from \"@runloop/agent-axon-client/shared\";\nimport {\n  isAgentMessageChunk,\n  isToolCall,\n  isToolCallProgress,\n} from \"@runloop/agent-axon-client/acp\";\n\nagent.onTimelineEvent((event) =\u003e {\n  switch (event.kind) {\n    case \"acp_protocol\":\n      if (event.eventType === \"session/update\") {\n        const update = event.data.update;\n        if (isAgentMessageChunk(update)) {\n          process.stdout.write(update.text);\n        } else if (isToolCall(update)) {\n          console.log(`Tool: ${update.name} (${update.status})`);\n        } else if (isToolCallProgress(update)) {\n          console.log(`Tool output: ${update.content}`);\n        }\n      }\n      break;\n    case \"unknown\":\n      console.log(\n        `Unrecognized event: ${event.axonEvent.event_type}`,\n        event.axonEvent.payload,\n      );\n      break;\n  }\n});\n```\n\n**Claude:**\n\n```typescript\nconn.onTimelineEvent((event) =\u003e {\n  switch (event.kind) {\n    case \"claude_protocol\":\n      if (event.eventType === \"assistant\") {\n        process.stdout.write(event.data.content);\n      } else if (event.eventType === \"result\") {\n        console.log(\"Result:\", event.data.content);\n      }\n      break;\n    case \"unknown\":\n      break;\n  }\n});\n```\n\n**Custom events** — use `publish()` to push your own events to the channel. They arrive as `kind: \"unknown\"` timeline events:\n\n```typescript\nimport { tryParseTimelinePayload } from \"@runloop/agent-axon-client/acp\";\n\n// Publish a custom event\nawait conn.publish({\n  event_type: \"build_status\",\n  origin: \"EXTERNAL_EVENT\",\n  source: \"ci-pipeline\",\n  payload: JSON.stringify({ step: \"compile\", progress: 75 }),\n});\n\n// Consume it on the other side\nconn.onTimelineEvent((event) =\u003e {\n  if (event.kind === \"unknown\" \u0026\u0026 event.axonEvent.event_type === \"build_status\") {\n    const status = tryParseTimelinePayload\u003c{ step: string; progress: number }\u003e(event);\n    if (status) console.log(`${status.step}: ${status.progress}%`);\n  }\n});\n```\n\nBoth modules also support pull-based consumption via an async generator:\n\n```typescript\nfor await (const event of agent.receiveTimelineEvents()) {\n  console.log(event.kind, event.data);\n}\n```\n\nSee the [SDK documentation](sdk/README.md#custom-events-via-publish-and-tryparsetimelinepayload) for more on custom events, and the [full timeline API reference](sdk/README.md#timeline-events) for replay behavior and `afterSequence`.\n\nSee the [SDK documentation](sdk/README.md) for the full API reference, or browse the [hosted API docs](https://runloopai.github.io/agent-axon-client-ts/).\n\n## Repository Structure\n\n```\nsdk/                      → @runloop/agent-axon-client (the published npm package)\nexamples/\n  acp-hello-world/        → Minimal ACP single-prompt script\n  acp-cli/                → Interactive ACP REPL\n  acp-app/                → Full-stack ACP demo (Express + React)\n  claude-hello-world/     → Minimal Claude single-prompt script\n  claude-cli/             → Interactive Claude REPL\n  claude-app/             → Full-stack Claude demo (Express + React)\n  combined-app/           → Full-stack combined demo (Claude + ACP, Express + React)\n```\n\n## Development\n\n**Prerequisites:**\n\n- [Node.js](https://nodejs.org) \u003e= 22.0.0\n- [Bun](https://bun.sh) (package manager and task runner)\n\n```bash\nbun install\nbun run build\nbun run test\nbun run check    # lint + format verification\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development workflow, commit conventions, and PR guidelines.\n\n## License\n\n[MIT](LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frunloopai%2Fagent-axon-client-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frunloopai%2Fagent-axon-client-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frunloopai%2Fagent-axon-client-ts/lists"}