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

skill-linter

v0.1.4

Published

Linter, scorer, and evaluator for AI agent skill files (Agent Skills spec)

Readme

skill-linter

Linter for AI agent skill files following the Agent Skills specification.

47 rules across 5 categories: structural, frontmatter, content, security, and best practices. Supports text, JSON, SARIF, and GitHub Actions output formats. Optional LLM-powered deep analysis via Anthropic API or Google Cloud Vertex AI.

Install

npx skill-linter check ./my-skill

Or install globally:

npm install -g skill-linter

Run from Source

git clone https://github.com/aicatalyst-team/skill-linter.git
cd skill-linter
npm install
npm run build
npm link

This makes the skill-linter command available globally, so you can use it like the published package:

skill-linter check ./my-skill
skill-linter check https://github.com/org/repo
skill-linter rules

To rebuild after making changes:

npm run build

Or use watch mode for continuous rebuilds during development:

npm run dev

To unlink when done:

npm unlink -g skill-linter

Requires Node.js >= 22.

Quick Start

# Lint a skill directory
skill-linter check ./my-skill

# Lint multiple skills
skill-linter check ./skill-a ./skill-b

# Lint skills from a GitHub repo
skill-linter check https://github.com/org/repo
skill-linter check github:org/repo

# Target a specific skill in a repo
skill-linter check https://github.com/org/repo/tree/main/skills/my-skill

# Scaffold a new skill
skill-linter new my-new-skill

# List all 47 rules
skill-linter rules

Commands

skill-linter check <paths...>

Lint and evaluate skill directories.

skill-linter check ./my-skill
skill-linter check ./my-skill --format json
skill-linter check ./my-skill --format sarif > results.sarif
skill-linter check ./my-skill --format github
skill-linter check ./my-skill --strict
skill-linter check ./my-skill --fix
skill-linter check ./my-skill --deep
skill-linter check ./my-skill --deep --deep-provider vertex

# Remote GitHub repos
skill-linter check https://github.com/org/repo
skill-linter check https://github.com/org/repo/tree/main/skills/my-skill
skill-linter check github:org/repo

| Flag | Description | |------|-------------| | -f, --format <type> | Output format: text, json, sarif, github (default: text) | | --fix | Auto-fix fixable issues | | --deep | Run LLM-powered semantic analysis | | --deep-provider <name> | LLM provider: anthropic, vertex (auto-detected) | | --deep-model <name> | LLM model to use for deep analysis | | --strict | Treat warnings as errors | | --rule <id> | Run only specific rules (repeatable) | | --category <name> | Run only rules in a category (repeatable) | | -c, --config <path> | Path to config file | | --no-config | Ignore config files, use defaults | | -q, --quiet | Suppress warnings and info, show only errors | | -v, --verbose | Show all skills including those with no issues |

Exit codes: 0 = pass, 1 = errors found (or warnings with --strict), 2 = config error, 3 = CLI error.

skill-linter rules

List all available rules.

skill-linter rules
skill-linter rules --category security
skill-linter rules --severity error

skill-linter init

Create a .skill-linterrc.json config file in the current directory.

skill-linter new <name>

Scaffold a new skill directory with a SKILL.md template.

Rules (47)

Structural (4)

| Rule | Severity | Description | |------|----------|-------------| | structural/skill-md-exists | error | SKILL.md must exist | | structural/directory-structure | info | Warn on non-standard directories | | structural/no-extra-top-level-files | info | Warn on unexpected root files | | structural/file-references-valid | warning | Referenced file paths must exist |

Frontmatter (12)

| Rule | Severity | Fixable | Description | |------|----------|---------|-------------| | frontmatter/frontmatter-present | error | | Must have YAML frontmatter | | frontmatter/name-required | error | | name is required | | frontmatter/name-format | error | yes | 1-64 chars, lowercase, hyphens | | frontmatter/name-matches-directory | error | | Must match parent directory | | frontmatter/name-no-reserved-words | error | | Must not contain reserved words ('anthropic', 'claude') | | frontmatter/description-required | error | | description is required | | frontmatter/description-length | error | | 1-1024 characters | | frontmatter/description-quality | warning | | Must be substantive | | frontmatter/no-extra-fields | error | | Only 6 allowed fields | | frontmatter/compatibility-length | error | | Max 500 characters | | frontmatter/metadata-types | error | | Must be string-to-string map | | frontmatter/allowed-tools-format | warning | | Must be space-separated string |

Content (8)

| Rule | Severity | Description | |------|----------|-------------| | content/body-not-empty | warning | Body must not be empty | | content/body-token-budget | warning | Body under 5000 tokens | | content/body-line-limit | warning | Body under 500 lines | | content/has-headings | info | Should have headings | | content/no-html-in-body | info | No raw HTML tags | | content/references-depth | info | References one level deep | | content/no-backslash-paths | info | Use forward slashes for cross-platform compatibility | | content/no-ascii-art | info | No decorative ASCII art or box-drawing characters |

