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

@coroboros/skillward

v0.1.2

Published

Take an agent skill apart before installing it — the complete deterministic scanner ensemble, fused into one offline verdict.

Readme

skillward

Take an agent skill apart before installing it — the complete deterministic scanner ensemble, fused into one offline verdict.

skillward runs every maintained offline scanner that adds a unique detection axis over an untrusted skill, fuses their overlapping findings into one deduplicated report, and returns a --fail-on verdict for CI. The scanners live in a from-source Docker bundle; the Rust binary orchestrates, fuses, and gates.

crates.io ci license stars skills coroboros.com

Contents

Requirements

  • macOS (Apple Silicon or Intel), Linux, or Windows.
  • Docker for the default sandbox — skillward runs the scanner bundle in a hardened container. --sandbox host drops this requirement in exchange for a local scanner install.
  • The first skillward install pulls the scanner bundle from the GitLab Registry (registry.gitlab.com/coroboros/security/infrastructure/skillward-bundle) — a multi-hundred-MB, multi-arch image (Python, semgrep, the trivy DB), container-scanned and cosign-signed. It is cached; subsequent scans are offline. GHCR (ghcr.io/coroboros/skillward-bundle) and Docker Hub (coroboros/skillward-bundle) mirrors are available via SKILLWARD_BUNDLE_IMAGE.

Install

cargo binstall skillward            # prebuilt binary via cargo
brew install coroboros/tap/skillward
npx @coroboros/skillward            # Node toolchains

From source:

cargo install --path .

Then pull the scanner bundle once:

skillward install

Usage

skillward ./my-skill                 # one skill
skillward ./skills                   # a directory of skills, scanned in parallel
skillward https://github.com/owner/skill   # a remote repo, cloned and hardened
skillward ./my-skill --fail-on critical    # only critical findings fail the gate
skillward ./my-skill --format json -o report.json
skillward ./my-skill --without cisco,semgrep   # trim the ensemble
skillward ./my-skill --sandbox host  # use locally-installed scanners, no Docker
skillward install                    # pull the bundle
skillward update                     # re-pull the pinned bundle

Run skillward --help for the full flag list.

Why this exists

Vetting an untrusted skill by hand means running several scanners, each with its own flags and output format, then trusting that none of them quietly reached the network and that none was skipped. skillward runs the whole maintained set at once and collapses the result into a single verdict.

  • Completeness over any one tool. No single scanner catches everything, so skillward runs the union of nine and makes their overlap read as signal: a site flagged by four tools is one finding at raised confidence, not four rows of noise.
  • Offline and deterministic. The default sandbox severs the network for every scan, so a tool's optional LLM or CVE-lookup call cannot reach out, and the same skill yields the same verdict every run.
  • Fails loud, never silent. A scanner that crashes, times out, or is missing becomes a visible tool-error, and a fully dead engine exits non-zero — a degraded run never reads as a clean skill.
  • A gate, not a wall of output. One --fail-on verdict per skill and a stable exit code, so it drops into CI without parsing.
  • Inherited detection. Rules come from the upstream tools. The bundle owns package pins, reviewed rule commits, and offline data refreshes; skillward orchestrates, fuses, and gates — it never authors detection.

How it works

For security, coverage completeness is the requirement: no single scanner catches everything, so skillward runs the union and makes the overlap read as signal rather than noise.

  1. Resolve the target — a skill folder, a directory of skills, or a remote URL (cloned into a hardened, throwaway checkout).
  2. Run the complete ensemble over each skill, every tool in its own isolated container, in parallel.
  3. Normalize each tool's SARIF into one finding model with a unified severity scale and a rule-class taxonomy.
  4. Fuse — dedup by (class, file, line), correlate across tools (the same site flagged by four tools becomes one finding citing all four, at raised confidence), and sort so corroborated criticals lead.
  5. Gate — a per-skill verdict; exit 20 when any finding reaches --fail-on.

Detection rules are never authored here. They are inherited from the upstream tools; package pins, reviewed rule commits, and offline data refreshes live in the bundle source-of-truth repository, coroboros/security/infrastructure/skillward-bundle — multi-arch, container-scanned, and cosign-signed with a CycloneDX SBOM.

