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

livestage

v1.1.1

Published

Live-document renderer and verifier for AI agents.

Readme

livestage

Live-document renderer and verifier for AI agents.

Version 1.1.1 | 1239+ tests | 30 directives | MIT

Your agent spends tokens every session re-deriving things the repo already knows. Which branch, what changed, which files have no test, whether .env.example still matches the code. Same commands, same parsing, every time.

A .stage file answers that once, at read time, in one Read call.

Source you write:

# Project status

@query "git log -1 --format='%h %s'" label="last_commit" /
@count "src" match="*.ts" label="file_count" /

Last commit: {{ last_commit }}. {{ file_count }} TypeScript files.

What the agent actually receives:

# Project status

Last commit: a1b2c3d fix parser edge case. 47 TypeScript files.

No directive syntax survives. The agent reading it needs to know nothing about LiveStage, and the numbers were true at the moment it read them.

Drift? What's that?

The reason those numbers are usually wrong is not laziness. It is that a document written once is a snapshot, and snapshots stop being true the moment the code moves.

CLAUDE.md, the file every Claude Code session in this repo reads first, was written once by Claude Code's own /init command and never regenerated. It claimed a directive count "as of this writing", a number nothing kept honest, and pointed at a donor spec file that had already stopped existing here. Both sat there, wrong, until someone happened to grep for them. Being written by an LLM the first time bought it nothing. A snapshot is a snapshot regardless of who typed it.

Now CLAUDE.stage generates it, and npm run claude-md:check fails CI if the committed file no longer matches. This README is the same: 5 modules, 30 directives, 25 worked examples, all computed at render time, none typed by hand.

Reach for this when

  • An agent runs the same commands at the start of every session.
  • A hand-maintained file describes something the code already knows: an env example, a scripts reference, a coverage map, an API index.
  • A number in your docs has an "as of" date next to it.
  • You want a document that degrades honestly rather than silently.

Skip it when

  • The document is genuinely static prose. A design rationale does not change because a file did.
  • The data changes within a single render, so the answer is stale before the reader finishes.
  • One shell command already answers the question. Wrapping it buys nothing and adds a dependency.
  • You need the agent to decide something. LiveStage computes and hands back markdown. It never judges, gates or chooses.

Install

npm install --save-dev livestage

Then wire it into an AI coding assistant:

npx livestage init

init is idempotent and transactional: safe to run twice, and a partial failure rolls back everything it wrote. It registers a PostToolUse hook so reading a .stage file with the normal file tool already returns the rendered result, installs a SessionStart hook that injects a live brief instead of a static CLAUDE.md section, writes both into the detected client's settings (~/.claude/settings.json, or ~/.cursor/settings.json, or pass --client), and seeds a policy file. See Security.

PostToolUse rather than PreToolUse on purpose: PreToolUse can only allow, deny or rewrite a tool's arguments. Only PostToolUse can substitute what a Read call actually returns.

Or standalone, no hook:

npx livestage render some-doc.stage

What it costs an agent to not have this

An agent getting repo state with shell emits a command, reads a result, and reasons about it, three times over. With a brief it emits one Read and reads one finished answer.

| scenario | shell | one brief | |-----------------------------|-------|-----------| | repo state (3 git commands) | 91 | 25 | | coverage gap (2 listings) | 54 | 20 | | env drift (2 commands) | 61 | 19 |

Method: cl100k_base, model-emitted tokens only, matched content on both sides. Model-emitted tokens are output-priced, roughly 5x input. There is no percentage claimed here on purpose: a real saving depends on a real agent run, and a modelled number published as a benchmark is the kind of claim that deserves to be torn apart.

The second-order point matters more than the first. A regenerated command varies. grep -r "process.env" and grep -rn 'process\.env' and rg are three different commands, and one of them returns a different answer. A .stage command is fixed text, authored once, and it returns the same shape every time.

Three briefs, live from their real source

Each of these replaces several separate commands with one render. They are read live from the runnable files under examples/agent-briefs/, not retyped, so what you see below cannot drift from what actually runs. Run any of them with livestage render <file> from inside that directory, where the shared policy grant applies.

Codebase health