Security (9)

Based on Snyk ToxicSkills research and OWASP Agentic Skills Top 10.

| Rule | Severity | Description | |------|----------|-------------| | security/no-prompt-injection | error | Detects prompt injection patterns (context-aware: patterns in quotes, backticks, or code blocks are downgraded to warnings) | | security/no-base64-payloads | error | Detects obfuscated base64 content | | security/no-credential-access | error | Detects sensitive file/env access | | security/no-curl-bash | error | Detects pipe-to-shell execution | | security/no-remote-fetch | warning | Detects untrusted remote content | | security/no-obfuscation | error | Detects Unicode smuggling | | security/no-memory-poisoning | error | Detects agent config writes | | security/no-secret-literals | warning | Detects hardcoded secrets | | security/no-password-archives | error | Detects password-protected archives |

Best Practices (14)

| Rule | Severity | Description | |------|----------|-------------| | best-practices/description-has-trigger-words | info | Use imperative phrasing | | best-practices/description-no-first-person | warning | Use third-person voice in descriptions | | best-practices/progressive-disclosure | info | Split large bodies into references/ | | best-practices/scripts-are-referenced | info | Scripts should be referenced in body | | best-practices/has-examples | info | Should contain code blocks | | best-practices/gotchas-section | info | Non-trivial skills need gotchas | | best-practices/pinned-versions | info | Pin package versions | | best-practices/scripts-have-help | info | Scripts should support --help | | best-practices/no-generic-names | info | Avoid generic names like 'helper' or 'utils' | | best-practices/no-persona-instructions | warning | Provide instructions, not persona assignments | | best-practices/no-vague-instructions | info | Avoid vague directives like 'follow best practices' | | best-practices/no-time-sensitive-content | info | Avoid time-sensitive language that becomes stale | | best-practices/no-excessive-negation | info | Tell agents what to do, not what not to do | | best-practices/non-descriptive-filenames | info | Use descriptive filenames, not generic ones |

Configuration

Create .skill-linterrc.json (or use skill-linter init):

{
  "extends": "recommended",
  "rules": {
    "content/no-html-in-body": "off",
    "best-practices/gotchas-section": "warning"
  },
  "ignore": ["node_modules", ".git"]
}

Config is discovered via lilconfig: .skill-linterrc.json, .skill-linterrc.yaml, skill-linter.config.js, or package.json["skill-linter"].

Presets

| Preset | Description | |--------|-------------| | recommended | All spec rules as errors, best practices as info (default) | | strict | Recommended + best practices elevated to warnings | | security | Security rules only, all as errors |

Inline Suppression

Suppress specific findings with HTML comments in your SKILL.md:

<!-- skill-linter-disable-next-line -->
This line's diagnostics are suppressed.

<!-- skill-linter-disable-next-line security/no-prompt-injection -->
Only the specified rule is suppressed on the next line.

Remote GitHub Scanning

Pass a GitHub URL instead of a local path to scan skills hosted on GitHub:

skill-linter check https://github.com/org/repo
skill-linter check https://github.com/org/repo/tree/main/skills/my-skill
skill-linter check github:org/repo

Authentication uses gh CLI (if installed and logged in) with a fallback to the GITHUB_TOKEN environment variable. Public repos work without authentication.

Deep Analysis (--deep)

Optional LLM-powered semantic analysis that catches issues regex can't:

  • Subtle prompt injection and social engineering
  • Self-contradicting instructions
  • Description-body misalignment
  • System message impersonation
  • Script safety issues

When --deep is enabled, the LLM also triages static security findings and dismisses confirmed false positives (e.g., injection patterns that appear in documentation or examples). Dismissed findings are removed from the output with an explanation.

Setup

Anthropic API:

export ANTHROPIC_API_KEY=sk-ant-...
skill-linter check ./my-skill --deep

Google Cloud Vertex AI:

export GOOGLE_CLOUD_PROJECT=my-project
export GOOGLE_CLOUD_LOCATION=us-east5
skill-linter check ./my-skill --deep --deep-provider vertex

Requires installing the provider SDK:

npm install @anthropic-ai/sdk          # For Anthropic
npm install @anthropic-ai/vertex-sdk   # For Vertex AI

CI/CD

GitHub Actions

- uses: actions/setup-node@v4
- run: npx skill-linter check ./skills --format sarif > results.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

GitHub Annotations

- run: npx skill-linter check ./skills --format github

Programmatic API

import { lint, registerAllRules } from "skill-linter";

registerAllRules();
const result = await lint("./my-skill");
console.log(result.errorCount, result.diagnostics);

Contributing

See CONTRIBUTING.md for development setup, how to add rules, and PR guidelines.

AI agents: see AGENTS.md for codebase architecture and conventions.

License

MIT