Scanners

The default ensemble — every maintained deterministic scanner that adds a unique axis, all offline-capable. --without trims it; --with re-adds a tool excluded by --without.

| Tool | Language | License | Detection axis | | --- | --- | --- | --- | | skillspector | Python | Apache-2.0 | Deepest SKILL.md taint → exec | | cc-audit | Rust | MIT | Claude Skills / Hooks / MCP config audit | | aguara | Go | Apache-2.0 | Supply-chain across 9 ecosystems + agent content | | cisco skill-scanner | Python | Apache-2.0 | Multi-engine static — YAML, YARA, bytecode, pipeline taint | | agent-audit | Python | MIT | OWASP Agentic Top 10, tool-boundary taint | | ramparts | Rust | Apache-2.0 | MCP servers + agent skills, static | | semgrep | — | LGPL-2.1 | AST/dataflow with the OWASP-LLM ruleset | | trivy | Go | Apache-2.0 | SCA + misconfiguration + secrets | | gitleaks | Go | MIT | Secrets — regex + entropy |

Determinism and isolation

Determinism is enforced at the sandbox, not trusted per-tool. Every scanner runs inside the bundle image with:

--network=none --read-only --cap-drop=ALL --security-opt=no-new-privileges
--pids-limit=512 --memory=2g

The network is severed, so a tool's optional LLM or CVE-lookup stage cannot reach out — offline DBs (trivy's vuln DB, the semgrep ruleset) are baked into the image. The same input produces the same report. A tool that crashes, times out, or emits nothing becomes a tool-error on the report rather than aborting the run — and a dead engine (every tool failing) fails loud with exit 12, never a silent PASS.

Remote targets are cloned depth-1 with hooks disabled, submodules and LFS not fetched, and symlinks written inert; an escaping-symlink sweep runs on top, and the scan itself happens inside the --network=none --read-only container.

Targets

| Target | Behavior | | --- | --- | | A skill folder (SKILL.md present) | Scanned as one skill. | | A directory of skills | Each SKILL.md root discovered and scanned in parallel. | | A remote https Git URL | Cloned into a hardened throwaway checkout, then discovered as above. |

--offline refuses remote targets; the default Docker sandbox already severs the network for every scan regardless.

Options

Every flag; skillward --help prints the same surface.

| Option | Default | Description | | --- | --- | --- | | <targets>... | (required) | Skill folders, directories of skills, or https Git URLs. See Targets. | | --fail-on <SEVERITY> | high | Fail (exit 20) at or above this severity: none, low, medium, high, critical. | | --format <FORMAT> | terminal | Report format: terminal, markdown, json, sarif. See Output formats. | | --output <FILE>, -o | stdout | Write the report to a file instead of stdout (color stripped). | | --without <TOOLS> | none | Tools to drop from the ensemble, comma-separated. See Scanners. | | --with <TOOLS> | none | Tools to re-add (e.g. one dropped by --without), comma-separated. | | --sandbox <MODE> | docker | Where scanners run: docker (hardened bundle) or host (local binaries). | | --jobs <N>, -j | device-aware | Worker threads for the scan; skills and their tools share the pool. | | --offline | false | Refuse remote targets; the Docker sandbox already severs the network per scan. | | --no-color | false | Disable colored output. |

| Command | Description | | --- | --- | | install | Pull the scanner bundle image (one-time, needs Docker). | | update | Re-pull the pinned bundle image. | | skills list · skills get [name] | List or print the bundled agent skill. See Agents. |

Environment variables

| Variable | Default | Description | | --- | --- | --- | | SKILLWARD_BUNDLE_IMAGE | the default bundle ref | Override the scanner bundle image — a tag or an @sha256: digest, for a byte-reproducible or air-gapped scan. |

Output formats

| --format | Contents | | --- | --- | | terminal | Colored summary — verdict, corroboration, per-finding lines (default). | | markdown | A Markdown report with a findings table per skill. | | json | A versioned schema for tooling — verdict, fused findings, sources, tool-errors. | | sarif | SARIF 2.1.0, one run per contributing tool, for code-scanning consumers. |

