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

durable-harness

v0.0.2

Published

Durable coding-agent harnesses (Claude Code, Codex, OpenCode, Pi) on a Workflow SDK World: the session is a run, its event log the source of truth, and a crash resumes the turn from the log on another machine.

Readme

durable-harness runs coding-agent harnesses (Pi, OpenCode, libfx's fx, Claude Code and Codex) as durable agents on a Workflow SDK World. Each session is a workflow run: its conversation, the turn in flight and every model and tool call are in the run's event log, so a crash anywhere resumes the turn from the log on another machine, and a tool call that isn't safe to repeat is never run twice.

[!NOTE] durable-harness is experimental: it's on 0.0.x, and its API may change between releases.

Quick start

Install it with a harness, here Pi with pi-durable, in a Next.js app:

npm install durable-harness @earendil-works/pi-durable @earendil-works/chord @earendil-works/pi-ai just-bash

Open Pi's own durable Harness on a World-backed storage. Agents are tool-less by default; Pi's coding tools go on a virtual workspace, whose files live in the session's log:

// lib/agent.ts
import { BACKGROUND_CONTEXT as ctx } from '@earendil-works/chord/context';
import { createRegistry, Harness, type Storage } from '@earendil-works/pi-durable';
import { CodingTools, GATEWAY_PROVIDER, gatewayModels, resumeWith, virtualEnv } from 'durable-harness/pi-durable';

const models = gatewayModels();
const registry = createRegistry();
registry.install(CodingTools);

export const agent = { model: { provider: GATEWAY_PROVIDER, modelId: 'anthropic/claude-sonnet-4.5' } };
export const open = resumeWith((storage: Storage) => Harness.open(storage, { models, registry, env: virtualEnv() }, ctx));

Serve it from a chat route, and configure the integration:

// app/api/chat/route.ts
import { chatRoute } from 'durable-harness/pi-durable';
import { agent, open } from '@/lib/agent';

export const { GET, POST } = chatRoute({ open, agent, authorize: async (request) => { /* your auth */ } });
// next.config.ts
import type { NextConfig } from 'next';
import { withDurableHarness } from 'durable-harness/next';

const nextConfig: NextConfig = {
  // your existing config
};

export default withDurableHarness(nextConfig);

withDurableHarness discovers modules that export agents created at module scope with durableAgent, claudeCode, codex, opencode or pi, and modules that register a pi-durable opener with resumeWith. A script that creates an agent for itself, an exported factory that creates one later, and code samples in strings or comments are excluded. Import aliases, default exports, export lists, and containers or accessors for an existing agent are supported. For custom factories or effect-only agent registration, list the modules explicitly: withDurableHarness(nextConfig, { agents: ['lib/agent.ts'] }).

Choose your harness and framework in the agent harnesses docs.

Harnesses

  • Pi: durable-harness/pi-durable (recommended: Pi's own durable Harness on a World), or durable-harness/pi.
  • OpenCode: durable-harness/opencode.
  • fx: durable-harness/fx, libfx's kernel tools for its own durable agents.
  • Claude Code and Codex: durable-harness/claude-code and durable-harness/codex. They run only in the session's own Vercel Sandbox, never in a shared Function (why).

Model-chosen commands and files run on a virtual workspace (virtual()) or in the session's own Vercel Sandbox (sandbox()), never on the machine that drives the session. See tools and security.

Sending messages

A message goes to a session as one of three kinds: prompt (the default), followUp or steer (sessions.send(sessionId, text, kind), or a chat route's POST kind). On an idle session, each kind starts a turn. When a message arrives while a turn is running, what happens depends on the harness:

| Harness | steer during a turn | prompt or followUp during a turn | | --- | --- | --- | | Pi (durable-harness/pi-durable and durable-harness/pi) | Goes into the running turn after its current tool calls (Pi's steer). | Joins the running turn while Pi is still working on it (Pi's followUp). Pi answers it after the turn's own answer, before the turn ends, so the turn's stream carries both answers and ends once. One that arrives as Pi is finishing gets a turn of its own. | | OpenCode | Goes into the running turn at OpenCode's next step. | Waits for the turn to end, then starts its own turn. | | fx | Goes into the running turn at its next model request. | Waits for the turn to end. Messages that waited together then start one turn. | | Claude Code | Goes into the running turn, at priority next. | Waits for the turn to end, then starts its own turn. | | Codex | Goes into the running turn (turn/steer). If Codex has just ended its turn, the steer runs next, in the same turn. | Waits for the turn to end, then starts its own turn. |

On every harness, prompts and follow-ups are answered in the order they were sent, after the turn that was running. The difference is whether a prompt sent during a turn becomes part of that turn, as on Pi, or gets a turn of its own. Pi's agent can only queue mid-turn input as a steer or a follow-up, and Claude Code, Codex and OpenCode take only steers into a running turn.

Run anywhere

Local development uses the Workflow SDK's local World with no configuration. Deploy to Vercel for managed storage, queuing and scaling, with sessions in Agent Runs. To self-host, use the Postgres World or any other World: see self-hosting.

Contributing

Contributions are welcome. Use issues to collaborate with the team, and read CONTRIBUTING.md before opening a pull request.

Security

If you find a security vulnerability in durable-harness, disclose it responsibly instead of opening a public issue.

To participate in our Open Source Software Bug Bounty program, please email [email protected]. We will add you to the program and provide further instructions for submitting your report.