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

@rhize/skill-forge

v0.7.0

Published

The supply-chain gate for agent skills — quarantine, scan, and curate agent skills before they enter your set

Readme

skill-forge

The supply-chain gate for agent skills.

Status: pre-release (built 2026-07-11)

This project is unrelated to the skillforge package on npm, which is a Claude Skills evaluation framework. skill-forge (this package, hyphenated) is a supply-chain security gate for skill installation — see the FAQ.

Why

Agent skills (Claude Code skills, and the equivalent extension formats emerging in Cursor and Codex) are now distributed the way npm packages were a decade ago: a public registry, a one-line install command, and no vetting step in between. skills.sh alone lists 600k+ skills. A single npx skills@latest add owner/name drops arbitrary third-party instructions, scripts, and tool bindings directly into a working agent's context and file system — with the same trust model as copy-pasting a shell script from a stranger.

skill-forge does not replace that install command; it wraps it. Every candidate skill is routed through quarantine → profile → safety scan → overlap analysis → report → an explicit promote/hold/reject decision, before it is allowed anywhere near your working skill set.

Quickstart

npx @rhize/skill-forge init

Optional, but recommended first: init detects which coding agents you have installed — the matrix covers 73 known agents (Claude Code, Codex CLI, Cursor, Windsurf, OpenCode, Gemini CLI, and 67 more; see src/agents.ts), and every entry's skill-directory paths are verified directly against the vercel-labs/skills CLI's own source, not just its README — none are unverified/community guesses today. (The schema carries a verified: false flag for any future entry that can't be confirmed that way; it's unused as of this release.) init lets you pick which of their skill directories should be gated, a default promotion target, and an optional agent to hand follow-up prompts off to (see --ingest). No configuration is required for a first run either way — skip init and skill-forge defaults to <cwd>/.claude/skills as its promotion target and ~/.skill-forge/quarantine as its sandbox (and offers to run init for you the first time add/scan/list/status runs with no config present, in an interactive terminal). See docs/configuration.md for the full field reference.

npx @rhize/skill-forge add <owner>/<skill-name>

One command runs the whole gate:

  1. Installs the source into an isolated quarantine sandbox — never your live skill set.
  2. Profiles it: name, version, license, structure, declared MCP/tool dependencies.
  3. Runs the safety gate (a built-in deny-pattern ruleset, always; SkillSpector too, if installed).
  4. Runs overlap analysis against your configured skill set, if one is configured.
  5. Prints a report and asks you to promote, hold, or reject the candidate.

To gate a skill without installing it (always cleans up afterward):

npx @rhize/skill-forge scan <owner>/<skill-name>

