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

@flashyos/shiplog

v0.1.0

Published

shipped/1 — the past tense of a record. One sealed entry per thing that shipped, emitted per repository and merged into one cross-repository calendar, changelog and attribution report. Verifiable offline; the past is append-only.

Readme

@flashyos/shiplog

shipped/1 — the past tense of a record.

The work layer already requires evidence: an initiative task cannot be completed without an evidenceUrl, and the settlement receipt seals it. But the evidence is a string somebody pasted. It is not attributed, not hashed, and not checkable by the counterparty being asked to believe it. A receipt that seals an unverifiable URL proves that a URL was pasted.

shipped/1 is the substrate that evidence was always supposed to point at. One sealed entry per thing that reached the branch that deploys — dated, attributed to the agents and humans who did it, emitted by the repository that shipped it, merged across a portfolio.

npm i @flashyos/shiplog

Two things fall straight out of the shape

The calendar is a projection, not a service. A merged shiplog sorted by at is the cross-repository calendar. There is nothing to integrate with: a portfolio company publishes one file and appears in it.

Agent authorship becomes a measured fact. by carries Directory node ids, and an agent id is as first-class as a person's. The share of shipping done by agents stops being a claim in a deck and becomes a number anyone can recompute from published documents — which is the only form of that number worth quoting.

Use it

import { seal, verifyEntry, merge, view, calendar, changelog, attribution, fromCommits } from '@flashyos/shiplog'

// Derive from the history you already have. Everything lands private.
const { entries, unmapped } = fromCommits(parseGitLog(gitOutput), {
  repo: 'repo/flashyos',
  assertedBy: 'agent/flashyos-ci',
  defaultAuthor: 'person/michael',
  authors: { '[email protected]': 'agent/flashyos-builder' },
  prBase: 'https://github.com/FlashyLabs/flashyos/pull/',
})
unmapped  // git emails no mapping covered — fix these, don't ignore them

// Many repositories, one record.
const { shiplog, problems } = merge([fragmentA, fragmentB, fragmentC])

calendar(shiplog.entries, { grain: 'week', includeEmpty: true })  // the calendar
changelog(shiplog.entries, { from: '2026-07-01T00:00:00Z' })      // the changelog
attribution(shiplog.entries).agentShare                            // 0.62, and recomputable
verifyEntry(entry)                                                 // { ok, claimed, recomputed }

The seal

An entry's digest is sha256 over its own canonical form with digest removed, through @flashyos/verify — the same canonicalisation that seals every settlement in the estate. Never a second one: a second canonicalisation is a way to make honest records look forged.

Change the title, the date, the authors or the refs and the digest moves. That is what makes an entry quotable: a settlement receipt can carry the digest, and anyone with the published fragment recomputes it offline without asking us anything.

The past is append-only. A wrong entry is superseded by a new one pointing back at it, never edited — an edited entry has a different digest, and every receipt that quoted the old one stops verifying. current() is the view that hides superseded entries; the log keeps them.

The asymmetry with backlog/1

A backlog item decays and is never sealed. A ship entry is sealed and never decays.

That is not an inconsistency, it is the difference between the two tenses. An intention stops being evidence of anything once nobody has restated it; a fact about the past does not become less true because time passed. What the past needs is not a decay window but a hash, so nobody can revise it quietly.

Saying what a commit was

A derived log is only as good as what it can read off a subject line, and most good repositories do not write feat:. The precedence chain, most authoritative first — every step above the last is something somebody said:

  1. .shiplog/kinds.json — a person's decision, by sha
  2. Kind: docs in the commit body — the author saying it outright
  3. A conventional-commit type
  4. "lexicon": "imperative" in the config — your own declared convention
  5. other — we could not tell

The lexicon is opt-in on purpose. Declare nothing and anything unprefixed stays other, because reading a convention nobody declared is guessing. Ambiguous verbs go to infra, never feature: a chore filed as a feature inflates the only number most readers look at.

Merges of another branch into your line are dropped — that is not a thing that shipped — and a project prefix like Phase 3: is looked past to the verb behind it.

For the entries nothing can read:

npx flashy-shiplog unread shiplog.fragment.json --draft .shiplog/kinds.json

Every value in that draft is other, never a guess. A draft pre-filled with plausible answers is one that gets accepted unread.

The command line

flashy-shiplog check     <file|dir>            validate and re-verify every seal
flashy-shiplog merge     <file|dir> [--tier T] [--out F]
flashy-shiplog calendar  <file|dir> [--grain day|week|month] [--from D] [--to D]
flashy-shiplog changelog <file|dir> [--from D] [--to D]
flashy-shiplog velocity  <file|dir> [--grain G] [--periods N]
flashy-shiplog who       <file|dir>            who did the shipping
flashy-shiplog summary   <file|dir>
flashy-shiplog unread    <file|dir> [--draft F]   what the classifier could not read
flashy-shiplog pilot     [--minutes N]           the four numbers, from this repository

pilot reads this repository's own fragment and config and prints a report: how much history the format saw, how much of it no convention could read, the share carrying an agent author, whether it is reachable, and how much is published. Nothing is sent anywhere — it is yours to keep or paste back.

Paths, not a base URL. Every number it prints is recomputed from the documents in front of it — a reader who does not trust us runs the same command.

Adopt it in one command

npx @flashyos/shiplog adopt

Reads the repository — its remote, its AAO charter if it has one, and which directory it actually serves from — then writes .shiplog/config.json, vendors the dependency-free emitter, and adds a workflow that keeps the log current. It tells you every decision it made and why, including the ones you should check.

Adopting publishes nothing. Everything derived lands private, so the served fragment is empty until somebody decides otherwise. That decision is one field in the config, and it is meant to be a decision.

The served copy is always the public projection. The emitter writes it, not a copy step in a workflow — a step can be forgotten, and forgetting this one would publish private entries at a URL. partner is excluded too: a partner-tier entry behind no gate is a public entry with a misleading label.

| Repository shape | Where the public projection lands | |---|---| | Next app, or a static builder with a public/ | public/.well-known/shiplog.json | | Monorepo with a marketing app | apps/marketing/public/.well-known/shiplog.json | | Serves its dot-directory through a rewrite | well-known/shiplog.json — and you add the rewrite | | No site at all | nowhere; the fragment sits at the repository root and is merged from a checkout |

No toolchain? vendor-shiplog.mjs

A single dependency-free ESM file. Copy it into any repository — including one with no package.json — and it derives, seals and emits a valid fragment from git log with node alone.

node vendor-shiplog.mjs emit --since 2026-01-01   # → shiplog.fragment.json
node vendor-shiplog.mjs verify shiplog.fragment.json

It reads --first-parent, so an entry is a merge to the deploy branch rather than every commit: a log of every keystroke is technically accurate, unreadable, and turns a velocity chart into a measure of typing. It lands everything private, so a first backfill over a decade of branch names is never an unreviewed disclosure.

src/vendor.test.ts asserts the vendored canonicalisation produces byte-identical digests to this package. A copy that seals almost the same way produces entries that fail verification for everyone else — which would surface as "your changelog is forged" rather than as a bug in a script.

Licence

Apache-2.0. The spec and the clients are permissive on purpose — a standard nobody can embed is not a standard.