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

@stratusagent/plugins

v0.6.0

Published

The Stratus Agent plugin host: manifest validation, the manifest-bound registration view, and the loader that turns a config block into running capability

Readme

@stratusagent/plugins

The plugin host: what a plugin claims, what it is allowed to register, and how a config block becomes running capability.

The contract lives in docs/architecture/plugins.md and is not re-derived here. This package is what makes it enforceable.

You do not install this directly — it comes with @stratusagent/cli. You do read it if you are writing a plugin.

What a plugin author needs

A stratus field in package.json, and one named export:

{
  "name": "stratus-plugin-notes",
  "keywords": ["stratus-plugin"],
  "stratus": {
    "pluginVersion": 1,
    "contributes": {
      "tools": [
        { "name": "notes.read", "risk": "safe" },
        { "name": "notes.write", "risk": "gated" }
      ]
    },
    "config": {
      "type": "object",
      "properties": { "vault": { "type": "string" } },
      "required": ["vault"]
    }
  }
}
export const createPlugin = (config) => ({
  name: 'stratus-plugin-notes',
  setup(context) {
    context.tools.register(readTool(config));
  },
  // Optional. Only if setup acquired something a daemon shutdown must release.
  async dispose() {},
});

What the host does with it

  • Reads the manifest without importing the package. A misconfigured or over-reaching plugin fails at load, with its own name in the message, rather than at the first tool call in the middle of somebody's turn.
  • Validates your config against your schema — including each per-agent entry under agents, with required relaxed there, because an override says what differs for one agent rather than restating the defaults.
  • Hands setup() a manifest-bound registry, not the real one. A name your manifest does not declare is refused. The risk a tool registers at is the riskiest of three claims — your manifest's, the floor your package is held to, and whatever the object says about itself — so a tool can raise itself and can never talk its way below what it declared.
  • Stages and commits. Nothing reaches the shared registry until your whole setup() has succeeded, so a plugin that over-reaches on its fourth tool leaves none of the first three behind.
  • Refuses collisions. Two packages contributing one tool name is a load-time error naming both, never whichever loaded last.

Resolving settings per call

import { resolvePluginAgentConfig } from '@stratusagent/plugins';

async execute(input, session) {
  const settings = resolvePluginAgentConfig(config, session.agent.id);
  …
}

Per call, from the session — not once at setup. For a plugin whose settings are an access boundary (tool-fs roots are the example), resolving once hands every agent whichever value was resolved first, which is one agent reading another's files from code that looks correct.

loadOptionalModule

The resolve-then-import split, in one place:

const slack = await loadOptionalModule('@stratusagent/channel-slack', {
  resolve: (id) => import.meta.resolve(id),
  import: (id) => import(id),
});

Only a package failing to resolve means "not installed". One that is installed but missing a dependency of its own throws ERR_MODULE_NOT_FOUND too, naming that dependency — so reading the import's error would turn a broken install into a silently disabled feature.

The two capabilities come from the caller because import.meta.resolve answers relative to the module that calls it: resolvable from the daemon and resolvable from this package are different questions, and only the first is the one being asked.