<source> accepts a skills.sh owner/name slug, a git URL (https://..., git@..., or anything ending in .git), or a local filesystem path.

Commands

skill-forge init [options]                     Detect installed agents and set gate targets / handoff agent
skill-forge add <source> [options]             Quarantine-install a skill and run it through the gate
skill-forge scan <source> [options]            Gate a skill without installing it (always cleans up)
skill-forge evolve <skill-dir> [options]       Self-evolve an installed skill via SkillOpt-Sleep, re-gate, decide (Pro)
skill-forge list                               List skills currently held in quarantine
skill-forge status                             Show configuration and quarantine summary

init

skill-forge init              # interactive: pick targets, default target, handoff agent
skill-forge init --defaults   # non-interactive: all detected agents, first as default (CI)
skill-forge init --list       # print detected agent skill roots and exit — no writes

Probes the known agent matrix (src/agents.ts) for both project-relative (.claude/skills, ...) and global (~/.codex/skills, ...) skill directories that already exist on disk, then writes skillsRoots, agents, defaultTarget, and (if you pick a handoff agent) handoffCommand to config.json. Safe to re-run any time — it always starts from your existing config and only overwrites the fields it's responsible for. If no config.json exists yet, add/scan/list/ status offer to run this for you on first use (skipped entirely for --json/--yes/non-TTY invocations, so scripted runs never block on a prompt).

add

skill-forge add owner/name
skill-forge add https://github.com/owner/repo.git --target ./.claude/skills
skill-forge add ./local-skill-dir --yes
skill-forge add owner/name --json
skill-forge add owner/name --yes --ingest

Installs the source into a quarantine sandbox, then runs it through the gate: profile → safety scan → overlap analysis against the configured skills root (Pro) → report. Nothing touches the target skills root until you decide.

| Option | Effect | |---|---| | (none) | Prompts you to promote, hold, or reject the candidate. | | -y, --yes | Skips the prompt and honors the gate verdict: a block safety verdict is rejected (process exits nonzero); anything else (pass/warn) is promoted. | | -t, --target <dir> | Skills root to promote into. Defaults to the config's defaultTarget, then skillsRoots[0]. | | --json | Prints the gate result (profile, safety findings, overlap) as JSON instead of the terminal report box. Implies non-interactive: the decision is made the same way --yes makes it (verdict decides promote/hold/reject), never an interactive prompt. | | --ingest | Pro (free during the 0.x beta). After a successful promote, hands off to a coding agent — see Ingestion handoff. |

A promoted skill gets a provenance entry appended to <target>/SOURCES.md, and every promote or hold decision is recorded to ~/.skill-forge/queue.json (or $SKILL_FORGE_HOME/queue.json) — see docs/queue-schema.md for the entry schema. A reject writes neither — nothing is left behind to record. These are Pro features that run free during the 0.x beta (see docs/pro.md): with no valid license, add still writes them, and prints a one-line notice above the report instead of skipping them.

add/scan also accept --artifact mcp (plus add-only --mcp-target <file>/--force) to gate an MCP server instead of a skill — see MCP gating below.

scan

skill-forge scan owner/name
skill-forge scan owner/name --json

Runs the same gate pipeline as add (profile → safety → overlap → report) but never promotes anything — the quarantine sandbox is always cleaned up afterward, on success or failure. Exits nonzero when the safety verdict is block. --json prints the same gate-result payload shape as add's.

evolve (v0.7)

skill-forge evolve .claude/skills/my-skill
skill-forge evolve .claude/skills/my-skill --yes
skill-forge evolve .claude/skills/my-skill --dry-run
skill-forge evolve .claude/skills/my-skill --backend claude --yes

Pro (free during the 0.x beta). Orchestrates microsoft/SkillOpt's skillopt-sleep CLI (pip install skillopt) to propose a self-evolution of an already-installed skill — harvest recent sessions, generate a candidate replacement SKILL.md/CLAUDE.md, and stage it — then runs the staged proposal, never the live skill, back through skill-forge's own static safety ruleset before you decide anything. SkillOpt-Sleep's own validation gate is score-only; it never content-vets the generated markdown. This closes that gap.

| Option | Effect | |---|---| | --project <dir> | Project dir passed to SkillOpt-Sleep as --project. Defaults to cwd. | | --dry-run | Uses SkillOpt-Sleep's dry-run subcommand — report only, nothing staged. | | --backend <name> | SkillOpt-Sleep backend. Defaults to mock (offline, deterministic, no network). | | --lookback-hours <n> | Hours of session history for SkillOpt-Sleep to harvest. | | -y, --yes | Skips interactive prompts (the disclosure confirm below, and the promote/hold/reject prompt) and honors the re-gate verdict automatically. | | --json | Prints the re-gate result as JSON instead of the terminal report. Implies non-interactive, same as add's --json. | | --force | Allows re-adopting a staging dir whose proposed content already matches the live skill (see the double-adopt guard below). |

Requires skillopt-sleep on PATH — skill-forge never installs it for you. If it's missing, evolve prints pip install skillopt + a docs pointer and exits, rather than attempting an auto-install (the same "detect, don't install" discipline the rest of the gate follows).

Data boundary. The default mock backend is fully offline — harvesting and proposal generation both run locally, no session data leaves the machine. Any other backend (claude, codex, azure_openai, ...) sends truncated excerpts from harvested sessions and derived tasks to the provider you selected; per SkillOpt-Sleep's own docs this is not currently guaranteed to be secret-free. evolve prints that disclosure and requires either --yes or an interactive y/N confirmation before a non-mock run proceeds — --json is non-interactive, so a non-mock run under --json without --yes is refused rather than silently sending data off-machine.

Re-gate. SkillOpt-Sleep only ever stages a proposal (<project>/.skillopt-sleep/staging/<timestamp>/ — full replacement files, never auto-adopted). evolve copies just proposed_SKILL.md (and proposed_CLAUDE.md, if present) into a fresh temporary directory and runs skill-forge's own static safety ruleset over that copy — the same one add/scan use, at your configured strictness. report.json/diagnostics.json (SkillOpt-Sleep's own redacted holdout evidence) are never scanned. The result renders through the same terminal report / --json shape as add/scan.

