npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@claxedo/agent-sdk-runtime

v0.8.0

Published

AgentRuntime facade over native SDK harnesses and configured agent connections

Readme

Agent SDK Runtime

@claxedo/agent-sdk-runtime is the embeddable SDK for running agent harnesses behind one host-owned runtime API. Register harnesses, choose a store, create a session, start a turn, and subscribe to events.

Install

npm install @claxedo/agent-sdk-runtime
import { createAgentRuntime } from "@claxedo/agent-sdk-runtime"
import { claude } from "@claxedo/agent-sdk-runtime/harnesses/claude"
import { pi } from "@claxedo/agent-sdk-runtime/harnesses/pi"
import { createSqliteRuntimeStore } from "@claxedo/agent-sdk-runtime/stores/sqlite"

const runtime = createAgentRuntime({
  store: createSqliteRuntimeStore({ root: ".agent-runtime" }),
  harnesses: [
    claude({ access: "native" }),
    pi(),
  ],
})

const session = await runtime.sessions.create({
  directory: "/repo",
  harness: { id: "claude", access: "native" },
  model: { providerID: "anthropic", modelID: "claude-sonnet-4-6" },
  title: "Review",
})

const events = runtime.events.subscribe({ sessionId: session.id })

await runtime.turns.start({
  sessionId: session.id,
  text: "review this repo",
})

The package owns harness process/session orchestration, adapter lifecycle, runtime configuration, model catalogs, MCP resolution, event fan-out, and first-party stores. Hosts still own auth policy, workspace routing, project inventory, HTTP route shape, and UI state.

Agent-First Public Docs

Coding agents and host integrators should start with docs/agent.md, then read docs/concepts.md and docs/architecture.md. Together they define the package job, mental model, blessed imports, stability labels, boundaries, recipes, and public API surface.

Flow

host app
  -> AgentRuntime
  -> harness factory
  -> adapter driver
  -> harness access (ACP / native)
  -> runtime events
  -> runtime.events.subscribe()

The canonical event contract comes from @claxedo/agent-event-runtime. Adapters either emit canonical AgentRuntimeEvent values directly or emit Claxedo client-presentation CompatEvent values when bridging an existing OpenCode surface.

Session Liveness And Turn Outcome

session.status is the current runtime liveness state. It is busy while a turn is running, recovering when a harness is being rebound, error when the session is in an error state, and null or absent when it is idle. It is never done.

The durable result of the most recent turn is session.lastTurn:

session.lastTurn?.status // "completed" | "failed" | "cancelled"
session.lastTurn?.assistantMessageId // assistant row for that completed turn

Render turn-level "Done", "Failed", or "Cancelled" from lastTurn, not from message.time.completed. Message completion is row-level metadata; turn outcome is recorded by the runtime after the harness stream settles. When a UI needs to reconcile an in-flight prompt, compare lastTurn.assistantMessageId with the assistant message id for that prompt; lastTurn.status alone only describes the most recent settled turn. If the host has a higher-level lifecycle such as a Goal or long-running task, use that lifecycle for session-level "working" and "done" badges. Claude SDK, Codex app-server, ACP, OpenCode, and Pi terminal signals all normalize through this runtime/store path. Shell hook integrations remain useful for terminal presence, but they are not the canonical SDK turn outcome source.

Goals

A Goal is a session-level completion condition that may span multiple harness turns. It is a dedicated runtime resource, not a prompt mode: callers use runtime.goals, and adapters must never repair missing support by sending the objective through runtime.turns.start().

const capabilities = await runtime.goals.capabilities(session.id, directory)
if (!capabilities.available) throw new Error(capabilities.unavailableReason)

const started = await runtime.goals.start({
  sessionId: session.id,
  objective: "Ship when verification passes",
}, directory)

const current = await runtime.goals.read(session.id, directory)

HarnessCapabilities.goals is only coarse runtime availability. Always read the detailed Goal capabilities for the materialized session before rendering actions. Pause and Resume form one reversible pair; do not expose either unless both are advertised. Delete is independent. Stop is part of the common Goal lifecycle and disables continuation before interrupting active work.

