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

@webskill/sdk

v0.25.0

Published

WebSkill — browser/Node agent skill runtime (skills, tools, MCP, governance, UI)

Downloads

2,789

Readme

@webskill/sdk

WebSkill is an agent skill runtime for Node.js and the browser. Skills are self-contained directories (SKILL.md + scripts/ + references/ + assets/) that an LLM agent discovers, reads, and executes through a multi-turn agent loop with human-in-the-loop interaction, artifacts, tracing, MCP integration, and governance.

Features

  • Skill protocol — Agent Skills compatible discovery, validation, cataloging (JSON / XML), declarative dependencies and allowed-tools, skill packs (multi-skill zip export/import with integrity digests).
  • Agent loop — multi-turn tool calling with structured errors fed back to the LLM, guardrails, lifecycle events, memory, human interaction (missing-parameter forms, confirmations, authorization prompts), and resumable interrupted runs.
  • Script sandbox — two tiers. Isolation-grade: Node ProcessSandboxExecutor (fork + --permission, real process isolation). (child_process.fork + --permission, experimental; fs scoped to the skill root, workers/child processes/addons denied by default — note the permission model has NO network dimension, so fetch/WebSocket stay patch-enforced and bare node:net imports remain a documented residual), and the browser opaque origin sandbox (sandbox="allow-scripts" iframe hosting a classic Worker — type:"module" workers cannot load in opaque origins, verified). Capability tier (NOT a security boundary): SandboxedScriptExecutor / BrowserWorkerScriptExecutor in blob-Worker mode, with deny-by-default network policy, builtin-module allowlist, forced approval, timeouts. Known proactive escape hatches (process.binding, dlopen, abort, …) are stripped in the worker entry (0.2.3); other host-shared surfaces are NOT defended — use ProcessSandboxExecutor for untrusted skills.
  • navigator.webskill — a browser facade (discover / read / validate / run / install / uninstall) assembled explicitly in one call.
  • MCP — call page-provided tools and consume page-declared dynamic skills over standard MCP transports (MessageChannel).
  • Governance — LLM-generated skill candidates with mandatory review, approval workflows, audit log, versioning/rollback, quarantine, evaluation, and scoring.
  • UI — framework-agnostic forms, result rendering (markdown, tables, SVG charts), generative UI adapters (Vercel AI SDK, OpenUI, A2UI), plus React and Vue component primitives.

Installation

npm install @webskill/sdk

React/Vue integrations require their respective peer dependencies (react + react-dom, or vue), which are optional.

zod ships as a direct dependency: the @webskill/sdk/ui catalog references it in its static import graph and in its public types, so declaring it optional would misrepresent the artifact. Hosts do not need to install it themselves. tar, oxc-parser and @modelcontextprotocol/sdk remain optional peers — they are loaded lazily and only when the corresponding API is called.

Requirements

  • Node.js >= 22.18 (native type stripping for .ts skill scripts)
  • Modern browsers for the browser host (OPFS, Web Workers, ES modules)

Quick start (Node)

Runs as-is with the bundled mock LLM — see examples/quickstart-node for the full project.

import { WebSkillRuntime } from '@webskill/sdk';
import { NodeFS, SandboxedScriptExecutor } from '@webskill/sdk/node';
import { MockLlmClient } from '@webskill/sdk/testing';

const fs = new NodeFS();
const llm = new MockLlmClient([
  { toolCalls: [{ id: 'c1', name: 'read_skill_file', arguments: { skillName: 'greeter' } }] },
  { toolCalls: [{ id: 'c2', name: 'greeter__greet', arguments: { text: 'world' } }] },
  { content: 'Greeted the world.' }
]);

const runtime = new WebSkillRuntime({ fs, roots: ['./skills'], llm, executor: new SandboxedScriptExecutor(fs) });

const catalog = await runtime.discover();
console.log(catalog.entries.map((e) => e.name));

const { output, run } = await runtime.run('Greet the world.');
console.log(output, run.status, run.trace.length);

For a real LLM, replace the mock with OpenAiCompatibleClient:

import { OpenAiCompatibleClient } from '@webskill/sdk';

const llm = new OpenAiCompatibleClient({
  baseUrl: 'https://your-llm-endpoint/v1',
  apiKey: process.env.LLM_API_KEY,
  model: 'your-model'
});

Subpath exports

@webskill/sdk (main entry)

Core protocol + runtime engine: discovery, catalog, validation, agent loop, LLM clients, routing, interaction types, memory, artifacts, tracing, network policy, capability approval, and the environment-agnostic createWebSkillApi facade.

import { SkillDiscovery, validateSkills, createWebSkillApi } from '@webskill/sdk';

const api = createWebSkillApi({ fs, roots: ['./skills'], llm, skillManager });
const report = await api.validate('./skills');
const run = await api.run('Summarize the references of skill greeter.');

@webskill/sdk/node

Node host: NodeFS, script executors (in-process, worker_threads sandbox, and ProcessSandboxExecutor for real process isolation), file-backed stores, SkillManager (install/export incl. multi-skill packs), CLI UI bridge, schema inference.

import { NodeFS, SkillManager } from '@webskill/sdk/node';