Decision. Same promote/hold/reject semantics as add: --yes/--json honor the re-gate verdict (a block is rejected); otherwise you're prompted.

  • promote — runs SkillOpt-Sleep's own adopt --staging <dir> (which backs up the live file(s) before copying the proposal over them), then records a provenance entry to the target skill's SOURCES.md and a pending-ingestion queue entry (origin: "evolve", see docs/queue-schema.md) so a later ingest pass reviews the evolution rather than an external source.
  • hold — leaves the staging dir exactly as SkillOpt-Sleep produced it (its own status command still lists it); report.md has the full evidence.
  • reject — deletes the staging dir.

Double-adopt guard. SkillOpt-Sleep's adopt has no confirmation of its own, and adopting the same staging dir twice overwrites its backup — the pre-evolution original would be lost. Before adopting, evolve refuses (unless --force) when the staged proposal is already byte-identical to the live skill it would replace, since that's the signature of a staging dir that was already adopted once.

list / status

list shows what's currently held in quarantine (installed via add, answered "hold", not yet promoted or rejected). status shows the resolved configuration (skills roots, quarantine dir, strictness) plus a count of held entries.

MCP gating (v0.5)

add and scan can also gate an MCP server instead of a skill — the same quarantine → profile → safety scan → overlap analysis → report → promote/hold/reject pipeline, applied to an MCP server candidate rather than a skill:

skill-forge scan ./my-mcp-server --artifact mcp
skill-forge add @scope/some-mcp-server --artifact mcp --mcp-target ~/.claude.json
skill-forge add https://github.com/owner/mcp-server.git --artifact mcp --yes

Pass --artifact mcp explicitly — skill-forge never guesses. In particular, an npm package name (@scope/name, or a bare some-mcp-server name) is only treated as an npm source with this flag; without it, the same string resolves as a skills.sh owner/name slug instead (no ambiguity guessing between the two).

Source forms

| Form | Example | How it's fetched | |---|---|---| | Local directory | ./my-mcp-server | Copied into quarantine, same as a local skill source. | | Git URL | https://github.com/owner/mcp-server.git | Shallow-cloned into quarantine, same as a git skill source. | | npm package | @scope/name or some-mcp-server | npm pack <name> --ignore-scripts --pack-destination <quarantine>, then tarball extraction only — never npm install, never lifecycle scripts. Every tarball member path is validated (absolute paths and .. segments are rejected) before extraction. |

What's gated