| Harness | Start authority | Actions | Recovery | | --- | --- | --- | --- | | Codex native | structured app-server Goal RPC | Pause, Resume, Delete | reconcile durable thread state | | Claude native | SDK /goal plus active_goal messages | none | blocked if provider state is lost | | Cursor native | Agent.send("/goal …") plus durable Run state | none | blocked if provider state is lost | | OpenCode native | first-party Session Goal aggregate | Pause, Resume, Delete | reconcile; orphaned execution becomes blocked | | Pi native | owned evaluator and follow-up controller | Pause, Resume, Delete | blocked after non-durable process loss | | ACP | negotiated _meta.goal extension | negotiated subset | negotiated reconciliation |

Goal snapshots report only provider- or controller-owned fields. Optional budgets, usage, iteration, and diagnostic reason fields are not synthesized. After reconnect, refetch runtime.goals.read(); recovery: "blocked" means an active persisted snapshot must become visibly blocked rather than complete.

Layers

Core Runtime

src/index.ts defines the public runtime surface.

  • createAgentRuntime() is the main public entrypoint.
  • runtime.sessions, runtime.turns, runtime.goals, runtime.events, runtime.permissions, runtime.questions, runtime.todos, runtime.commands, runtime.config, and runtime.health are the user-facing resource namespaces.
  • PromptInput is the normalized message submission shape used across transports internally.
  • SessionConfig and SessionConfigUpdate describe harness/model/agent selection as host-visible state.

Adapter classes are implementation plumbing behind harness factories. Public host code should use the runtime facade first.

Stores

First-party stores live on explicit subpaths:

  • @claxedo/agent-sdk-runtime/stores/memory
  • @claxedo/agent-sdk-runtime/stores/sqlite

The root import does not load SQLite.

Harness Factories

Harness factories have individual entries and a convenience aggregate:

  • @claxedo/agent-sdk-runtime/harnesses/acp
  • @claxedo/agent-sdk-runtime/harnesses/claude
  • @claxedo/agent-sdk-runtime/harnesses/codex
  • @claxedo/agent-sdk-runtime/harnesses/cursor
  • @claxedo/agent-sdk-runtime/harnesses/pi

The browser-safe Pi provider/model catalog is available separately at @claxedo/agent-sdk-runtime/pi-catalog; it does not load a harness runtime.

import { acp, claude, codex, cursor, pi } from "@claxedo/agent-sdk-runtime/harnesses"
// Smaller single-harness graph:
import { claude as nativeClaude } from "@claxedo/agent-sdk-runtime/harnesses/claude"

Factories hide adapter class construction and let the runtime inject store and event plumbing.

Harness Metadata

src/harness-types.ts is the source of truth for supported harness ids and access modes.

  • ACP connections: acp(id, { binary, ... }) with access: "acp".
  • Native harnesses: claude, codex, cursor, opencode, and pi with access: "native".
  • Configured providers, including ACP, use an opaque connection id with access: "connection"; they are not added to the native id catalog.

harnessDefinition(), harnessKey(), isAgentHarnessId(), and isAgentHarnessAccess() centralize harness classification so callers do not infer behavior from strings.

Runtime model options come from live, directory-scoped harness queries. Query errors are returned to the caller and an empty result remains empty. The exported SDK model catalog is an explicit reference/validation API; it is not substituted for a failed live query.

Subagent support matrix

Subagent discovery is normalized into durable, parent-scoped host rows. A spawn tool is associated with its row by an explicit toolCallId edge. The host mints childSessionId when it can materialize a readable child Session; provider ids and transcript refs stay opaque and are never treated as Session ids or file paths by the UI.

