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

@eriknaslund/skiss

v0.6.1

Published

A text notation for sketching data models, compiled to LinkML

Readme

Skiss

Sketch a data model as fast as someone can describe it. Compile it to LinkML when it becomes real.

Skiss is Swedish for sketch.

Character @Catalog                      # a person or droid in the archive
  id*
  name
  homeworld: Planet
  films: Film[]
  popularityRank: int @Community

Planet @Catalog
  id*
  name
  climate: arid|temperate|frozen|unknown

CharacterPage @Community ~ Character    # the community wiki's version
  slug*
  characterId = Character.id
  summary                               # free text, written by editors

That is the whole language. Classes at column 0, fields indented under them, a handful of punctuation marks.

Why

You sit down with someone who knows the domain. Within the hour you want a shared picture of it: what the things are, what they are called, which system owns them, how they hang together.

The whiteboard is the best tool we have for that hour, and it is still not good enough. Redrawing an arrow is slow when the other person is mid-sentence. Half of what gets said never reaches the board. And when the hour is over, the picture stays on the wall, or in a photo nobody opens again.

The tools that outlive the hour are worse at the hour itself. A schema language (LinkML, JSON Schema, SQL) wants answers you do not have yet: required or optional, which pattern, what base URI. A diagram tool wants you to drag boxes. Both make you stop talking to operate the tool.

Skiss is text you can type while someone talks. A field is one line. A change is one edit. A diagram renders live from the text, so the picture on the screen is always the current picture, and when the hour is over you have a file, not a photo. When the model is real, it compiles to LinkML and you carry on there.

The rules that make it fast

  • A colon means "the type matters here". No colon means no type yet; it compiles to string and you fix it later. This is what lets you write a field without stopping to think.
  • What you leave out means "not yet". Never "unknown", never "none". A sketch is silent about what you do not know.
  • @Catalog says which system owns a thing. On a class, or on a single field when the box is really a view over two systems.
  • ~ and = are two different statements. ~ says two classes are about the same thing. = says which field joins to which. The first is a domain conversation, the second an integration conversation.
  • < inherits, once. Jedi < Character on the class line: the child has everything the parent has and adds its own. One parent, no mixins; it compiles to is_a.
  • # describes, ? doubts. A description ends up in generated documentation. A doubt never does.
  • Names are ASCII. A–Z, a–z, 0–9, and nothing else: a name becomes an identifier and a URI in LinkML, a class in generated Python, a node in a diagram, and none of those take the rest of the alphabet. The words of the domain, in whatever alphabet they are spoken, go in the # description (SPEC §4).
  • Every line stands on its own. A half-typed line breaks that line and nothing else, so the diagram keeps rendering while you type.
  • Everything you can write compiles to valid LinkML. Skiss is a strict subset. Nothing is lost on the way up.

What it is not

  • Not a schema language. No required/optional, no cardinality beyond [], no constraints. LinkML has all of that, and that is where you go when you need it.
  • Not an integration diagram. It says where things live, not how they sync.
  • Not a layout format. Positions belong to whatever draws the picture, never to the text.

Using it

npm install -g @eriknaslund/skiss
skiss diagram model.skiss

Or without installing: npx @eriknaslund/skiss diagram model.skiss.

skiss diagram writes a Mermaid class diagram to standard output; -o diagram.mmd writes it to a file, --notes includes the ? doubts as notes, and - reads standard input. Anything the file gets wrong is reported on standard error, one line each, and the diagram is still drawn from the lines that parse. --strict makes that a non-zero exit. skiss --help lists the rest.

skiss render model.skiss -o model.svg writes a picture rather than the Mermaid text. A class diagram is laid out in a browser, so this one command needs a browser: it delegates to the official Mermaid CLI, which you install yourself with npm install -g @mermaid-js/mermaid-cli. Nothing in the package or the library depends on it, and skiss render says that line and exits 2 when it is not there. The format is the extension of -o — .svg or .png — and --format svg|png overrides it; with no -o the SVG goes to standard output, and a PNG always needs an -o. --scale is what the PNG is rasterised at and defaults to 2; --notes, --strict and the diagnostics work as they do for diagram. When mmdc itself fails, its exit status is the command's.

skiss compile model.skiss writes a LinkML schema instead, as YAML on standard output. --json writes the same schema as JSON, --name sets the schema name (it defaults to the file name without its extension, and to sketch when reading standard input), and -o, -, --strict and the diagnostics work exactly as they do for diagram.

skiss import schema.linkml.yaml goes the other way: it reads a LinkML schema, YAML or JSON, and writes Skiss. What the projection could not carry — patterns, required, mixins, the names it had to convert — is one line on standard error before the diagnostics, because a sketch is a smaller language than LinkML and that line says by how much. -o, - and the diagnostics work as they do for compile; --strict exits 1 when the projected sketch has a diagnostic, and also when anything was dropped. An input that is not a schema at all — not YAML, or YAML no schema can be read out of — produces no sketch, says why on standard error, and exits 2, the code every command uses for unreadable input.

npm install @eriknaslund/skiss also gives you the library: compile, formatDiagnostic, parse, resolve, toLinkML, serialize, toMermaid, toSkiss, fromLinkML, formatDropped, importLinkML, tokenizeLine and VERSION, browser-safe.

tokenizeLine is there for editors: it says where the words of one line are — { kind, from, to } for each run of characters, so a host can colour them. It is line-based and stateless, as the language is: one line in, its tokens out, nothing carried from the line before, and nothing said about a run it does not recognise, so a half-typed line keeps the colours it has earned. It is not a parser and reports nothing; diagnostics stay parse and resolve's (ADR 0010).

Editors that render Skiss live are separate projects built on this package. This repository is the language, the library and the command line. To try the language without installing anything, open the playground: write a sketch, watch the diagram, share a link. Inside Obsidian, the obsidian-skiss plugin renders skiss code blocks in your notes.

Where to look

| | | |---|---| | docs/SPEC.md | The language, its grammar, and the LinkML mapping. Start here. | | docs/DESIGN.md | Why the rules are what they are. | | docs/ARCHITECTURE.md | How the code is organised. | | docs/adr/ | Architecture decision records. | | docs/ROADMAP.md | What comes next. | | docs/RELEASING.md | How a version reaches npm. | | AGENTS.md | How this repository is built. |

Status

0.6.1, published on npm as @eriknaslund/skiss. The language parses, resolves and diagnoses; skiss diagram draws it, skiss compile writes LinkML that the real LinkML toolchain validates in CI, and skiss import reads a LinkML schema back into a sketch. The library exports the same in both directions and is browser-safe.

The specification is at 0.3.1 and moves when the language does, which is not with every release. Not built: editing a projected schema so that what Skiss cannot express survives the edit (SPEC §8.1). CHANGELOG.md is what changed when.

License

MIT.