Old way: git rev-parse --abbrev-ref HEAD, then git log -1, then git status --short. Three round trips, three outputs to merge mentally.

# Codebase Health Brief
The old way: `git rev-parse --abbrev-ref HEAD`, `git log -1`, `git status
--short`, three separate commands run and mentally merged into one picture
of "is this repo in good shape right now."
The new way: one render.
## Policy grant this example needs
`examples/agent-briefs/.livestage/policy.json` in this directory (shared
with `change-review.stage`): `shell.enabled` plus the exact `git ...`
command strings below in `allow_patterns`, nothing else, and no wildcard
(a prefix pattern like `"git *"` allows anything after that prefix,
including `;`/`&&`/pipe chaining; only safe with commands that never
interpolate `{{ }}`/`${}` values, exact strings are the honest default).
See that file directly for the exact JSON.
## Result
@query "git rev-parse --abbrev-ref HEAD" label="branch" visible="false" /
@query "git log -1 --format='%h %s'" label="last_commit" visible="false" /
@query "git status --short" label="dirty" visible="false" /
- Branch: {{ branch }}
- Last commit: {{ last_commit }}
@if dirty == ""
- Uncommitted files: none detected
@if-end
@if dirty != ""
- Uncommitted files:
{{ dirty }}
@if-end

Change review

Old way: git diff --stat, git log -5 --oneline, git status --short.

# Change Review Brief
The old way: `git diff --stat`, `git log -5 --oneline`, `git status
--short`, three commands and three separate scrollbacks to reconstruct
"what changed here, and what's still uncommitted."
The new way: one render.
## Policy grant this example needs
Shares `examples/agent-briefs/.livestage/policy.json` with
`codebase-health.stage`: `shell.enabled` plus the exact `git ...` command
strings this file uses below in `allow_patterns`, no wildcard.
## Result
@query "git diff --stat" label="diff_stat" visible="false" /
@query "git log -5 --oneline" label="recent_commits" visible="false" /
@query "git status --short" label="status" visible="false" /
### Diff stat
{{ diff_stat }}
### Recent commits
{{ recent_commits }}
### Working tree status
{{ status }}

Onboarding brief, with no shell grant at all

Old way: cat README.md, cat package.json, ls src, grep scripts package.json. This one needs no shell permission. @read and @tree are filesystem directives, which means a whole class of "read this project" work never needs shell access in the first place.

