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

@opvs-ai/skills

v0.7.3

Published

opvsHUB Skill Factory + marketplace CLI — generate plugins from schema.yaml; publish / install / doctor signed marketplace packages

Readme

@opvs-ai/skills

Skill Factory for opvsHUB — generates typed OpenClaw gateway plugins from schema.yaml API definitions.

Install

# From the private OPVS registry
npm install @opvs-ai/skills --registry https://npm.opvs.ai

Usage

Generate plugins from schema.yaml files

# Generate a single skill
opvs-skills generate agentboard --skills-dir ./skills --plugins-dir ./plugins

# Generate all skills
opvs-skills generate --all --skills-dir ./skills --plugins-dir ./plugins

# Generate all + bundle for gateway deployment
opvs-skills generate --all \
  --skills-dir ./skills \
  --plugins-dir ./plugins \
  --bundle ./bundle/index.ts

# Generate all + MCP tool definitions
opvs-skills generate --all \
  --skills-dir ./skills \
  --plugins-dir ./plugins \
  --mcp ./mcp/generated-tools.ts

Validate schemas

opvs-skills validate --skills-dir ./skills

List skills with tier status

opvs-skills list --skills-dir ./skills

Emit runtime-native skill bundles (W2.3)

emit-runtime re-emits opvsHUB skills as runtime-native skill/rule bundles for non-OpenClaw agent runtimes. Each runtime has its own filesystem convention; the generator handles the path + frontmatter shape per runtime.

| Runtime | Drop path inside --out | Frontmatter shape | |---|---|---| | claude-code | .claude/skills/<prefix>-<name>/SKILL.md | name, description (per Claude Code skills) | | antigravity | .agent/skills/<prefix>-<name>/SKILL.md | name, description (per Antigravity skills codelab) | | cursor | .cursor/rules/<prefix>-<name>.mdc | description, alwaysApply (per Cursor rules) | | windsurf | .windsurf/rules/<prefix>-<name>.md (capped at 12,000 chars) | trigger, description (per Windsurf memories) |

# Emit a single skill for Claude Code
opvs-skills emit-runtime claude-code \
  --skills-dir ./skills \
  --out ./opvs-runtime-bundle/claude \
  --skill vayapin

# Emit all skills for Cursor
opvs-skills emit-runtime cursor \
  --skills-dir ./skills \
  --out ./opvs-runtime-bundle/cursor

# Restrict to an allowlist
opvs-skills emit-runtime windsurf \
  --skills-dir ./skills \
  --out ./opvs-runtime-bundle/windsurf \
  --allowlist vayapin,agentboard,opvs-foundation

# Dry-run (print what would be written without touching disk)
opvs-skills emit-runtime antigravity \
  --skills-dir ./skills \
  --out /tmp/scratch \
  --dry-run

--prefix <prefix> controls the filename / directory prefix (default opvs). The user drops the contents of --out into a target project root to activate the skills.

End-to-end verification status (2026-05-15):

| Runtime | Status | |---|---| | claude-code | Live-verified — fresh project + dropped bundle → claude --print discovers /opvs-vayapin, lists methods + env vars. Session log: tests/fixtures/e2e/claude-code-session.md | | cursor | Verified via Claude-equivalent rule-injection simulation — rule body fed as system prompt yields a correct, contextual answer. Session log: tests/fixtures/e2e/cursor-session.md | | windsurf | Format-level verified only — file lands at .windsurf/rules/, frontmatter parses, body kept under the 12k char cap. IDE-side activation untested (Windsurf is GUI-only). | | antigravity | Format-level verified only — file lands at .agent/skills/<slug>/SKILL.md, frontmatter matches the docs. IDE-side activation untested. |

What it generates

From a single schema.yaml:

| Output | Purpose | |--------|---------| | {skill}.ts plugin | TypeScript plugin with api.registerTool() calls — native LLM tools | | skills.yaml manifest | Tier 1 discovery index (one line per skill) | | index.ts bundle | All plugins merged into one file for gateway deployment | | generated-tools.ts | MCP tool definitions for the @opvs-ai/mcp server |

schema.yaml format

name: my-skill
version: "1.0.0"
description: What this skill does
category: utility
base_url: /api/v1/my-service
auth:
  type: pat
  header: Authorization
  prefix: Bearer
  env_var: OPVS_PAT

methods:
  listItems:
    description: List all items
    http: GET /items
    params:
      status:
        type: enum
        values: [active, archived]
        required: false
    response:
      format: yaml

See the opvsHUB repo for all skill schemas and full documentation.

Programmatic API

import { generateFromSchema } from "@opvs-ai/skills";

const schemaYaml = fs.readFileSync("schema.yaml", "utf-8");
const result = generateFromSchema(schemaYaml);

// result.plugin   — TypeScript plugin code
// result.manifest — skills.yaml entry
// result.skillMd  — updated SKILL.md (if applicable)

OpenAPI ↔ schema.yaml drift detection (check / fix)

A.4 / A.6 in B1 Bundle 1 (2026-05-22) were both release-process bugs — agentboard_reorderColumns had a stale param shape and agentboard_updateColumn was missing from the published MCP entirely. Both were caused by schema.yaml drifting from the live FastAPI OpenAPI spec with nobody noticing until customer-facing tools 422'd.

