JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 414
  • Score
    100M100P100Q103216F
  • License MIT

ACP Kit core runtime: agent profiles, process spawn, ACP connection bootstrap, auth orchestration, host adapters, and session lifecycle on top of @agentclientprotocol/sdk.

Package Exports

  • @acp-kit/core
  • @acp-kit/core/node

Readme

ACP Kit

CI npm version npm downloads License: MIT Node Status

ACP Kit is a runtime for building applications on top of the Agent Client Protocol.

It launches an ACP agent process, manages the protocol connection, handles authentication, exposes host adapters for permissions / files / terminals, and turns raw session/update traffic into normalized turn, message, reasoning, and tool events. Your application chooses an agent profile, attaches a host, opens a session, and consumes stable events.

Why ACP Kit:

  • Stable events over messy session/update. Per-message, per-tool, per-turn events with correlation ids (messageId, toolCallId, turnId) — drive UI state and transcripts without parsing raw protocol traffic.
  • Lifecycle is handled for you. Cross-platform process spawn, startup diagnostics, auth_required retry, session.error surfacing, vendor _meta pass-through, multiple sessions over one agent process.
  • Six common agents, one import. import { ClaudeCode, GitHubCopilot, CodexCli, GeminiCli, QwenCode, OpenCode } from '@acp-kit/core' — or drive any other ACP-capable agent via a custom AgentProfile.

Install

npm install @acp-kit/core

Requires Node.js >= 20.11 and a reachable ACP agent CLI on PATH.

Quick Start

import { createAcpRuntime, ClaudeCode } from '@acp-kit/core';

await using acp = createAcpRuntime({
  agent: ClaudeCode,
  host: {
    requestPermission: async () => 'allow_once',
    chooseAuthMethod:  async ({ methods }) => methods[0]?.id ?? null,
  },
});

await using session = await acp.newSession({ cwd: process.cwd() });

session.on({
  messageDelta:  (e) => process.stdout.write(e.delta),
  toolStart:     (e) => console.log(`\n[tool ${e.toolCallId}] ${e.title ?? e.name}`),
  toolEnd:       (e) => console.log(`[tool ${e.toolCallId}] ${e.status}`),
  turnCompleted: (e) => console.log(`\n(turn ${e.turnId} done: ${e.stopReason})`),
});

await session.prompt('Summarize this repository.');

session.on(...) accepts a camelCase handler map (shown above), a single 'tool.start'-style event type for one listener, or 'event' for the full union. Each callback is type-narrowed. See Getting Started for the full event vocabulary, multi-session use, and how to debug startup / auth failures.

Examples

The repository ships with five runnable examples under examples/. Each one is a standalone npm package that installs the published @acp-kit/core from npm:

Example Runs without an agent installed What it shows
quick-start/ No Minimal single-prompt script.
pair-programming/ No Two sessions in one runtime as AUTHOR + REVIEWER, looping until the reviewer says APPROVED.
mock-runtime/ Yes Self-contained mock ACP server. Use this to see the full event flow without installing an agent.
real-agent-cli/ No Interactive CLI driver for real agents (copilot, claude, codex, gemini, qwen, opencode) with prompts for auth and permission decisions.
web-daemon/ No Tiny node:http + Server-Sent Events demo: POST a prompt, stream normalized events back to a browser.
cd examples/mock-runtime
npm install
npm start

See examples/README.md for details.

What ACP Kit Does

flowchart TB
  P["Your Product<br/>(editor extension &middot; desktop shell &middot; web daemon &middot; CLI)"]
  K["<b>ACP Kit</b><br/>process spawn &middot; auth &middot; session lifecycle<br/>event normalization &middot; host adapters"]
  S["@agentclientprotocol/sdk<br/>JSON-RPC framing &middot; typed payloads"]
  A["ACP Agent CLI<br/>(Claude &middot; Copilot &middot; Codex &middot; Gemini &middot; Qwen &middot; OpenCode)"]
  P -- normalized events --> K
  K -- uses --> S
  S -- stdio --> A

Without ACP Kit, every product that wants to host an ACP agent has to write the same plumbing: pick the right CLI for the platform, spawn it without breaking on Windows shells or login envs, surface stderr when it fails to start, run initialize, retry session/new after auth_required, expose host capabilities only when the application actually backs them, parse session/update notifications into something a UI can render, and decide when a turn is really done.

ACP Kit packages all of that behind createAcpRuntime({...}).newSession({ cwd }) (or the runOneShotPrompt one-shot helper). The agent stays a regular ACP server; your application stays a regular consumer of typed events. See Architecture for the layer breakdown.

API Overview

