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

@skillguard/cli

v3.1.22

Published

Security scanner for AI agent skill files

Downloads

1,087

Readme

@skillguard/cli

Security scanner CLI for AI agent SKILL.md files.

Quick start

npx @skillguard/cli scan SKILL.md

No saved CLI auth configured? CLI falls back to anonymous scanning (rate-limited).

Scan all skills in current repo

npx @skillguard/cli scan

Generate CI workflow (no secrets required)

npx @skillguard/cli workflow

Command help (man-like)

npx @skillguard/cli help scan
npx @skillguard/cli man workflow

Primary commands:

  • skillguard scan [path] — scan one file or recursively scan a directory
  • skillguard gate [path] — CI gate mode with deterministic pass/fail behavior
  • skillguard verify <path> — verify embedded SkillGuard signature via JWKS
  • skillguard limits — show anonymous/owner/agent quota state
  • skillguard auth login|status|logout — manage CLI auth state (OAuth or API key)
  • skillguard init — bootstrap local auth config and create default .skillguard.yml
  • skillguard workflow — generate GitHub Actions CI workflow
  • skillguard update — check for and install latest CLI version
  • skillguard help [command] / skillguard man [command] — detailed command help

Setup

npx @skillguard/cli init

Or via the shared backend OAuth flow:

npx @skillguard/cli auth login

Notes:

  • auth login opens the browser, completes backend OAuth, and stores bearer/refresh tokens locally.
  • auth login --api-key <key> stores an API key only.
  • neither auth login nor auth login --api-key writes .skillguard.yml
  • init remains the only command that bootstraps the project policy file

You can also provide the key via env:

export SKILLGUARD_API_KEY="sgk_..."

Usage

Scan one file

npx @skillguard/cli scan ./SKILL.md

By default, scan verifies embedded signature metadata (if present) and can skip API rescans for unchanged files (Source: embedded (verified)). When OAuth login is configured and no API-key override is active, scan, gate, and verify use SkillGuard API endpoints over bearer auth.

Stable skill stream ID (recommended for badges)

npx @skillguard/cli scan ./SKILL.md --skill-id team/daily-ops-assistant

Rules:

  • canonical format is namespace/name (lowercase ASCII, digits, hyphens)
  • priority is --skill-id > frontmatter skill_id > server-generated fallback
  • use --force-skill-id to normalize legacy/non-canonical ASCII IDs during transition
  • non-ASCII skill IDs are rejected to prevent NFKD canonicalization collisions

Live scan progress (default)

npx @skillguard/cli scan ./SKILL.md

Streams stage-by-stage updates in real time using SSE (POST /api/v2/scan/stream) and prints each stage reply as a full line immediately.
Plain stage progress is the default. Use --with-jokes to enable theatrical narration.
If streaming is unavailable, CLI automatically falls back to standard scan output.
ANSI colors can be disabled with NO_COLOR=1.

Edge-case behavior matrix

| Scenario | Behavior | Exit code | |---|---|---| | No CLI auth configured | Anonymous scan mode + guidance to sign in or add an API key | 0/1/2/3 by verdict | | Invalid API key (401) | Sanitized auth error, suggests skillguard auth login | 5 | | Anonymous rate limited (429) | Message suggests signing in or adding an API key | 5 | | Authenticated rate limited (429) | Message suggests waiting/upgrading | 5 | | Server 502/503 | Retries once, then sanitized API error | 5 | | Timeout / unreachable / DNS / TLS | Sanitized network timeout/error (no stack trace) | 5 | | Empty dir or no SKILL.md | Deterministic no-op notice | 0 | | Empty / binary / invalid UTF-8 SKILL.md | File skipped with warning; scan continues | 0 if nothing risky remains | | Oversized file (>1MB) | Warns and scans first 1MB only | Verdict exit code | | --format sarif + API failure | Emits valid SARIF (empty results) | 5 | | --output unwritable | Sanitized write error | 4 | | Redirected stdout / non-TTY | ANSI color and spinner UI disabled | Normal command exit code | | Unexpected exception | Catch-all message, no stack trace | 5 |