| Harness | Discovery | Transcript | Child Session | | --- | --- | --- | --- | | Claude native | Agent tool lifecycle | messages | openable after host materialization | | Codex native | collab thread lifecycle | live | openable | | Cursor native | Task result carrying a valid transcript reference | file | conditionally openable after host materialization | | Configured ACP | negotiated ACP lifecycle | provider-dependent | capability-dependent | | Pi model-backed | foreground or background child lifecycle | live | openable | | Pi bare adapter | no subagent capability | none | no subagent row |

Foreground children participate in parent interruption; background children continue independently and remain visible as background work. Child transcripts are read-only conversation surfaces: opening one preserves the parent Session, and repeated activation focuses the existing child surface. Rows with no supported transcript render an explicit unavailable state with no navigation control.

Runtime event streams that expose these rows are scoped and authorized by parent Session. A denied parent subscription returns 403 before replay or live events are attached, so one parent cannot observe another parent's child lifecycle.

Capabilities

src/capabilities.ts describes runtime feature support.

  • HarnessCapabilities is the per-harness session feature matrix returned to hosts and UI.
  • AdapterCapability marks implementation abilities that are not part of the normal session contract, currently runtime-config.
  • hasAdapterCapability() is the safe narrowing helper for optional adapter extensions.

Capability data is explicit. Unsupported operations fail rather than returning synthetic data or events.

Events And SSE

src/runtime-event-hub.ts and src/sse.ts provide in-process fan-out and SSE helpers.

  • RuntimeEventHub is a lightweight pub/sub boundary for runtime events.
  • createAgentRuntime({ subscriberBufferSize, eventDelivery }) bounds each subscriber while allowing the host to authorize every delivered event.
  • createSseReplayBuffer() keeps bounded replay for reconnecting clients.
  • attachSseFanout() bridges a subscribe function into a streaming response with lifecycle cleanup.

These primitives are production-appropriate when each session is pinned to one owner machine and that machine's durable session/message log is the source of truth. Hosts only need external pub/sub when they serve the same session live from multiple processes or machines.

Native Pi

Pi runs as a child process in the session's machine directory, using the pinned 0.85.1 RPC protocol. The shared adapter owns product session lifecycle; Pi owns its native session file, tools, extensions, compaction and context. Each active session has a separate process. Idle processes resume from the same native file. A missing native file is an error, never a replacement conversation.

Use pi({ binary, agentDir }) to select the executable and isolated Pi profile. PI_EXECUTABLE also selects the executable. The host projects credentials into that profile and removes its auth file on disposal. It does not modify the user's own Pi profile. Model options come from get_available_models in Pi. Every session requires a real directory and workspace identity.

Pi's extension questions use the shared question API. Extensions and native tools execute with the machine process's permissions, and project extensions remain subject to Pi's project trust policy. Pi does not provide a permission prompt or native subagent API. Host-provided MCP servers are not automatically loaded by upstream Pi; use a trusted Pi extension when that capability is needed.

MCP Resolution

src/mcp-resolver.ts merges managed MCP state with user-defined MCP servers and converts the result into harness-specific shapes.

  • resolveEffectiveMcp() returns the effective server map plus managed status.
  • toOpencodeConfig() writes the OpenCode config shape.
  • toAcpMcpServers() writes ACP McpServer values.

Managed MCP defaults are intentionally empty today. User MCP config still resolves normally, while managed loops remain explicit no-ops until real managed servers exist.

Command Discovery

src/command-discovery.ts reads command files from configured directories and normalizes them into AgentCommandRow values. Adapters and hosts use it to serve slash-command surfaces without making command parsing part of the core runtime facade.

Adapters

ACP

src/harnesses/acp owns Agent Client Protocol process integration.

  • index.ts implements the ACP harness driver.
  • process.ts manages ACP process lifecycle, prompts, config option probing, permissions, and restart behavior.
  • session.ts translates session load/resume state, mode/model sync, and prompt parts into ACP request content.
  • transport.ts abstracts stdio/http process creation.
  • recovery.ts and title.ts handle recovery metadata and title generation.

ACP adapters should prefer live session config options and only call ACP session-mode APIs when the advertised mode list supports the requested value.

Shared SDK Adapter

