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

@earendil-works/pi-protocol

v0.84.0

Published

Transport-neutral CBOR protocol for remote pi sessions

Readme

@earendil-works/pi-protocol

Runtime-neutral schemas, types, CBOR encoding, and byte-stream framing for the experimental pi protocol.

Protocol version 1 uses binary messages with this wire layout:

  1. A four-byte unsigned big-endian payload length.
  2. One definite-length CBOR item containing the message.

The first client message is always hello, containing PROTOCOL_VERSION. Subsequent messages use correlated request/response envelopes and server event envelopes. Session and server snapshots are authoritative. Progress events are transient UI hints and must not be reduced into authoritative state. Transports complete authentication before protocol bytes are exchanged.

Session lists contain SessionMetadata, the normalized durable metadata available without acquiring a session runtime. Only id and createdAt are required; updatedAt, parentSessionId, sessionName, and cwd are included when supported by the backing store. Runtime state such as phase, model, thinking level, attachment, and locking appears only in an acquired SessionSnapshot.

Validated message API

encodeClientMessage() and encodeServerMessage() validate a message and return a complete framed Uint8Array. The incremental decoders accept arbitrary fragmentation or coalescing, so they work with streams, sockets, and custom byte transports.

import {
  PROTOCOL_VERSION,
  createServerMessageDecoder,
  encodeClientMessage,
  type ClientHello,
} from "@earendil-works/pi-protocol";

const hello: ClientHello = {
  type: "hello",
  version: PROTOCOL_VERSION,
};

transport.send(encodeClientMessage(hello));

const decoder = createServerMessageDecoder({ maxFrameLength: 1024 * 1024 });
for (const message of decoder.push(incomingChunk)) {
  handleServerMessage(message);
}
decoder.end(); // Call when the byte stream closes to detect truncation.

ClientMessageDecoder and ServerMessageDecoder are also available directly. Schema violations, malformed CBOR, and invalid framing throw ProtocolValidationError. Validation errors do not retain rejected payloads.

parseClientMessage() and parseServerMessage() only validate already-decoded values. They do not parse JSON strings.

Transport support

Every transport carries the same complete bytes: [uint32-be CBOR length][CBOR payload]. Transports may split or coalesce those bytes arbitrarily.

This package does not bundle a transport. Consumers provide a byte-stream transport that preserves byte order and reports stream closure. Custom transports must handle arbitrary frame fragmentation and coalescing.

All transports are untrusted. Configure matching frame limits and enforce access controls appropriate for the transport before exposing a connection to the protocol. Unix sockets can use filesystem permissions, while network transports can authenticate during connection establishment.

Encoding and framing

encodeCbor() and decodeCbor() implement the protocol's strict RFC 8949 subset. encodeFrame() and FrameDecoder handle framing independently of schemas and CBOR.

The CBOR subset supports:

  • null and booleans
  • finite numbers, with integers restricted to JavaScript's safe range and non-integers encoded as float64
  • UTF-8 strings
  • Uint8Array byte strings
  • definite-length arrays
  • definite-length maps represented by objects with unique string keys

Undefined object properties are omitted. JSON-valued protocol fields reject CBOR byte strings and non-plain objects. Top-level undefined, undefined array entries, sparse arrays, non-finite or unsafe numbers, tags, indefinite-length items, malformed UTF-8, trailing data, excessive nesting, and oversized values are rejected.

Default limits are 16 MiB per CBOR payload/frame, 1,000,000 array elements or map entries, and 64 nested item levels. Options can configure these limits. A frame decoder validates the declared length before buffering payload bytes.

All schemas reject unknown object properties. The protocol is experimental and has no compatibility guarantees.