Scan a directory

npx @skillguard/cli scan ./skills --fail-on warning

JSON output for CI

npx @skillguard/cli scan ./skills --json > skillguard-report.json

CI gate (recommended)

npx @skillguard/cli gate ./skills

CI gate without API key (allow partial scope)

npx @skillguard/cli gate ./skills --allow-partial

Check remaining limits

npx @skillguard/cli limits

limits intentionally stays on the REST/API-key path in this phase. If only OAuth tokens are configured, the command falls back to anonymous limits and prints a hint.

Auth status and logout

npx @skillguard/cli auth status
npx @skillguard/cli auth logout

Generate and push workflow in one command

npx @skillguard/cli workflow --auto-gh-push

Worst-score CI exit code (recommended)

npx @skillguard/cli scan
# exit: safe=0, warning=1, dangerous=2

Verify signature

npx @skillguard/cli verify ./SKILL.md

Verification notes:

  • customer-facing verification should rely on signedSkillContent, signatureStatus, signatureType, and tamperEvident
  • do not rely on a raw top-level security object being present in customer-facing v2 responses

Options

scan

  • --json
  • --fail-on <SAFE|WARNING|DANGEROUS|BLOCKED> (v2 threshold, default: WARNING)
  • --fail-on-capability=<LOW|MEDIUM|HIGH|CRITICAL>
  • --fail-on-intent=<LOW|MEDIUM|HIGH>
  • --fail-on-policy-violation
  • --fail-on-status=<SCANNED>
  • --fail-on-hypothesis
  • --timeout <ms> (default: 180000)
  • --base-url <url> (default: https://skillguard.ai)
  • --api-key <key>
  • --yml <path> (override project policy YAML path)
  • --skill-id <namespace/name>
  • --force-skill-id
  • --dry-run
  • --quiet
  • --no-color
  • --embed (default: enabled; write returned signedSkillContent into existing frontmatter files)
  • --no-embed (disable file write-back)
  • --force (ignore embedded cache and always rescan via API)
  • --with-jokes (enable theatrical narration)
  • --skip-node-modules (default: enabled)
  • --scan-all (disable skip filters, scans everything recursively)

.skillguard.yml

The policy engine can read a repository-local .skillguard.yml file during v2 scans. By default, the CLI reads <git-root>/.skillguard.yml; use --yml <path> to override. skillguard init creates the default file when it is missing. This file is not generated by skillguard workflow; the workflow command only writes .github/workflows/skillguard.yml.

Supported format:

version: "1.0"
enforcement_mode: blocking
treat_hypothesis_as: IGNORE

rules:
  max_intent_suspicion: null
  capabilities:
    deny_file_reads: []
    allowed_network_destinations: []
  require_verified_if_capability: null

Supported values:

  • treat_hypothesis_as: IGNORE, WARN, FAIL
  • max_intent_suspicion: LOW, MEDIUM, HIGH
  • require_verified_if_capability: LOW, MEDIUM, HIGH, CRITICAL

Behavior notes:

  • IGNORE excludes hypothesis-only flows from policy evaluation.
  • WARN and FAIL include hypothesis-only flows in policy evaluation.
  • --fail-on-hypothesis is separate: it affects CLI exit behavior, not policy config.

Example:

version: "1.0"
treat_hypothesis_as: WARN

rules:
  max_intent_suspicion: MEDIUM
  capabilities:
    deny_file_reads:
      - ".env*"
      - "**/secrets/**"
    allowed_network_destinations:
      - "api.openai.com"
      - "*.githubusercontent.com"
  require_verified_if_capability: HIGH

gate

  • same core scan options as scan, except theatrical narration remains a scan-only toggle
  • supports --yml <path> with the same behavior as scan
  • defaults to CI gate behavior (--fail-on warning in threshold mode)
  • defaults to --no-embed behavior unless --embed is explicitly set
  • --allow-partial (do not fail-closed when API returns partial scope, e.g. anonymous Stage 1 only)

limits

  • --json
  • --timeout <ms> (default: 180000)
  • --base-url <url> (default: https://skillguard.ai)
  • --api-key <key> (optional)
  • --no-color

Behavior:

  • explicit --api-key and SKILLGUARD_API_KEY force API-key mode
  • stored config API key is used when present
  • OAuth-only auth falls back to anonymous limits in this phase

auth

  • auth login [--api-key <key>] [--base-url <url>]
  • auth status [--json] [--api-key <key>] [--base-url <url>]
  • auth logout

Behavior:

  • default auth login uses OAuth discovery + browser loopback callback
  • auth login --api-key is auth-only and does not create .skillguard.yml
  • init is the bootstrap/policy command
  • if both stored OAuth and stored config API key exist, scan / gate / verify prefer OAuth; limits prefers the stored config API key

workflow

  • --path <file> (default: .github/workflows/skillguard.yml)
  • --scan-path <path> (default: .)
  • --fail-on <safe|warning|dangerous> (default: warning)
  • --print (print yaml, do not write file)
  • --force (overwrite existing workflow file)
  • --auto-gh-push (git add/commit/push after write)
  • --every-push (trigger on every push, not just SKILL.md changes)

help / man

  • help [command]
  • man [command]

verify

  • --json
  • --timeout <ms>
  • --base-url <url>

Behavior:

  • with stored OAuth and no API-key override, verify calls SkillGuard API/JWKS endpoints
  • otherwise it falls back to local JWKS-based verification

Exit codes

  • scan / gate (v2 verdicts):
    • 0 SAFE
    • 1 WARNING
    • 2 DANGEROUS
    • 3 BLOCKED (policy FAIL)
  • verify:
    • 0 signature valid
    • 1 invalid/tampered/expired signature
  • limits:
    • 0 success
  • gate:
    • 0 below threshold
    • 1 threshold exceeded
  • workflow:
    • 0 success
  • auth:
    • 0 success
  • all commands:
    • 4 usage/input/config error
    • 5 network/API/runtime external failure

Embedded signature cache behavior

Cache hit requires all of:

  • embedded metadata.security block exists (legacy top-level security is also supported)
  • content hash matches security.content_sha256
  • Ed25519 signature verifies against SkillGuard JWKS
  • security.issuer is in trusted issuer allowlist (SKILLGUARD_TRUSTED_ISSUERS, default: https://skillguard.ai)
  • valid_until is not expired

If any check fails, CLI falls back to API scan. If gate cannot validate cache and API is unavailable, it fails closed with non-zero exit. --force bypasses both embedded cache checks and server-side scan reuse.

GitHub Actions example

name: SkillGuard Gate
on:
  pull_request:
    paths:
      - '**/SKILL.md'
      - '**/skill.md'
  push:
    paths:
      - '**/SKILL.md'
      - '**/skill.md'

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      actions: read
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: |
          fail_on=warning
          gate_args=(. --fail-on "$fail_on" --format sarif --output skillguard-results.sarif)
          if [ -z "${SKILLGUARD_API_KEY:-}" ]; then
            fail_on=dangerous
            gate_args=(. --fail-on "$fail_on" --format sarif --output skillguard-results.sarif)
            gate_args+=(--allow-partial)
          fi
          npx @skillguard/cli gate "${gate_args[@]}"
        env:
          SKILLGUARD_API_KEY: ${{ secrets.SKILLGUARD_API_KEY }}
      - uses: github/codeql-action/upload-sarif@v4
        if: always()
        with:
          sarif_file: skillguard-results.sarif

More info: skillguard.ai


v2 Pipeline (2.0.0)

scan — Deep analysis with multi-stage LLM pipeline

npx @skillguard/cli scan ./SKILL.md

Runs the v2 pipeline (Stage 0 static → Stage 1 Flash-lite → Stage 2 Flash-lite → Stage 3 Flash-lite cross-check via Gemini) with policy evaluation and attestation. When the API returns badge metadata, the CLI also prints a ready-to-paste README snippet:

[![Verified by SkillGuard](https://skillguard.ai/badge/skill/owner/skill.svg)](https://skillguard.ai/skill/owner/skill)

v2 options

scan includes v2 controls:

| Flag | Description | |------|-------------| | --fail-on <SAFE\|WARNING\|DANGEROUS\|BLOCKED> | Base v2 risk threshold (default: WARNING) | | --fail-on-capability=<LOW\|MEDIUM\|HIGH\|CRITICAL> | Fail if capability risk ≥ threshold | | --fail-on-intent=<LOW\|MEDIUM\|HIGH> | Fail if intent suspicion ≥ threshold | | --fail-on-policy-violation | Fail if any policy violation exists | | --fail-on-status=<SCANNED> | Fail if analysis level matches (require VERIFIED) | | --fail-on-hypothesis | Fail if any hypothesis flows detected | | --with-jokes | Enable theatrical narration while preserving the existing theatrical output |

v2 exit codes

| Code | Meaning | |------|---------| | 0 | SAFE — below threshold | | 1 | WARNING | | 2 | DANGEROUS | | 3 | BLOCKED (policy FAIL) | | 4 | Usage/config error | | 5 | Network/runtime failure |

v2 CI example

name: SkillGuard v2 Gate
on:
  pull_request:
    paths: ['**/SKILL.md', '**/skill.md']

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npx @skillguard/cli scan . --fail-on WARNING --fail-on-policy-violation

If your CI intentionally runs without SKILLGUARD_API_KEY, use partial mode and a dangerous threshold:

npx @skillguard/cli gate . --fail-on dangerous --allow-partial

v2 report output

The v2 CLI renders a box-drawing report including:

  • Risk verdict, capability risk, intent suspicion
  • Data flow evidence with context_before / context_after
  • Policy evaluation status and violations
  • "Evidence is for content hash <sha256>" notice
  • Ed25519 attestation signature block

Changelog

2.1.2

  • Added a TTY spinner for staged stream output while waiting between SSE replies
  • Improved theatrical stream UX with clearer "pipeline is alive" feedback during network/model pauses

2.1.1

  • Changed stream rendering from per-symbol typing to answer-by-answer line output
  • Changed theatrical header text to THE THREE MUSKETEERS AUDIT
  • Prevented duplicate full humor block when SSE stream succeeds (stream output remains stage-by-stage + final decree)

2.1.0

  • Added realtime SSE streaming path via /api/v2/scan/stream
  • Added resilient fallback to standard scan when streaming is unavailable
  • Added Node tests for SSE humor stream parser/render flow

2.0.0

  • v2 pipeline: 3-stage LLM analysis (Gemini Flash-lite across stages) with Zod validation and retry/fallback
  • scan v2 mode: v2-specific output and exit codes
  • 6 granular --fail-on-* flags: capability, intent, policy-violation, status, hypothesis
  • Policy engine: 4 standard policies + .skillguard.yml config rules (max_intent_suspicion, deny_file_reads, require_verified_if_capability)
  • Attestation: RFC 8785 canonical 8-field payload, Ed25519 signing, JWKS verification
  • Metering: VERIFIED quota per tier (FREE/TEAM/ENTERPRISE) with graceful degradation
  • Punycode normalization: IDN homograph protection via url.domainToASCII()
  • Evidence display: "Evidence is for content hash" in CLI output

Maintainer release notes

The npm package is published from GitHub Actions via Trusted Publishing.

One-time npm setup:

  • In npm package settings for @skillguard/cli, add a GitHub Actions trusted publisher.
  • Use repository Lionberg/SkillGuard.
  • Use workflow filename publish-cli.yml.

Release flow:

git tag cli-v3.1.14
git push origin cli-v3.1.14

Or run the Publish CLI workflow manually from GitHub Actions.

Safety checks in the workflow:

  • installs from the repo root with npm ci
  • builds @skillguard/shared, @skillguard/skill-security-core, and @skillguard/cli
  • runs npm test --workspace @skillguard/cli
  • verifies tag version matches packages/cli/package.json
  • publishes only from packages/cli