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

@mcuste/pi-diagram

v0.5.1

Published

Makes Pi and Oh My Pi agents actively explain complex topics with token-efficient D2 diagrams

Readme

pi-diagram

CI

Diagram extension demo

An extension for the Pi and Oh My Pi terminal coding agents. It makes agents actively use visual explanations instead of defaulting to walls of text. The model writes compact declarative D2 source through one diagram tool. The extension renders that source as Unicode in the terminal and as reusable SVG and PNG output.

If any of those names are new to you:

  • D2 is a declarative diagram language. Text such as client -> gateway -> api compiles to a laid-out diagram, and the same language covers containers, sequence diagrams, and SQL tables.
  • Pi and Oh My Pi are terminal coding agents. An extension is an npm package they load at startup to add tools the model can call.

Why

Coding agents explain spatial things in prose: "A calls B, B queues C, C writes D, D emits an event back to A." The user rebuilds a graph in their head that the agent could have drawn. A fenced Mermaid block moves the problem rather than solving it, because a terminal shows the source instead of the picture.

The goal is to change how agents explain, not just add a renderer. When structure, flow, sequence, data, or relationships are easier to see than to read, the agent leads with a diagram and limits prose to details the picture cannot show.

D2 keeps generation token-efficient: the model describes nodes, edges, groups, and labels instead of spending tokens on layout or SVG coordinates. The tool owns the layout, theme, spacing, and fonts, so the same compact source produces consistent Unicode, SVG, and PNG output.

Requirements

  • Node.js 22 or newer
  • The D2 CLI, version 0.8.0 or newer, on PATH or named by D2_BIN
brew install d2                          # ships 0.8.1
go install github.com/d2lang/[email protected]   # or a pinned build from source

The prebuilt binaries on D2's GitHub releases page stop at 0.7.1, which draws SQL tables as empty boxes, so they are below the supported floor.

D2 is an external dependency on purpose. The extension never downloads a renderer during a tool call. Without it, the extension still loads and a call explains how to install it.

Install

Pi:

pi install npm:@mcuste/pi-diagram

Oh My Pi:

omp plugin install @mcuste/pi-diagram

Or through the Oh My Pi marketplace:

/marketplace add mcuste/pi-diagram
/marketplace install pi-diagram@pi-diagram

From a local checkout:

pnpm install
pi install /absolute/path/to/pi-diagram
omp plugin link /absolute/path/to/pi-diagram

What the tool does

One tool named diagram. Give it D2 source and it draws the diagram in the terminal:

edge: Edge { gateway }
core: Core { api; worker }
edge.gateway -> core.api
core.api -> core.worker: enqueue
┌───────────────────┐
│       Edge        │
│                   │
│    ┌──────────┐   │
│    │ gateway  │   │
│    └──────────┘   │
│          │        │
└──────────│────────┘
           │
 ┌─────────│─────────┐
 │       Core        │
 │         ▼         │
 │     ┌──────┐      │
 │     │ api  │      │
 │     └──────┘      │
 │         │         │
 │      enqueue      │
 │         ▼         │
 │    ┌─────────┐    │
 │    │ worker  │    │
 │    └─────────┘    │
 └───────────────────┘

Containers, sequence diagrams, SQL tables, class shapes, and state flows all work from the same language.

| Field | Purpose | | --- | --- | | source | The diagram, in D2 | | title | Label shown above the diagram | | render | auto prepares Unicode and PNG; image, unicode, and source choose a view | | profile | What the diagram is for. It sets the layout engine, theme, and spacing | | formats | Files to produce: source, svg, png, txt. Written outside the repository | | save | Also copy them into the repository. dir is required |

When the model draws

A tool description alone gets called when the user asks for a diagram, not whenever a diagram is the clearer answer. To make visual explanation active, the extension adds a short block to the host system prompt: draw when structure, flow, or relationships are easier to see than to read, call the tool before explaining, keep the prose to what the picture does not show, and never hand-write ASCII art or Mermaid. The block tells the model to check C4, sequence, class, data, dependency, or tree before drawing a generic flow. The tool description contains the detailed profile and shape rules.

The result is fewer walls of text: an answer about how parts connect arrives as a picture with a few lines around it. The block is appended to whatever the host built, is added once, and is left out when the diagram tool is not active.

What a profile changes

The model says what a diagram is for, and the tool decides how it looks:

| Profile | For | Drawn as | | --- | --- | --- | | explain | States, decisions, transformations, or process flow inside an answer | Hand drawn, neutral theme, small margins | | architecture | Runtime services and infrastructure without C4 levels | Neutral theme, more room between rows so edges stay separable | | data | Stored records and relations, or types and public APIs | Neutral theme, tight spacing: tables and classes are tall already | | docs | A saved diagram when no more specific profile fits | Grey theme that prints in greyscale, page-sized margins | | tree | Folders, call trees, or other parent-child structures | Dagre, which fans children out under their parent | | c4 | System scope, users, external systems, runnable units, or module responsibilities | Architecture spacing under the C4 palette | | dependency | Imports, packages, build order, coupling, impact, or cycles | The tightest spacing, cutting the room edges take past nodes |

