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

@supersuit/self-md

v0.1.0

Published

A written standard for the folder that holds everything about one person (self/), with a lint that enforces it and a sweep that derives which tools read each file.

Readme

@supersuit/self-md

A written standard for the folder that holds everything about one person (self/), with a lint that enforces it and a sweep that derives which tools read each file.

Zero dependencies. Node 20 or later. Use is governed by the retained license.

30 seconds

npm install @supersuit/self-md
npx self-md lint --workspace .
npx self-md undeclared --workspace . --root ./skills
npx self-md stamp --workspace . --root ./skills --write

The standard

A workspace is a folder. self/ inside it holds everything about the person the workspace belongs to, and self/self.md is the one screen an agent reads first.

Facets

Each facet is a folder under self/ that answers one question.

| Facet | Answers | | --- | --- | | voice/ | How do they write and speak? | | calling/ | What are they for, and what are they aiming at? | | personality/ | What are they like, by evidence? | | values/ | What do they hold to? | | faith/ | How do they walk with God? | | journal/ | What are they thinking and dreaming, in their own words? | | body/ | How is their body, and what are their rules for it? | | story/ | The record of their life: events, press, pictures. | | taste/ | What do they love and choose? | | daily/ | What is today's plan? | | log/ | What happened, dated, month by month? |

Files allowed at the root of self/: self.md, story.md, identity-map.md, README.md.

Anything else is declared in self/README.md, one bullet per name, with what it is for:

## Facets
- craft/: what am I building with my hands?

## Root files
- GROUNDING.md: what keeps me steady

self.md

---
kind: self
id: ann-lee
name: Ann Lee
summary: Ann, on one screen.
read_when: every session
as_of: 2026-10-08
keep: home
---

# Ann Lee
...
  • Required, non-empty: kind (must be self), id, name, summary, read_when, as_of, keep.
  • Refused: title (the name is name:) and last_verified.
  • The body is at most 60 non-empty lines.

What the lint reports

| Rule | Meaning | | --- | --- | | self-missing | There is no self/self.md. | | self-header | A required key is missing or empty, kind is not self, or a refused key is present. | | self-length | The body is over 60 non-empty lines. | | self-undeclared | A folder or file at the root of self/ is neither a default nor declared, or is a dangling symlink. | | self-outside | A collection about the person (dreams/, prayers/, ...) sits in documents/collections/ instead of under its facet. |

reads: and read_by

A reader (a skill, an app, a script) declares the workspace paths it depends on. Each source's read_by: is then derived from those declarations, never kept by hand.

A skill declares in its SKILL.md frontmatter:

---
name: dream-processor
reads:
  - "self/journal/dreams/: files each dream here"
---

Anything else declares in a manifest named .reads.json or .freedom-reads.json (both are read; the second is the original name and stays supported):

{ "reader": "journal-app", "reads": [{ "path": "self/journal/", "use": "the nightly export writes here" }] }

stamp --write puts the derived block at the top of each source's frontmatter. A folder stamps its README.md; a .md file stamps itself; any other file is reported unstampable.

---
read_by:
  - "dream-processor: files each dream here"
read_by_generated: true
---

read_by_generated: true is what marks the block as derived. A read_by: without it is hand-kept and is never touched. A generated block whose path no reader declares any more is cleared, which is why stamp --write must be given every reader root and refuses to run with none.

undeclared scans the reader roots for any file that names a workspace folder under self/, documents/collections/, people/, projects/ or setup/ without a declaration covering it. A mention counts at a path boundary (myself/journal/ is not self/journal/), after ./ or ../ only inside the workspace itself, and after the workspace folder's own name from anywhere.

Library

import { lintSelf, collectReads, stampReadBy, undeclaredReaders } from "@supersuit/self-md";

const findings = lintSelf("/path/to/workspace");
// [{ rule, path, message, severity }]

const reads = collectReads(["/path/to/skills", "/path/to/app"]);
// [{ reader, path, use }]

const plan = stampReadBy("/path/to/workspace", reads, { write: true });
// [{ target, lines, missing?, handKept?, unstampable?, cleared? }]

const loose = undeclaredReaders("/path/to/workspace", ["/path/to/skills"]);
// [{ file, path }]

Every default can be overridden without changing it for anyone else:

lintSelf(root, {
  facets: { ...FACETS, craft: "What do I make?" },
  rootFiles: ROOT_FILES,
  personCollections: { dreams: "journal" },
  collectionsDir: "documents/collections",
  screenLines: 60,
});
undeclaredReaders(root, roots, { scan: ["self", "notes"], deep: ["self"] });

Also exported: FACETS, ROOT_FILES, PERSON_COLLECTIONS, REQUIRED_KEYS, REFUSED_KEYS, SCREEN_LINES, MANIFEST_NAMES, SCAN_FOLDERS, DEEP_FOLDERS, selfFacetFor(root, facet), declaredExtras(root), readHeader(text) and isMain(import.meta.url).

CLI

self-md lint --workspace DIR [--json]
self-md stamp --workspace DIR --root DIR [--root DIR ...] [--write] [--json]
self-md undeclared --workspace DIR --root DIR [--root DIR ...] [--json]
self-md --help

Exit codes: 0 clean, 1 findings (a lint error, an undeclared mention, or a stamp target that is missing or hand-kept), 2 usage error. --json prints one JSON object instead of tab-separated lines.