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

viv-knowledge-diagrams

v0.2.0

Published

Knowledge-spread visualizations for Viv projects — who knows what, how they learned it, and how knowledge propagated through the world.

Downloads

256

Readme

viv-knowledge-diagrams

Text-based knowledge-spread visualizations for Viv projects. Shows who knows what, how they learned it, and how knowledge propagated through the world.

Works with any Viv project. Peer dependency on @siftystudio/viv-runtime.

Setup

With Claude Code

Ask Claude Code to add viv-knowledge-diagrams to your project. Claude will:

  1. npm install viv-knowledge-diagrams
  2. Create .claude/commands/ directory
  3. Copy the knowledge diagram commands into your project

You'll then have three new commands available:

  • /knowledge-tree — who told whom about an action
  • /knowledge-map — what a character knows
  • /knowledge-wave — temporal spread of knowledge

Without Claude Code

  1. Install in your Viv project:
npm install viv-knowledge-diagrams
  1. Import and call from your code:
import { fromAdapter, constructKnowledgeTreeDiagram } from "viv-knowledge-diagrams";

// After initializing the Viv runtime with your adapter:
const ds = fromAdapter(myAdapter);

// Pick an action ID from the chronicle and visualize its spread
const diagram = await constructKnowledgeTreeDiagram({
    dataSource: ds,
    actionID: someActionID,
    showTellers: true,
});
console.log(diagram);

Prerequisite: knowledge-relaying actions

The diagrams are only interesting if your .viv code has actions that relay knowledge about past events. This means actions that cast a past action in a role using search query:

action retell-market-drama:
    roles:
        @teller:
            as: initiator
        @audience:
            as: partner
        @pastEvent:
            as: action
            from:
                search query noteworthy-event:
                    over: @teller
    ...

query noteworthy-event:
    importance:
        >=: 3
    salience:
        >=: 1

When @pastEvent is cast, Viv automatically propagates knowledge of that event to everyone present. Without actions like this, all memories are first-person witnessed and there are no relay chains to visualize.

Three diagrams

Knowledge tree

"How did knowledge of this action spread?"

Characters are the nodes, actions are the labeled edges. Reads top-down: who knew, how they told, who learned next.

◉ whisper-rumor-about

  Witnessed by: Bran, Lirael  t=1560

  Spread:

    Bran (witness)
    └──[warn-about-merchant]──▶ Brull, Cedric  t=1620

    Cedric (secondhand)
    └──[retell-market-drama]──▶ Horik, Hrag, Korg, Gork  t=1680

  28 knowers / 164 characters
await constructKnowledgeTreeDiagram({
    dataSource: ds,
    actionID: "...",
    showTellers: true,
});

Memory map

"What does this character know?"

Groups memories into witnessed vs. learned secondhand, with salience and the relay action that carried the knowledge.

◉ Varr — 133 memories (11 secondhand)

  Witnessed (122):
    retell-market-drama  sal:6  t=1740
    hold-court-from-bench  sal:4  t=300

  Learned secondhand (11):
    whisper-rumor-about  sal:5  t=1620  <- heard via elder-recounts-old-tale
await constructMemoryMapDiagram({
    dataSource: ds,
    characterID: "...",
    sortBy: "salience",
    limit: 15,
});

Propagation wave

"In what order did knowledge spread?"

Timeline of waves. Each wave shows who learned, how (the relay action), and from whom (the teller).

◉ whisper-rumor-about

  Wave 0 — t=1560
    Witnessed: Bran, Lirael

  Wave 1 — t=1620
    Learned: Brull, Cedric
    How:     warn-about-merchant
    From:    Bran

  Wave 2 — t=1680
    Learned: Horik, Hrag, Korg, Gork, Krall, Mad Tilda
    How:     retell-market-drama
    From:    Cedric

  28 / 164 characters know (17% penetration)
await constructPropagationWaveDiagram({
    dataSource: ds,
    actionID: "...",
    showTellers: true,
    showStats: true,
});

Adapter contract

fromAdapter() expects your HostApplicationAdapter.getEntityView() to return entity objects with specific properties:

Characters must have a memories object:

type CharacterMemories = {
    [actionID: UID]: {
        formationTimestamp: number;      // When the character learned this
        salience: number;                // 0–infinity, higher = more important to remember
        forgotten: boolean;              // Whether the character forgot this
        sources: UID[];                  // Action IDs that caused knowledge formation
        associations: string[];          // Tags for querying/filtering
    };
};

Actions must have a present array:

type ActionView = {
    present: UID[];  // Character IDs who witnessed this action
    // ... other action properties
};

If your adapter doesn't populate these fields, fromAdapter() will throw a descriptive error explaining what's missing.

Custom data source

If you don't want to pass the full adapter, implement KnowledgeDataSource directly:

import type { KnowledgeDataSource } from "viv-knowledge-diagrams";

const ds: KnowledgeDataSource = {
    getAllCharacterIDs: () => [...],
    getCharacterMemories: (id) => characters[id].memories,  // Returns CharacterMemories object
    getActionPresent: (id) => actions[id].present,          // Returns UID[] of witnesses
    getEntityLabel: (id) => entities[id].name,
};

Options

All three functions accept:

| Option | Default | Description | |--------|---------|-------------| | dataSource | required | KnowledgeDataSource or result of fromAdapter() | | ansi | false | ANSI terminal colors | | showForgotten | false | Include forgotten memories | | showTellers | false | Identify who told whom (costs more but richer output) | | formatCharacterLabel | getEntityLabel | Custom character name formatter | | formatActionLabel | getEntityLabel | Custom action name formatter |

Plus per-diagram:

  • Knowledge tree: showTimestamps (default true)
  • Memory map: sortBy ("salience" | "timestamp"), limit
  • Propagation wave: showStats (default true)

License

MIT