explain is the default and is drawn by hand: an answer in a conversation is a rough model, and a crisp diagram claims more precision than it has. Every other profile is crisp.

Every profile also sets a dark theme, so a saved SVG adapts to dark mode.

Only the picture changes. D2 draws text in character cells, so every profile gives the same box drawing.

Unicode and PNG views

Every call prepares Unicode, SVG, and PNG from the same D2 source.

Pi shows Unicode in its live tool row. Press Ctrl+O to replace it with the PNG and press it again to return to Unicode. If the terminal or harness has no image protocol, expansion keeps the Unicode view and reports This terminal cannot display inline images. A multiplexer between the terminal and agent must forward the protocol. tmux needs allow-passthrough, and herdr needs experimental.kitty_graphics.

OMP keeps complete Unicode in the chronological tool result because settled transcript rows are immutable. Ctrl+O opens the latest diagram's PNG in a viewport-fitted fullscreen overlay. Press Ctrl+O or Esc to close it and return to the transcript. The Open PNG link remains available independently.

OMP owns the shared terminal image budget. Closing an overlay does not purge unrelated terminal images; the host evicts cached graphics under its normal budget policy.

Per-call overrides remain available when the user requests another method:

  • render: "image" shows a compact inline PNG. Pi can zoom it with Ctrl+O.
  • render: "unicode" keeps Unicode in both Pi views.
  • render: "source" shows the D2 source.

The PNG never enters the model's context. It is written to a private temporary directory and read only by the display renderer.

Where the terminal supports OSC 8 hyperlinks, OMP shows the linked PNG file name below the Unicode tool result. Pi links the title above the PNG, or the file name below an untitled PNG. Open that link to pan or zoom beyond the terminal view. Ghostty, Kitty, WezTerm, and iTerm2 support these links, some of them on a modified click.

D2 exports PNG by driving a headless browser it downloads on first use, which this tool will not do during a call. Instead the SVG is rasterized locally by resvg, which needs no browser and no network. Labels use the fonts in the SVG. Characters those fonts do not cover, such as CJK, fall back to fonts on the machine and produce a note.

What the model gets back

In a terminal this extension draws the row, so the model reads one line: Drew "Request path". It is on the user's screen, so it is not repeated here. Saved paths and generation notes come with it, so a conversation full of diagrams costs about what a conversation of text costs. Print, RPC, and JSON modes have no row to draw, so there the Unicode diagram is the result text.

Expanding a result replaces Unicode with PNG where supported and adds the display mode, profile, D2 version, file paths, diagnostics, and source.

Where files go

Most diagrams explain something in passing and should leave nothing behind. So nothing is written unless it is asked for, and the repository is never the default:

| Call | Files | Approval | | --- | --- | --- | | { source } | none, the diagram is only in the transcript | read | | { source, formats: ["svg"] } | an SVG in a private temp directory, path returned | read | | { source, title, save: { dir: "docs/diagrams" } } | editable D2 plus an embeddable SVG | write, prompts with the exact files |

save.dir has no default. There is no directory convention that holds across repositories, so the destination has to be named. Only pass save when the user asked to keep the diagram. A saved .d2 is put through d2 fmt first, because people edit it later.

A saved pair is editable source plus a viewable rendering:

docs/diagrams/request-lifecycle.d2
docs/diagrams/request-lifecycle.svg

Markdown then needs no D2 or Mermaid runtime:

![Request lifecycle](diagrams/request-lifecycle.svg)

For documentation prefer svg: it scales, and Markdown renders it anywhere. png exists for places where SVG support is weak.

Repository paths stay inside the workspace. Absolute paths, .., and symlinks pointing outside are all refused.

What D2 drew is also kept in a temporary store, so the same diagram drawn again is about ten times faster, including in a later session. A new D2 version, or any change to a profile, is a different entry. The store holds 64 MB for a week.

Layout engine, theme, padding, and font are deliberately not in the schema. They are policy here, and a model given those knobs spends tokens on styling and produces a different look every call.

What is deliberately missing

  • Model-drawn images. The model never emits SVG coordinates or ASCII art directly. It writes source, and a renderer lays it out.
  • Imports and external assets. Diagram source cannot pull in files, local images, or remote icons. Those turn a rendering request into file and network access.
  • Interactive editing. The tool renders; it is not a diagram editor in the terminal.
  • Every D2 feature. A safe subset is supported, and anything outside it is reported as an error the model can correct rather than being silently dropped.

Documentation

License

MIT