const manager = new SkillManager({ managedRoot: './.webskill/skills' });
await manager.install({ type: 'http', url: 'https://example.com/greeter.zip' });
await manager.exportPack(['greeter', 'calculator'], { outPath: './pack.zip' });
console.log((await manager.verifyIntegrity('greeter')).ok);

@webskill/sdk/browser

Browser host: OPFS provider, opaque origin iframe script sandbox (default on the main thread; engines running inside a Worker automatically fall back to the blob Worker form — no iframe is available there, documented), worker runtime host/client, BrowserSkillManager, and the navigator.webskill assembler. See examples/quickstart-browser.

import { installWebSkillNavigator } from '@webskill/browser';

const api = installWebSkillNavigator({ roots: ['/skills'], llm });
const catalog = await navigator.webskill.discover('/skills');
const run = await navigator.webskill.run('Greet the world.');

@webskill/sdk/mcp

MCP integration: MessageChannel transport, endpoint registry, tool resolver, temporary (page-declared) skills, WebMCP adapter, runtime plugin.

import { MessageChannelTransport, serveSkillAsMcp } from '@webskill/sdk/mcp';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

const server = new McpServer({ name: 'page', version: '0.1.0' });
serveSkillAsMcp(server, { name: 'greeter', description: 'Greet someone', body: '# Greeter' });
await server.connect(new MessageChannelTransport(port));

@webskill/sdk/ui

Framework-agnostic UI: form models + WebFormBridge, result rendering (markdown / table / mini-chart SVG), mini markdown, generative UI adapters (Vercel AI SDK, OpenUI, A2UI).

import { WebFormBridge } from '@webskill/sdk/ui';

const bridge = new WebFormBridge({ mount: document.querySelector('#ui') });
// pass as uiBridge to the runtime: forms, confirmations, and authorization
// prompts render as real DOM, results (incl. charts) render on completion.

@webskill/sdk/ui-react

React bridge state + InteractionForm / ResultBlocks / StreamingText components (requires react + react-dom).

import { ReactBridgeState, InteractionForm, ResultBlocks } from '@webskill/sdk/ui-react';

const bridge = new ReactBridgeState();
// <InteractionForm bridge={bridge} /> <ResultBlocks bridge={bridge} />

@webskill/sdk/ui-vue

Vue bridge state + equivalent components (requires vue).

import { VueBridgeState, InteractionForm, ResultBlocks } from '@webskill/sdk/ui-vue';

const bridge = new VueBridgeState();
// <InteractionForm :bridge="bridge" /> <ResultBlocks :bridge="bridge" />

@webskill/sdk/governance

Governance: skill candidates with mandatory review, approval workflows, audit log, versioning/rollback, quarantine, evaluation, scoring, dependency graph.

import { DependencyGraph } from '@webskill/sdk/governance';

const graph = DependencyGraph.buildFromCatalog(catalog.entries, documents);
console.log(graph.dependenciesOf('greeter'));

@webskill/sdk/testing

Test facilities (moved out of the main entry in 0.1.0): MockLlmClient, MockUiBridge, InMemoryStore, MemoryArtifactStore.

import { MockLlmClient, MockUiBridge, InMemoryStore, MemoryArtifactStore } from '@webskill/sdk/testing';

const llm = new MockLlmClient([{ content: 'deterministic answer' }]);

allowed-tools

A skill may narrow the tool surface it needs by declaring allowed-tools in its SKILL.md frontmatter. Three kinds of tools can be listed:

allowed-tools:
  - render # a script of this skill (scripts/render.ts)
  - endpoint:github/create_issue # one tool of an MCP endpoint
  - endpoint:github/* # every tool of an MCP endpoint
  - mcp#read_file # one page-provided (WebMCP) tool

Matching rules:

  • Only whole-entry matches and a trailing /* are supported. Wildcards in any other position are not, and a bare endpoint:github is not a prefix wildcard — it simply matches nothing.
  • A bare identifier means a script of the declaring skill only. It never grants access to another skill's script of the same name.

When several skills are active at the same time:

| Situation | Result | | ---------------------------------------- | -------------------------------------------------------------------------------------------------------- | | No active skill declares allowed-tools | Unrestricted | | At least one active skill declares it | A tool is allowed if it matches any declaring skill's list, or if some active skill declares nothing |

Enforcement level differs per tool kind in 0.3.0:

  • Scripts — enforced since 0.0.5: a script outside the list is not registered, and calling it by name returns TOOL_NOT_FOUND.
  • MCP / WebMCP tools — 0.3.0 only records a run.warning naming the tool and the entry to add, and still allows the call. This becomes a rejection in 0.4.0, so treat the warning as a build error in your own pipeline.

Stability

This package follows semver starting at 0.1.0. Public symbols carry JSDoc stability tags:

  • @stable — covered by the semver contract: bug fixes ship in patch, backwards-compatible capabilities in minor, breaking changes only in major (with release notes).
  • @experimental — may change in minor/patch releases. Currently: ExperimentalWebMcpAdapter, resumeRun and the RunSnapshot format, the A2UI/OpenUI adapters, and the authorize interaction type.

The public API surface of every subpath is pinned by checked-in .d.ts snapshots (api-snapshots/); any intentional change requires pnpm api:update and is reviewable in the diff.

License

MIT