RuntimeSession emits normalized RuntimeSessionEvents: stable per-message, per-tool, and per-turn events with correlation ids (messageId, toolCallId, turnId). They drive transcripts, UI state, and multi-agent orchestration. If you need raw protocol traffic (debuggers, protocol bridges), composeWireMiddleware / normalizeWireMiddleware let you observe the exact JSON-RPC frames.

Create the runtime with an agent profile and a host that implements only the capabilities your application backs:

import {
  createAcpRuntime,
  ClaudeCode,
  type RuntimeHost,
  type AgentProfile,
} from '@acp-kit/core';

await using acp = createAcpRuntime({
  agent: ClaudeCode,           // built-in constant, or a custom AgentProfile literal
  host: {
    requestPermission: async (req) => 'allow_once',
    chooseAuthMethod:  async ({ methods }) => methods[0]?.id ?? null,
    // readTextFile / writeTextFile / createTerminal+friends are advertised to
    // the agent only when you provide them. See docs/api-overview.md.
  } satisfies RuntimeHost,
});

Then open a session, subscribe to events, send prompts:

await using session = await acp.newSession({ cwd: '/path/to/workspace' });

session.on({
  messageDelta:  (e) => process.stdout.write(e.delta),
  toolStart:     (e) => console.log(`[tool ${e.toolCallId}] ${e.title ?? e.name}`),
  toolEnd:       (e) => console.log(`[tool ${e.toolCallId}] ${e.status}`),
  turnCompleted: (e) => console.log(`done: ${e.stopReason}`),
});

const result = await session.prompt('Refactor utils.ts'); // Promise<PromptResult>
await session.cancel();        // optional: cancel the in-flight turn
// session and runtime are disposed automatically by `await using`

Lifecycle helpers: acp.shutdown() (explicit teardown), acp.reconnect() (drop the agent process and reconnect), session.setMode(modeId) / session.setModel(modelId) (switch mid-session when the agent advertises options). One-shot helper: runOneShotPrompt({ agent, cwd, prompt }) yields RuntimeSessionEvents and disposes everything when iteration completes.

The full surface is exported from a single entry point: @acp-kit/core. See API Overview for the complete RuntimeHost, AcpRuntime, RuntimeSession, and RuntimeSessionEvent reference.

Supported ACP Agents

ACP Kit can drive any agent that speaks the Agent Client Protocol over stdio. Six agents ship as named constants you import and pass as agent: <Constant>:

Agent Constant
Claude Code ClaudeCode
GitHub Copilot GitHubCopilot
Codex CLI CodexCli
Gemini CLI GeminiCli
Qwen Code QwenCode
OpenCode OpenCode

The runtime treats every agent uniformly: features like session/load, setMode, setModel, session/list, file system, and terminal capabilities are forwarded to whichever agent advertises them in its initialize response. Inspect acp.agentCapabilities after the runtime is ready to see exactly what a given agent CLI version supports.

To override one field on a built-in profile (e.g. agent: { ...ClaudeCode, env: { ANTHROPIC_API_KEY } }) or to drive a brand-new agent via a custom AgentProfile literal, see Supported Agents for per-agent details (command/args, login flow, known quirks).

How It Compares to @agentclientprotocol/sdk

ACP Kit is built on top of @agentclientprotocol/sdk, not as a replacement.

  • @agentclientprotocol/sdk is the protocol toolkit. It gives you ClientSideConnection, ndJsonStream, typed request/response/notification payloads, and JSON-RPC framing — once you already have a connection to an ACP server.
  • ACP Kit is the client runtime. It launches the agent, manages the connection lifecycle, runs auth, exposes host adapters, normalizes raw protocol updates into stable events, and tracks turn state.

The protocol layer underneath stays exactly @agentclientprotocol/sdk. ACP Kit does not fork it, replace it, or hide it — it depends on it as a regular npm dependency. For the full layered diagram and side-by-side code comparison, see SDK vs Runtime.

Compatibility

Dependency Version
@agentclientprotocol/sdk ^0.18
Node.js >= 20.11 (matches the package's engines field; CI tests Node 20 and 22)
TypeScript (consumers) >= 5.2 (for using / await using syntax)
OS Windows, macOS, Linux

ACP Kit aims to track the latest stable @agentclientprotocol/sdk minor release. Breaking changes in the SDK will be matched by a minor or major bump in @acp-kit/core while v0.x is in effect.

Status

ACP Kit is experimental (v0.x). The public API may change between minor versions until v1.0; every breaking change is called out in CHANGELOG.md. See docs/migration-plan.md for incremental adoption.

Documentation

Development

npm install        # install workspace deps (packages/core only)
npm run build      # tsc -b packages/core
npm test           # vitest run

To try an example: cd examples/mock-runtime && npm install && npm start.

Contributions are welcome. Please open an issue to discuss non-trivial changes before sending a PR.

License

MIT