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

hc-persistent

v0.1.2

Published

Persistent single-conductor multi-agent Holochain dev tool — like hc-spin but data survives restarts. One conductor, N agents, one unified Playground.

Downloads

81

Readme

hc-persistent

Persistent single-conductor Holochain dev tool — like hc-spin but data survives restarts.

  • 1 conductor (ws://localhost:11111 for Playground) — low RAM vs hc-spin N conductors
  • N persistent agents on that one conductor (ws://localhost:9001,9002,... for UIs) — profile/avatar/post/contract stay after Ctrl+C
  • 1 unified Playground (http://localhost:8282) showing all agents in one graph
  • Holochain 0.6.3 — danger_test_keystore + msgpack admin (no TTY ENODEV)
  • Local bootstrap by default (127.0.0.1:12345/12346 via hc run-local-services) — stays local, no public dev-test-bootstrap2 load (per Paul d'Aoust suggestion)

Install

Quick start (recommended) — via npm/npx:

# inside holochain nix develop (holochain/hc/hc-playground available), make sure bun is on PATH:
npx hc-persistent --happ ./workdir/my-app.happ --agents 4

Or via bun:

bunx hc-persistent --happ ./workdir/my-app.happ --agents 4

From source (for development/contributing):

# inside holochain nix develop (holochain/hc/hc-playground available):
git clone https://github.com/Nuruddindev/hc-persistent ~/hc-persistent
cd ~/hc-persistent
bun install        # or npm install
chmod +x bin/hc-persistent
# optional: link globally
bun link           # or npm link

Requires holochain, hc, hc-playground in PATH (via nix develop from holonix or flake.nix), plus Bun as the actual execution runtime — src/index.ts uses Bun-native APIs (Bun.spawn, Bun.$, Bun.sleep) internally.

You can install/invoke it via either package manager — both end up running the same Bun process:

  • bun: bunx hc-persistent --happ ... or bun run src/index.ts --happ ...
  • npm: npx hc-persistent --happ ... (the bin/hc-persistent wrapper detects it's under plain Node and hands off to bun — make sure bun is on PATH, e.g. via npm i -g bun or the included Nix shell)

Usage

# inside your Holochain app repo (with .happ built):
nix develop
# 2 agents (default):
hc-persistent --happ ./workdir/my-app.happ
# 4 agents (multidevice test):
hc-persistent --happ ./workdir/my-app.happ --agents 4 --app-port 9001 --admin-port 11111
# with env:
HAPP_PATH=./workdir/my-app.happ AGENTS=4 hc-persistent
# clean restart:
hc-persistent --happ ./workdir/my-app.happ --agents 4 --clean
# add agents without wiping (reuse 2, add 2 more):
hc-persistent --happ ./workdir/my-app.happ --agents 4   # Existing apps: skip, new: install

Options:

--agents=<n>         Number of agents on single conductor (default: 2)
--happ=<path>        Path to .happ (default: ./workdir/my-app.happ)
--admin-port=<n>     Single admin port for Playground (default: 11111)
--app-port=<n>       First app port (default: 9001, +1 per agent)
--data-dir=<path>    Persistent dir (default: ./.sandboxes)
--network-seed=<s>   Network seed (default: my-app-seed)
--bootstrap-port=<n> Local bootstrap+signal ports (default: 12345/12346, 0=disable→public, not recommended)
--clean              Wipe persistent data before start
--help

Local bootstrap: default 127.0.0.1:12345 (signal 12346) via hc run-local-services. Gracefully falls back if holonix 0.6.3 lacks that command — single-conductor still works via loopback gossip. Disable with --bootstrap-port=0 (uses https://dev-test-bootstrap2.holochain.org/, not recommended per Holochain team).

After start, open the printed URLs (with token, not plain):

my-app → http://localhost:3000/?app_port=9001&app_api_token=BASE64...
my-app-agent-2 → http://localhost:3001/?app_port=9002&app_api_token=...
Playground: http://localhost:8282 (already connected to ws://localhost:11111)

Vite UIs: UI_PORT=3000 VITE_HC_PORT=9001 vite --port $UI_PORT --strictPort

Web UI signing (browser dev only): Web UIs (Vite, not Tauri/Launcher) must authorize signing via AdminWebsocket before first callZome, or callZome fails no signing credentials. Add to your holochain-app.ts firstUpdated before AppWebsocket.connect:

import { authorizeSigningCredentialsInDev } from "hc-persistent/helpers/dev-signing";
// or copy `ui/src/services/dev-signing.ts` if not using npm
const isDev = import.meta.env.DEV === true;
if (isDev) {
  const adminPort = new URLSearchParams(location.search).get("admin_port") || "11111";
  const appPort = new URLSearchParams(location.search).get("app_port") || "9001";
  const basePort = 9001;
  const idx = parseInt(appPort,10) - basePort;
  const appId = idx <=0 ? "my-app" : `my-app-agent-${idx+1}`;
  await authorizeSigningCredentialsInDev(appId, adminPort);
}

import.meta.env.DEV is true in vite dev and false (tree-shaken) in vite build, so this never runs in production and the browser never tries ws://localhost:11111 in prod.

Data lives in .sandboxes/ (data_root_path + conductor-config.yaml + app-tokens.json). Ctrl+C keeps it. Only --clean or rm -rf .sandboxes wipes it.

How it works

  1. Writes conductor-config.yaml with danger_test_keystore (no passphrase TTY) src/index.ts:230
  2. Spawns holochain -c .sandboxes/conductor-config.yaml
  3. Waits for admin ws://localhost:11111 via net.Socket src/index.ts:85
  4. Connects admin via ws + @msgpack/msgpack WireMessage src/index.ts:103
  5. list_apps → skip existing, else generate_agent_pub_key → install_app {source:{type:"path",value:happ}} → enable_app → attach_app_interface → issue_app_authentication_token (30-day, non-single-use)
  6. Spawns hc-playground ws://localhost:11111 src/index.ts:508 at 8282

Single conductor saves RAM vs hc-spin N conductors. For hc-spin parity, use multi-conductor mode (not default).

Comparison with hc-spin

| | hc-spin | hc-persistent | |---|---|---| | Conductors | N (one per agent) | 1 (N apps) | | RAM | N × holochain | 1 × holochain | | Playground | N ports | 1 port (unified graph) | | Persistence | temp (wiped) | .sandboxes survives | | Add agents | restart all | --agents=5 reuses |

License

MIT