src/harnesses/shared contains reusable lifecycle and projection code for SDK-backed transports.

  • sdk-runtime-adapter.ts implements common session storage and adapter behavior.
  • turn-lifecycle.ts owns active-turn cancellation and cleanup rules.
  • turn-projection.ts bridges harness events into runtime/compat output.

SDK adapters should put harness-specific code in their driver and keep shared session semantics in this layer.

Claude SDK, Codex App Server, Cursor SDK

src/harnesses/claude, src/harnesses/codex, and src/harnesses/cursor adapt native SDK or app-server streams into the shared runtime contract through the shared SDK adapter.

These transports query their native SDK or app-server for model options and cache successful results per workspace directory.

Configured connections

External agents are installed through ConnectionProvider implementations. The runtime resolves an explicit connection identity to a trusted descriptor, materializes host-owned secret leases at execution time, and persists only the full AgentExecutionBinding needed to address the session. Unknown, disabled, or stale connections fail closed; there is no built-in external-server default.

ACP is one connection provider. The external OpenCode server protocol lives in the separate @claxedo/opencode-server-adapter package and is composed by host applications like any other installed provider.

Pi

src/harnesses/pi is a built-in native harness. It is useful for placeholder or host-controlled flows where no external agent process owns a real model/config surface.

Host Boundaries

Host packages are responsible for:

  • choosing and constructing adapters
  • resolving directories and workspace ids
  • enforcing auth and operation guards
  • owning HTTP/RPC route shape and status codes
  • persisting sessions, config, and event history
  • publishing global/session events beyond the current process
  • exposing product-specific HTTP routes
  • materializing Agent Plugins, skills, and MCP config outside this package

This package should stay focused on runtime contracts and transport execution.

Adding A Harness

  1. Add the harness to AGENT_HARNESS_DEFINITIONS in src/harness-types.ts.
  2. Decide whether it supports access: "acp", access: "native", or both.
  3. Implement an adapter under src/harnesses/<harness>.
  4. Expose explicit HarnessCapabilities; unsupported operations must be errors.
  5. Implement live model discovery when the harness exposes configurable models.
  6. Add focused adapter tests around session lifecycle, submit, abort, config, and event projection.
  7. Add or update the public factory in src/harnesses/index.ts when the harness should be user-selectable.

Public Entry Points

The package ships public docs under docs/. Use docs/recipes.md for import examples and docs/api.md for the stable root API.

Entry point status:

  • Stable: @claxedo/agent-sdk-runtime, @claxedo/agent-sdk-runtime/capabilities
  • Stable: @claxedo/agent-sdk-runtime/harnesses, @claxedo/agent-sdk-runtime/stores/memory, @claxedo/agent-sdk-runtime/stores/sqlite
  • Advanced: @claxedo/agent-sdk-runtime/adapters, @claxedo/agent-sdk-runtime/subagent-admission, @claxedo/agent-sdk-runtime/message-page @claxedo/agent-sdk-runtime/runtime-event-hub, @claxedo/agent-sdk-runtime/sse, @claxedo/agent-sdk-runtime/mcp-resolver
  • Compatibility: @claxedo/agent-sdk-runtime/compat-events, @claxedo/agent-sdk-runtime/status

@claxedo/agent-sdk-runtime/adapters is public but advanced. Most hosts should use createAgentRuntime() plus harness factories. Use the adapter subpath only when building a workspace host, custom HTTP compatibility layer, or harness integration that needs direct driver lifecycle control.

Handoff-capable custom adapters return an AgentPreparedHandoffSession with an idempotent rollback() and may implement releaseHandoffSource to clean up the old native session only after the target binding commits.

The package publishes built ESM and declaration files from dist. Publish verification hashes the complete reachable declaration closure for every export-map entrypoint, so reviewed type-contract changes must update the API manifest explicitly.

Verification

Run package checks from the package directory:

cd packages/agent-sdk-runtime
bun test src
bun typecheck
bun run build

Do not run tests from the repository root. This workspace guards against root test execution.