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

@miadi/episode-vessel

v0.1.3

Published

The file law of a chronicle episode folder, written once: bounded contained listing, text read and revision-guarded atomic write, ceremony notes and ceremony file attachments. No HTTP, no React, no service URL — a phone, a Next.js route and a test open th

Readme

@miadi/episode-vessel

The file law of a chronicle episode folder, written once.

What an episode folder contains, which of it may be read, which of it may be written, and how a write is guarded. No HTTP, no React, no service URL, no medicine-wheel client — so a phone process (miadisabelle/gmtermux), a Next.js route handler (jgwill/Miadi) and a test all open the same vessel the same way.

npm i @miadi/episode-vessel
import { listEpisodeFiles, readEpisodeText, writeEpisodeText } from "@miadi/episode-vessel"

// MIADI_CHRONICLE_ROOT, or pass { root }
const files = listEpisodeFiles("2026-09-17-episode-349-miadi-conducts-a-ceremony-its-circle-can-enter")
const note = readEpisodeText(episode, "review-claude-1-260918.md")
writeEpisodeText(episode, "review-claude-1-260918.md", edited, note.revision.sha256)

CommonJS works too — require() of this ESM build is proven on node 24 on both gaia and the Android device.

What it guarantees

  • Containment. An episode is one folder name directly beneath the chronicle root — never a path, never a traversal, never a symlink. A file inside it is a relative path with no ., .. or dot-prefixed segment, resolving after symlink resolution to a real file still inside that folder.
  • A bounded listing. Depth 3, 200 files, dotfiles and episode.yaml excluded. The host's include(relativePath, kind) hook runs before a file consumes the cap, so a hundred capture files cannot hide one artefact.
  • No lost write. writeEpisodeText takes the sha256 the caller was shown. If the file moved, nothing is written and EpisodeConflictError carries the revision on disk. The write itself is a temp file created with wx, the revision re-checked, then rename — a reader never sees half a file.

Kinds

| kind | extensions | previewed | editable | |---|---|---|---| | text | md, txt, yaml, yml, json | yes, to 512 KiB | yes, unless the path says otherwise | | document | html, htm, pdf, csv | no | no | | media | m4a mp3 wav opus aac amr mp4 webm mov mid ogg | by byte range, by the host | no |

document is listed and downloadable but never rendered inline. A vessel's HTML is written by agents; serving it into a page's own origin would make every artefact a script the reader did not ask for. A host that wants to show it does so in a sandbox of its own choosing, deliberately.

Never editable through a browser: episode.yaml (the vessel's identity), guidance documents (AGENTS.md, CLAUDE.md, …), anything under captures/ (bundles carry verified digests — that is @miadi/episode-capture's work) and anything under ceremonies/ (which has its own verbs).

Guidance documents are listed, marked guidance: true. Hiding a file that exists is the worse error.

Ceremonies

ceremonies/<id>/ holds two files, and the two verbs that write notes.md are different on purpose:

  • seedCeremonyNote — write-once. The minted record of who opened the ceremony. If the circle has already written, it is not overwritten; the reason comes back and a correction goes beside it.
  • writeCeremonyNote(content, { expectedRevision }) — the circle's working notes, overwritten under the same guard as any other text file.

listCeremonyFiles / attachFileToCeremony / detachFileFromCeremony keep files.json: which artefacts of this vessel the ceremony was held about. The file must already exist in the same vessel — a ceremony cannot be told it was held about something that is not there.

A ceremony id is either form the wheel emits: a UUID (603bfaa1-958d-42a1-bbdf-a25fc2cfdaae) or a minted id (ceremony:1789863312388:mgj2x). Accepting only one made half the wheel's ceremonies unwritable, which is how this package found out.

Permissions

@miadi/episode-vessel/permissions is a role → capability map as plain data. No identity, no token, no session, no dependency.

import { capabilitiesFor } from "@miadi/episode-vessel/permissions"
const can = capabilitiesFor(person.role, { grants: communityConfig.role_grants })

The capability object decides what is offered. The host's gate decides what is allowed. A surface rendering an edit button for a role without edit is a bug; a route writing because the client claimed a capability is a vulnerability. Both checks exist and neither replaces the other.

Provenance

Lifted from gmtermux:web/pixel/episodes/store.js, the one place this law had been written and proven, and from Miadi:lib/chronicle-vessel.ts, which had copied half of it by hand. Ref jgwill/Miadi#651, and jgwill/Miadi#644 for the same measurement applied to captures.