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

@plures/chronos

v0.1.1

Published

Graph-native application state chronicle — zero-effort observability through PluresDB state diffs

Readme

Chronos

Graph-native application state chronicle — zero-effort observability through PluresDB state diffs.

"The best log is one no developer had to write."

CI npm version License: AGPL-3.0-or-later

Table of Contents

Installation

npm install @plures/chronos

Requires Node.js ≥ 18 or a modern browser. ESM only.

Quick Start

import { createChronicle } from '@plures/chronos/chronicle';

// One line. Every state change is now chronicled.
const chronicle = createChronicle(db);

// Inspect history
const history = chronicle.history('todos.1');
// → [{ id, timestamp, path, diff: { before: null, after: { text: 'buy milk' } }, ... }]

chronicle.stop();

📖 Full API Reference →

The Problem

Traditional application logging is broken:

  • Manual — developers decide what to log, inevitably missing what matters
  • Flat — lines in a file with no relationships or causality
  • Lossy — you only see what someone thought to capture
  • Noisy — 90% garbage until something breaks, then the 10% you need is missing

The Insight

If your application state is already reactive (via plures/unum), then logging is just the chain of diffs recorded in time. Every state change is a graph node. Every causal relationship is an edge. No developer effort required.

How It Works

Application (using unum)
    │
    │  state diffs (automatic via unum subscriptions)
    ▼
┌─────────────────────────────┐
│  Chronos                    │
│  • Captures unum state diffs│
│  • Builds causal chain      │
│  • Timestamps each node     │
│  • Zero configuration       │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  PluresDB                   │
│  • Graph storage            │
│  • Time-series indexing     │
│  • Vector search            │
│  • Hyperswarm P2P sync      │
└─────────────────────────────┘

The Graph Model

Instead of flat log lines:

[INFO] 2026-03-18T15:30:00 User clicked submit
[INFO] 2026-03-18T15:30:01 Form validated
[INFO] 2026-03-18T15:30:01 API call POST /submit
[ERROR] 2026-03-18T15:30:02 Request failed: 500

Chronos captures a state graph:

UserAction(click_submit)
  ├─causes→ StateChange(form.validated = true)
  │           ├─causes→ APICall(POST /submit)
  │           │           └─causes→ StateChange(request.error = "500")
  │           └─causes→ UIUpdate(spinner.visible = true)
  └─context→ Session(user_id: 7, page: /checkout)

Querying

Replace grep "ERROR" | tail -100 with graph queries:

import { createChronicle } from '@plures/chronos/chronicle';
import { traceCausalChain } from '@plures/chronos/trace';
import { query } from '@plures/chronos/query';
import { createTimeTravelDebugger } from '@plures/chronos/time-travel';

const chronicle = createChronicle(db, { contextId: 'session:abc123' });

// What caused this error state?
const causes = traceCausalChain(
  chronicle._nodes, chronicle._edges, errorNodeId, { direction: 'backward' }
);

// What did this user action affect?
const effects = traceCausalChain(
  chronicle._nodes, chronicle._edges, actionNodeId, { direction: 'forward' }
);

// Everything that changed in this session
const sessionNodes = query(chronicle._nodes, chronicle._edges, {
  contextId: 'session:abc123',
});

// All changes to 'todos' in the last hour
const recentTodos = query(chronicle._nodes, [], {
  pathPrefix: 'todos.',
  startMs: Date.now() - 60 * 60 * 1000,
});

// Step through history interactively
const debugger_ = createTimeTravelDebugger(chronicle._nodes);
while (debugger_.stepForward()) {
  console.log(debugger_.current().path, debugger_.snapshot());
}

See docs/api.md for the complete API reference.

Integration with Unum

Chronos hooks into unum's reactive subscriptions automatically:

import { createChronos } from '@plures/chronos';
import { pluresData } from '@plures/unum';

// One line. That's it. Every state change is now chronicled.
const chronicle = createChronos(db);

// Your app code doesn't change at all
const todos = pluresData('todos');
todos.add({ text: 'Ship chronos', completed: false });
// ^ This state change is automatically captured with full causal context

Architecture

Chronicle Node

Each state change becomes a ChronicleNode:

interface ChronicleNode {
  id: string;              // Unique node ID (format: "chrono:{timestamp}-{counter}")
  timestamp: number;       // Unix ms
  path: string;            // PluresDB path that changed (e.g. "todos.abc123")
  diff: {
    before: unknown;       // Previous value (null for creates)
    after: unknown;        // New value (null for deletes)
    minimal?: DiffDescriptor | null; // Minimal structural diff (chronicle nodes only)
  };
  cause: string | null;    // ID of the node that caused this change
  context: string | null;  // Session/request/transaction context ID
}

Chronicle Edge Types

| Edge | Meaning | |------|---------| | causes | This state change directly caused another | | context | Belongs to this session/request/transaction | | reverts | Undoes a previous state change | | concurrent | Happened simultaneously (same tick) |

Causal Chain Tracking

Chronos uses async context (AsyncLocalStorage in Node.js) to automatically track causality:

  1. User action triggers a state change → root node
  2. That change triggers a subscriber → child node with causes edge to root
  3. Subscriber makes an API call → grandchild node
  4. API response triggers more state changes → great-grandchildren

All connected automatically. No manual instrumentation.

Design Principles

  1. Zero effort — If you use unum, you get chronos for free
  2. Complete — Every state change captured, not just what devs remember to log
  3. Structural — Graph, not text. Relationships, not lines.
  4. Queryable — Semantic search, graph traversal, time-range queries
  5. Distributed — PluresDB Hyperswarm sync means multi-node observability with just a topic key
  6. Minimal overhead — Append-only writes, async batching, configurable retention

Development

Prerequisites

  • Node.js ≥ 18
  • npm ≥ 9

Setup

git clone https://github.com/plures/chronos.git
cd chronos
npm install

Running Tests

# Run the full test suite (watch mode)
npm test

# Single run (CI mode)
npm run test:run

All tests are colocated under tests/ and use Vitest.

Roadmap

  • [x] Core: PluresDB subscription → causal graph chronicle
  • [x] Causal chain inference via AsyncLocalStorage
  • [x] Time-range queries (@plures/chronos/query)
  • [x] Graph traversal API — trace forward/backward (@plures/chronos/trace)
  • [x] Subgraph extraction by context/session
  • [x] Snapshot diff — minimal JSON diff engine (@plures/chronos/diff)
  • [x] Retention policies — TTL, quota, archival (@plures/chronos/rules)
  • [x] Time-travel debugger — step forward/backward through history
  • [x] Praxis rule engine integration
  • [ ] Semantic search over state changes
  • [ ] Dashboard UI (design-dojo component)
  • [ ] PluresDB Hyperswarm sync for distributed observability

Contributing

Contributions are welcome! Please read CONTRIBUTING.md before opening a pull request.

In short:

  1. Fork the repo and create a feature branch (git checkout -b feat/my-feature)
  2. Make your changes and add tests
  3. Run npm run test:run and ensure all tests pass
  4. Open a PR against main with a conventional-commit title (e.g. feat: add X)

Security

Please do not report security vulnerabilities through public GitHub issues. See our security policy for the responsible disclosure process.

Part of the Plures Ecosystem

| Package | Role | |---------|------| | PluresDB | Graph database with vector search + Hyperswarm | | Unum | Reactive state bindings (Svelte 5 ↔ PluresDB) | | Chronos | State chronicle (zero-effort observability) | | Pares Agens | AI agent framework | | Design Dojo | UI component library | | Plures Vault | Encrypted secret storage |

License

AGPL-3.0-or-later