-o <file> writes the report to a file (color is stripped); otherwise it prints to stdout, with the plan banner and status on stderr.

Agents

skillward ships an agent skill — its own usage-and-triage guide — for coding agents. Install it into an agent:

npx skills add coroboros/skillward

Or read it inline without installing:

skillward skills get skillward   # print the bundled skill to stdout
skillward skills list            # list bundled skills

skillward --help carries an Agents: footer with the same pointers. The skill drives the CLI to scan a skill, a directory of skills, or a remote URL, then triages the report into an install / don't-install / remediate call. The same Markdown is the single source — embedded in the binary for skills get and published for npx skills add.

Exit codes

Stable across releases — only ever added, never renumbered.

| Code | Meaning | | --- | --- | | 0 | clean, or all findings below --fail-on | | 1 | unexpected error (e.g. failed to write the report) | | 2 | usage error (bad flag or value, no targets) | | 10 | target not found | | 11 | remote clone failed, an unsupported transport (http/ssh/git/file), or refused under --offline | | 12 | scan-engine failure (Docker unavailable, or no scanner produced output) | | 13 | scanner bundle image unavailable (not pulled, or a pull failed) | | 14 | refused: a --sandbox host target has symlinks escaping the skill root | | 20 | findings at or above --fail-on |

Limitations

  • Docker by default. The complete ensemble ships as a container image; the first pull is large. --sandbox host runs locally-installed scanners instead.
  • Static, read-only. skillward never executes a scanned skill — it cannot catch a threat that only manifests at runtime.
  • Detection is inherited. Coverage is exactly what the bundled tools detect; skillward adds completeness, fusion, and a stable gate, not new rules.

Compared to alternatives

Most tools that vet an agent skill are a single scanner: one engine, one detection philosophy, run directly on the files. A couple orchestrate several scanners, but each drops something skillward keeps: isolation, offline operation, corroboration, or a gate.

| Tool | Approach | Multiple external tools | Sandboxed scan | Offline | Cross-tool corroboration | Stable CI gate | | --- | --- | :---: | :---: | :---: | :---: | :---: | | skillward | 9 deterministic scanners, fused | yes | yes | yes | yes | yes | | SkillSpector | regex + AST + optional LLM | no | no | mostly | no | — | | ramparts | YARA + LLM + OWASP-MCP tags | no | no | no | no | partial | | cc-audit | AI-free regex rules | no | no | yes | no | yes | | agent-audit | AST + taint + secrets | no | no | yes | no | — | | Cisco skill-scanner | 8 internal engines + meta-analyzer | internal | no | no | yes | — | | shield-claude-skill | wraps Semgrep + gitleaks + Trivy | yes | no | no | dedup only | no | | semgrep / gitleaks / trivy, alone | one engine, run by hand | no | no | yes | no | per-tool |

Cells reflect each tool's own docs and source; means the property is not established by its primary sources, not a confirmed "no". The nuances: SkillSpector's LLM stage is optional and its deterministic core is offline; ramparts connects to live MCP endpoints and an LLM; Cisco's LLM, VirusTotal, and AI-Defense layers need API keys and a network, and its eight engines are internal modules, not independent tools; shield-claude-skill deduplicates by (file, line, tool), so the same issue from two tools is never merged or confidence-raised, and it ships no isolation and no exit-code gate.

skillward's niche is the intersection none of them occupy: multiple deterministic external scanners, each run inside a hardened --network=none container, fused offline with cross-tool corroboration, behind a stable-exit --fail-on gate.

Contributing

Bug reports and PRs welcome.

  • Open an issue before non-trivial PRs.
  • Commits follow Conventional Commits.
  • Run cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test before pushing.
  • A new scanner must run deterministically and offline and add an axis the ensemble does not already cover; add its adapter and mirror its argv in the bundle repo's smoke-test.sh (coroboros/security/infrastructure/skillward-bundle).
  • Target the main branch.

License

Apache 2.0