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

@crow-agent/client

v0.2.0

Published

Client library for connecting to a Crow server over the wire protocol.

Downloads

429

Readme

@crow-agent/client

Client for the Crow service protocol. It is transport-neutral: you supply a ByteTransportFactory that moves ordered bytes, and the client handles the handshake, request correlation, attachments, and subscriptions on top.

import { Client, type ByteTransport, type ByteTransportFactory } from "@crow-agent/client";

async function openTransport(handlers): Promise<ByteTransport> {
  // Wire up a WebSocket, Unix socket, or any ordered byte channel here.
  return {
    send: async (chunk) => {
      // write bytes in call order, honoring backpressure
    },
    close: () => {},
  };
}

const transportFactory: ByteTransportFactory = (handlers) => openTransport(handlers);

const client = await Client.connect({
  serverId: "01234567-89ab-4def-8123-456789abcdef",
  transportFactory,
});
const hello = client.hello;
if (!hello) throw new Error("handshake did not complete");

const result = await client.request(
  { serverId: hello.serverId },
  { serviceId: "example.service", member: "read", args: [] },
);

During connect() the client confirms the physical endpoint reports the expected logical serverId. Server-wide requests carry that id; every session request carries the full live target { serverId, sessionId, attachmentId }. That combined durable address rules out cross-server and cross-session misrouting, and the server-issued attachment id discards stale frames after a switch or reattach.

A factory opens one fresh authenticated connection per attempt. Requests are matched by id, and server-side failures surface as ServerError.

Services and subscriptions

Typed server and session APIs come from Chord service bindings owned by the application — never from this package. createClientServiceTransport() adapts a lazily resolved server or session route into a Chord transport, while request() and subscribeService() stay the low-level primitives. Chord provides the service-control parsers and the per-subscription state decoder; @crow-agent/protocol only validates the routed envelope and the strict-JSON boundary.

Subscribing to a service first yields a complete provider snapshot. The binding installs that snapshot, then calls start() to release updates buffered during hydration. Client applies ordered out-of-band attachment changes but does not build typed service proxies or interpret application contracts, so observation APIs such as the coding agent's transcript stay ordinary Chord services whose snapshots and updates pass through untouched.

Disconnects

On disconnect or disposal, in-flight requests fail locally, although accepted work may still finish remotely before the attachment is released. The client drops its live attachment route and never reconnects or replays requests on its own. To resume: call reconnect(), attach again through the application's management service, and explicitly repeat only the operations known to be safe.

The local coordinator only offers a stable endpoint and relays traffic. Replaceable server processes own session and worker lifecycle outside the public client protocol.

Transport handler contract

Drive the handlers your factory receives like this:

  • handlers.onData(chunk) — inbound bytes arrived;
  • handlers.onClose() — the transport closed in an orderly, terminal way;
  • handlers.onError(error) — the transport failed.

Unix-domain sockets

Node.js and Bun consumers can use the dedicated Unix transport instead of writing a factory:

import { Client } from "@crow-agent/client";
import { createUnixTransportFactory } from "@crow-agent/client/unix-transport";

const client = new Client({
  serverId: "01234567-89ab-4def-8123-456789abcdef",
  transportFactory: createUnixTransportFactory({ path: "/tmp/crow.sock" }),
});
await client.connect();

discoverUnixServers() scans an explicit physical-route directory, derives each expected server id from its filename, and confirms it with the usual handshake:

import { discoverUnixServers } from "@crow-agent/client/unix-transport";

const routes = await discoverUnixServers({ directory: "/run/user/1000/crow" });
// [{ serverId: "...", path: "/run/user/1000/crow/<serverId>.sock" }]

Malformed entries, non-sockets, stale or silent endpoints, and server-id mismatches are skipped. Discovery is read-only and probes at most 16 sockets at once; unexpected filesystem and socket errors fail the whole discovery run. Pass timeoutMs to change the default probe timeout.

ClientOptions.maxFrameLength caps protocol payloads and maxPendingBytes caps queued Unix transport output. Set matching limits on both peers.