# Onboarding Brief
The old way: `cat README.md`, `cat package.json`, `ls src`, `grep scripts
package.json`, four separate commands before an agent (or a new
contributor) has any real picture of what a project even is.
The new way: one render. This example needs no shell grant at all, no
`.livestage/policy.json` beyond the shared one in this directory (which
this file doesn't even use): `@read` and `@tree` are filesystem-policy
directives, not shell.
## Result
Runs against a small, self-contained fixture project
(`sample-project/`) alongside this file, so the pattern is reusable in any
project without a path escaping this example's own directory.
@read "sample-project/package.json" path="name" label="proj_name" visible="false" /
@read "sample-project/package.json" path="description" label="proj_desc" visible="false" /
@tree "sample-project/src" label="src_tree" visible="false" /
## Onboarding Brief: {{ proj_name }}
{{ proj_desc }}
### Source tree
{{ src_tree }}

Security

Every directive runs under a policy file at .livestage/policy.json. init seeds the shipped strict profile if one does not already exist.

"Strict" names the enforcement model, not a feature switch. Every surface not explicitly granted is denied, hard destructive patterns are immutable, and nothing reaches outside the project root.

  • shell ships with a curated read-only allowlist, around 40 patterns: git, cat, grep, find, the common test runners. Deliberately, since @query is dead on arrival without it.
  • @code and HTTP ship genuinely empty. Anything beyond the shipped allowlist, on any surface, needs an explicit grant.

The three briefs above share one grant in examples/agent-briefs/.livestage/policy.json, which lists the five git commands they run and nothing else.

Keep a generated .md honest at read time

Add --stamp-metadata to a livestage build call and the generator writes a small HTML comment at the top of the output:

<!-- livestage:generated
livestage_source: docs/api.stage
livestage_updated_at: 2026-08-17T15:46:01.385Z
livestage_version: 1.0.2
livestage_content_hash: 53e17201482b...
livestage_hash_inputs: src/**/*.ts,package.json,docs/api.stage
livestage_regenerate_on_read: true
livestage_degraded: false
-->

An HTML comment rather than YAML frontmatter on purpose. GitHub renders a leading --- block badly at the top of a repo's own README, or Jekyll interprets it. A comment renders as nothing and is equally machine-readable. --hash-inputs names every file the render actually depends on; without it the hash covers only the .stage source. Presence of the block, not the filename, opts a file into the contract. A .md with no block is passed through untouched whether the hook is installed or not.

The PostToolUse hook watches reads of any stamped .md. It hashes the declared inputs first, and unchanged means the committed file is served as-is with no render at all. Only a changed hash triggers work, and livestage_regenerate_on_read, a field only you set, decides what happens:

  • absent (default): committed content is served, with a notice naming what is stale and the exact regen command. Drift gets surfaced, content does not change under the reader.
  • true: a fresh render is served, with a notice stating plainly that what follows is a live render rather than the file's committed bytes.
  • false: committed content, no notice, no comparison. An explicit opt-out is honored as one.

If the render fails or times out, the committed file is served unchanged with a "could not verify, may be stale" notice. A read through this hook never fails and never serves a fresh render silently. A stale file being wrong is recoverable. A stale file that looks current to the one reader who could have caught it is not.

Fallbacks

Every directive declares a static fallback. A .stage file read without the engine, or after a timeout, is still a usable document, and it says plainly that it is degraded rather than presenting stale output as current.

Directive reference

All 30 directives, with syntax and examples: docs/directives.md.

That page is generated the same way this one is, pulled from whichever docs declare primitives in their frontmatter. Document a new directive with a primitives entry and it appears there on the next npm run directives.

More examples

25 worked examples ship in this repo, each with a rendered .md beside its .stage source, kept honest by npm run examples:check in CI. A few are marked live because they are deliberately non-deterministic: real git state, wall-clock timing, an environment-dependent tree. Those ship a rendered snapshot too, just not one asserted byte-identical on every run.

examples/hello.stage (rendered, live) The smallest one: today's date, this directory's tree.

examples/drift/ eliminates four kinds of hand-maintained file that silently diverge from the code that governs them: env-drift (rendered), .env.example against actual process.env usage . scripts-reference (rendered), package.json's real scripts . test-coverage-map (rendered), which source files have no matching test . todo-debt (rendered), a live TODO/FIXME/HACK inventory.

examples/agent-briefs/ the three above in full: codebase-health (rendered, live), change-review (rendered, live), onboarding-brief (rendered).

examples/database/ and examples/http-health/ there is no @db or @http directive. External reach is @code under policy. customers (rendered) runs driver code and renders a table. check (rendered) runs fetch and renders structured status.

examples/import-graph/ (rendered) @graph reads YAML frontmatter and has no notion of real imports. @import-graph does, walking a source tree into a real Mermaid dependency graph, one node per file, no shell or @code grant needed.

examples/connections/ (rendered) A project index: path tree, dependency graph, source overlap, nothing hand-maintained.

examples/multi-step/ files as steps, frontmatter as state, assertions as gates, no workflow engine. index (rendered) is the overview; its own README runs the pipeline. The step files are not pre-rendered here because running them changes real state on disk, which is the point.

examples/showcase/ three documents rendering under the default policy with no extra grants: index (rendered), api-reference (rendered), report (rendered, live).

How this README stays current

README.stage, the source of this file, reads package.json for the name, version and description; scripts/test-baseline.json for the reviewed test floor, rendered as "N+" because it only ever rises; the module, directive and example counts by counting the directories and files themselves; the round-trip table from benchmarks/roundtrip.json; and the three worked examples from their real source, so the shown code cannot drift from what runs.

npm run readme regenerates README.md. npm run readme:check renders into a throwaway and fails if the committed file differs. That check runs in CI on every push, so a stale README fails the build instead of quietly persisting.

The one thing that still needs a human is writing a new directive's ## Interface Overview when it lands, the same way any judgment-call frontmatter field is authored by hand. Discovery, names, syntax, examples and counts are automatic.


MIT License.