opvs-skills check is the gate that prevents this from happening again. Point it at any FastAPI service's /openapi.json and it compares the live spec to your schema.yaml on a per-operation basis.

# Local smoke (boot the service first):
docker compose --profile queue up -d agentboard
sleep 20
opvs-skills check --skill agentboard --against http://localhost:8100/openapi.json
# Exit 1 on drift + structured report on stdout
# Exit 0 + "All schema methods match the live OpenAPI spec." when clean

# Against a checked-in OpenAPI export (no service boot needed):
opvs-skills check --skill agentboard --against ./openapi-agentboard.json

# JSON output for machine consumption:
opvs-skills check --skill agentboard --against http://localhost:8100/openapi.json --format json

# Skip known unbacked operations (e.g. routes intentionally not on the agent surface):
opvs-skills check --skill agentboard --against ... --ignore "GET /docs,GET /openapi.json"

The diff reports four drift classes per operation:

  • schema_only_fields — schema declares a param the API doesn't accept (column_ids after the rename)
  • api_only_fields — API requires a param the schema is missing (columns after the rename)
  • required_mismatch — both sides know the field but disagree on required
  • type_mismatch — both sides know the field but disagree on primitive type

Plus two operation-level diffs:

  • schema_only_op — schema declares an http: route the API doesn't expose
  • api_only_op — API exposes a route no schema method binds to (this is what would have caught updateColumn)

fix — emit a hand-apply checklist

opvs-skills fix --skill agentboard --against http://localhost:8100/openapi.json --out fix.md

fix deliberately does NOT mutate schema.yaml in place. Descriptions are hand-crafted and an automated rewrite risks stamping over them. The output is a markdown checklist with concrete per-field instructions you can copy into the YAML by hand.

Which drift FAILS: --fail-on

The six classes above split into three things, not two, and conflating any of them is what kept this check advisory for months.

| | Classes | Meaning | Gates? | |---|---|---|---| | blocking | schema_only_fields, required_mismatch, type_mismatch, schema_only_op | The schema is wrong. An agent that follows it literally gets a silently-dropped write, a 422, or a 404. | always | | unexposed fields | api_only_fields on a bound method | The agent can reach the endpoint and cannot set a field the API accepts. A capability gap in a surface already committed to. | at fields | | unwrapped routes | api_only_op | A route the skill does not bind. Curated-subset scope, not a defect. | never |

# Default — every difference exits 1. Useful locally; unusable as a gate.
opvs-skills check --skill agentboard --against ...

# Gate form — WRONG, plus an undecided field on a method you already bind.
opvs-skills check --skill agentboard --against ... --fail-on fields

# Narrowest — only WRONG.
opvs-skills check --skill agentboard --against ... --fail-on mismatch

🔴 --fail-on any can never be green for any real skill, and that is not a bug in your schema. A skill wraps a curated subset of its service by design — admin-catalog binds 44 of 1117 operations — so api_only_op is the normal state, not a defect. Requiring full coverage would force exposing internal config (default_model, model_overrides, heartbeat_config) to a vendor-facing agent surface just to satisfy CI.

🔑 Why fields is a separate rung (OTAS-36). Until the split, both coverage classes shared one counter — and they move in opposite directions. For admin-catalog that number read 1084: 1073 unwrapped routes it should never try to reduce, hiding 11 bound methods that were genuinely missing fields. Nobody could act on the sum, so nobody did. Separated, the second half is drivable to zero — and two of the three gated services (agentboard, agentmemory) were already there when it was first measured.

A withheld field is a decision, and the decision has to be written down. Record it in _drift_ignore.field_mismatches with a comment saying why:

_drift_ignore:
  field_mismatches:
    # `rating` — the star rating on a public storefront. Must DERIVE from job
    #   history; a hand-set value is fabricated social proof.
    # `heartbeat_config` — runtime scheduling, owned by the gateway.
    updateProfile: [rating, heartbeat_config]

A method whose every finding is allowlisted is promoted back to match, so the gate goes green. An undeclared withhold is indistinguishable from an oversight and fails — which is the point: a field added to the API tomorrow blocks the merge until someone decides expose-or-withhold.

CI gate

The .github/workflows/tests.yml workflow runs opvs-skills check --fail-on fields against three services on every PR: agentboard, agentmemory, admin-catalog. Since OTAS-32 it is a required check in the All Tests Pass gate; since OTAS-36 it holds both blocking drift and unexposed fields at zero to merge. This is what catches A.4/A.6-class regressions before they hit npm publish.

It was advisory from B1 until 2026-08-27 on the plan that a follow-up would walk the report and then flip it. That follow-up could not have worked: the check exited 1 on any unwrapped route, so no amount of reconciliation would have turned it green. Measured at the flip — agentboard 0 blocking / 25 coverage, agentmemory 0 / 10, admin-catalog 0 / 1084 — the two services long believed to hold "unreconciled drift" had never had a single field-level defect. The earlier version of this section also named agentdocs, which has never been in the matrix. OTAS-36 then split that coverage figure and raised the gate to --fail-on fields; at that flip the unexposed-field counts were agentboard 0, agentmemory 0, admin-catalog 11 → 0.

Requirements

  • Node.js >= 18
  • OpenClaw gateway for plugin deployment