Safety runs the same built-in deny-pattern ruleset used for skills (curl|bash, credential-file access, etc.) plus MCP-specific rules: inline credential values in config/env (quoted or unquoted), unpinned npx -y launch commands (a moving/dist tag like @latest counts as unpinned, and npx is recognized by basename so a full path or npx.cmd can't evade it), --dangerously-*/--no-sandbox flags, and filesystem-root launch args — see the MCP safety ruleset table. Overlap analysis (Pro, free during the 0.x beta) ranks the candidate against the server entries already present in your configured mcpTargets files, instead of against a skills root.

Capability profile (v0.6). The report also includes a static capability summary — tool, resource, and prompt counts, plus a declaredConfidence (high/partial/none) — parsed from the candidate's package.json, any shipped .mcp.json/manifest, and MCP SDK source-text patterns (server.tool(...), setRequestHandler(ListToolsRequestSchema, ...), etc.):

Artifact type       : mcp
Capabilities        : 2 tools, 1 resource, 0 prompts (declaredConfidence: high)

This is free (it's profiling, not a Pro feature) and never derived by running the candidate server — anything that can't be determined from source text is reported as undetermined rather than discovered by executing it. --json includes the full tools/resources/prompts name lists under profile.capabilities.

Promote semantics

Promoting an MCP candidate writes ONE server entry into a target MCP config file's mcpServers map — it never touches a skills root:

{ "mcpServers": { "<name>": { "command": "...", "args": ["..."], "env": { "SOME_KEY": "" } } } }
  • Env values are never copied from the candidate — every declared env var is written as an empty string, and skill-forge prints the var names you need to fill in yourself.
  • Target resolution: --mcp-target <file>, else config.mcpTargets[0], else <cwd>/.mcp.json.
  • Existing target file: backed up first to <file>.bak-<timestamp>.
  • Existing same-name server entry: refused unless --force is passed.
  • Missing target file/parent dirs: created.
  • A candidate config listing more than one server gates/promotes the first (same "N found — using the first" convention add/scan already use for a multi-skill source), noted on stderr.

There's no MCP equivalent of the skill provenance ledger (SOURCES.md) — the pending-ingestion queue (Pro) and --ingest handoff both apply the same way, keyed on the written config file path instead of an installed skill directory. The queued entry carries the candidate's static capability profile (capabilities, v0.6, above), so a --ingest handoff run on an MCP promote has real material to work with: assets/ingest-prompt.md branches on artifactType: "mcp" and walks the same five-verb decide (DEFER/ABSORB/FORK/REJECT/WATCH) applied to a server instead of a skill — compare declared capabilities against what's already configured, then keep/tighten/remove the promoted config entry accordingly. Same static-only rule as the CLI's own profiling: the deep pass never runs or installs the candidate server to inspect it.

TOML-format agents: detect-only. skill-forge init detects MCP config files for every known agent, including TOML-format ones (Codex CLI's config.toml) — they show up in init's MCP-target list and can be selected into config.mcpTargets for overlap ranking. But promote only writes JSON-shaped targets ({ "mcpServers": { ... } }); pointing --mcp-target at (or letting config.mcpTargets[0] resolve to) a TOML file fails when the promote step tries to parse it as JSON. Detection/overlap is agent-format-agnostic; writing is JSON-only.

Free vs. Pro

| Capability | Free | Pro | |---|:---:|:---:| | Quarantine install (skills.sh slug / git / local path) | ✓ | ✓ | | Profile (name, version, license, structure, MCP/tool deps) | ✓ | ✓ | | Safety gate — built-in ruleset + SkillSpector shell-out | ✓ | ✓ | | Terminal report + --json | ✓ | ✓ | | Promote / hold / reject decision | ✓ | ✓ | | init setup wizard (agent detection, gate targets, handoff agent) | ✓ | ✓ | | Overlap analysis against your configured skill set | | ✓ | | Provenance ledger (SOURCES.md audit trail) | | ✓ | | Pending-ingestion queue + --ingest handoff | | ✓ | | evolve — SkillOpt-Sleep self-evolution, re-gating, provenance, queueing (v0.7) | | ✓ | | Set-level organizer (capability registry, redundancy, dependency graph) | | ✓ |

Free is the complete safety gate on its own — quarantine, profile, safety scan, and an explicit promote/reject decision, with nothing held back. Pro is the curation layer on top: whether a new candidate duplicates something you already have, and an ongoing provenance record across your whole skill set rather than a single install-time decision.

Everything free until 1.0. This is a 0.x beta build, and the Pro tier's runtime license check is intentionally asleep for the whole 0.x line: overlap analysis, the provenance ledger, and the pending-ingestion queue / --ingest handoff all run for everyone, licensed or not. Without a valid license (SKILL_FORGE_LICENSE env var or config.json's licenseKey, verified offline), add prints a one-line notice — Pro feature (...) — free during the 0.x beta; will require a license at 1.0. — above the report (or in the --json payload's notices array) and otherwise runs exactly as a licensed run would. At 1.0 the lock re-arms and these features go back to requiring a valid key. The set-level organizer and the skills.sh partner-audit enrichment are not yet exposed by any CLI command, licensed or not, beta or not. See docs/pro.md for the per-feature implementation status.

Security model

  • Quarantine-first. Every source — skills.sh slug, git URL, or local path — is installed into an isolated sandbox (~/.skill-forge/quarantine/<id>/) before anything is inspected. Nothing reaches your working skill set without an explicit promote decision.
  • Built-in safety ruleset, always on, fully offline. A deny-pattern scan (curl/wget-into-shell, base64-obfuscated exec, reverse shells, recursive force-delete, credential-file access/exfil, dynamic eval, shell=True subprocess, persistence via shell rc files or cron, sudo usage) runs against every candidate with no external dependency and no network call. See docs/gate-policy.md for the full rule table.
  • Block on HIGH/CRITICAL. Any finding at HIGH or CRITICAL severity blocks the candidate outright (verdict block); a lower-severity finding produces warn; a clean scan is pass. --yes honors this: block is rejected automatically.
  • npm-sourced MCP candidates: --ignore-scripts + tarball member validation. An npm-package MCP source is fetched with npm pack --ignore-scripts, and the tarball's member list is checked with tar -tzf before extraction — any absolute path or .. path segment refuses the extract with an error instead of running tar -xzf (a path-traversal guard against a malicious tarball writing outside the quarantine sandbox).
  • SkillSpector, when installed. If SkillSpector (Apache-2.0) is on PATH, skill-forge shells out to it (--no-llm by default, so scanned skill content is never sent to an external LLM provider) and merges its findings into the same report. Purely additive — its absence never blocks the gate.
  • skills.sh partner audits — implemented, not yet wired into the CLI pipeline. skill-forge ships a client for skills.sh's documented /api/v1/skills/audit endpoint (partner verdicts from Socket, Snyk, Gen Agent Trust Hub, Runlayer, ZeroLeaks), gated on a user-supplied VERCEL_OIDC_TOKEN. The client exists (src/gate/skillsSh.ts) but add/scan do not call it yet in this build — see docs/gate-policy.md for current status.

Ingestion handoff (--ingest)

skill-forge deliberately doesn't try to decide what to extract from a skill worth adopting — that deeper judgment (which patterns to keep, whether to absorb into an existing skill vs. fork a new one, verifying the result beats baseline) is a job for a coding agent, not the gate. --ingest hands a promoted skill off to one, running the bundled, agent-neutral prompt at assets/ingest-prompt.md (Claude Code users get a deeper experience via the companion rhize-skill-forge plugin skill, but the bundled prompt works with any agent). The same flag works on an MCP server promote (--artifact mcp --ingest, v0.6): the bundled prompt branches on the queue entry's artifactType and runs the matching decide pass — see MCP gating above.

skill-forge add owner/name --yes --ingest

The command that gets run, in order:

  1. config.handoffCommand — an argv-style template (["claude", "-p", "{prompt}"]-shaped) set by skill-forge init's "handoff agent" prompt, with {path} (the installed skill) and {prompt} (the bundled prompt file) substituted in. Never shell-parsed, so it's safe even if a substituted path contains shell metacharacters.
  2. Otherwise, the first known agent binary found on PATH (claude, codex, cursor-agent, windsurf, opencode, gemini), invoked generically with the prompt.
  3. Otherwise, skill-forge prints the prompt path and skill path for you to hand off yourself.

Every promote or hold is recorded to the pending queue (~/.skill-forge/queue.json) regardless of --ingest — nothing is lost if you skip the handoff. See docs/queue-schema.md for the entry schema.

Configuration

Config lives at ~/.skill-forge/config.json (or $SKILL_FORGE_HOME/config.json). Run skill-forge init to generate it interactively, or write it by hand:

{
  "skillsRoots": ["/path/to/.claude/skills"],
  "quarantineDir": "/path/to/quarantine",
  "strictness": "block-high",
  "defaultTarget": "/path/to/.claude/skills",
  "agents": [{ "id": "claude-code", "skillsRoot": "/path/to/.claude/skills" }],
  "handoffCommand": ["claude", "-p", "Read {prompt} and follow its instructions for the skill installed at {path}"]
}

Missing keys fall back to defaults (skillsRoots: ["<cwd>/.claude/skills"]); defaultTarget, agents, and handoffCommand are optional and only written by init. Full field reference, including current caveats, in docs/configuration.md.

FAQ

Is this related to the skillforge npm package? No. skillforge is a Claude Skills evaluation framework — it tests whether a skill performs well. skill-forge (this package, hyphenated) is a supply-chain security gate for skill installation — it decides whether a skill is safe and non-redundant before it ever runs. Same neighborhood, different problem, name collision only.

Does skill-forge replace npx skills@latest add? No, it wraps it. add uses the same install mechanisms (skills.sh, git, local copy) but stages the result in a quarantine sandbox and runs it through the gate before anything touches your live skill set.

What happens if I never configure a skills root? add/scan still run — profiling and the safety scan work on any candidate independent of a skills root. Overlap analysis is skipped (a message goes to stderr, it isn't fatal) if skillsRoots[0] doesn't resolve to a directory containing existing skills.

Does the safety gate call out to the network? The built-in ruleset is fully offline. SkillSpector, if installed, runs with --no-llm by default. See docs/gate-policy.md.

Is there a license key or activation step? An offline-verified license key exists (SKILL_FORGE_LICENSE env var or config.json's licenseKey), but there's no license/activate CLI command — you set the key via config or environment, not a command. Through the 0.x beta the key doesn't gate anything: overlap analysis, the provenance ledger, and the pending-ingestion queue / --ingest handoff all run for everyone, with a one-line "free during the beta" notice if no valid key is set. See docs/pro.md for details.

License

skill-forge is open-core with a split license (as of v0.2.0):

  • Free tier — MIT. Everything except the Pro modules: quarantine install, profile, safety gate, report, promote/hold/reject. See LICENSE-MIT.
  • Pro modules — Rhize Commercial License. src/license.ts, src/gate/overlap.ts, src/provenance.ts, src/queue.ts (overlap analysis, provenance ledger, pending queue / --ingest handoff). The source is available to read and audit, but production use of Pro functionality requires a license key — see LICENSE-COMMERCIAL.

LICENSE is the authoritative map of which files fall under which license. Versions up to and including 0.1.0 were published entirely under MIT.