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

@skillbolt/lint

v1.0.1

Published

SKILL.md format linter for Skillbolt - check and fix your AI agent skills

Readme

@skillbolt/lint

技能文件 lint 工具,检查技能文件的质量、格式和最佳实践,提供自动修复功能。

功能特性

  • 多规则支持: 内置多种 lint 规则,涵盖格式、样式和最佳实践
  • 自动修复: 支持自动修复部分 lint 错误
  • 可配置: 通过配置文件自定义规则和严重级别
  • 多种输出格式: 支持 stylish、JSON、GitHub 等格式
  • 预设配置: 提供 recommended 和 strict 预设
  • 自定义规则: 支持编写和注册自定义规则
  • 性能优化: 高效的文件扫描和规则执行

基本使用

CLI 使用

# Lint 单个文件
skill lint ./skill.md

# Lint 目录
skill lint ./skills

# 自动修复
skill lint ./skill.md --fix

# 使用配置文件
skill lint ./skill.md --config .skilllintrc.json

# 指定输出格式
skill lint ./skill.md --format json
skill lint ./skill.md --format github

# 使用预设
skill lint ./skill.md --preset recommended
skill lint ./skill.md --preset strict

API 使用

import { Linter } from '@skillbolt/lint';

const linter = new Linter();

const result = await linter.lintFile('./skill.md');

console.log(result.messages); // Lint 消息数组
console.log(result.summary); // 汇总统计

// 自动修复
if (result.hasErrors) {
  const fixResult = await linter.fixFile('./skill.md');
  console.log(`Fixed ${fixResult.fixedCount} issues`);
}

内置规则

格式规则 (format)

frontmatter-required

检查技能文件是否包含必需的 frontmatter 字段。

import { frontmatterRequired } from '@skillbolt/lint';

const rule = frontmatterRequired;

配置选项:

{
  required: ['name', 'description']; // 必需字段
}

frontmatter-fields

验证 frontmatter 字段的类型和格式。

import { frontmatterFields } from '@skillbolt/lint';

配置选项:

{
  fields: {
    name: { type: 'string', pattern: '^[a-z-]+$' },
    version: { type: 'string', pattern: '^\\d+\\.\\d+\\.\\d+$' }
  }
}

sections-required

检查是否包含必需的章节。

import { sectionsRequired } from '@skillbolt/lint';

配置选项:

{
  required: ['@Claude', '@User']; // 必需章节
}

section-not-empty

检查章节内容是否为空。

import { sectionNotEmpty } from '@skillbolt/lint';

样式规则 (style)

description-format

验证描述格式。

import { descriptionFormat } from '@skillbolt/lint';

配置选项:

{
  minLength: 10,
  maxLength: 200,
  pattern: '^[A-Z].*[.!?]$' // 首字母大写,以标点结尾
}

最佳实践规则 (best-practices)

examples-exist

检查是否包含使用示例。

import { examplesExist } from '@skillbolt/lint';

max-length

检查文件或章节的最大长度。

import { maxLength } from '@skillbolt/lint';

配置选项:

{
  maxFileLength: 10000,
  maxSectionLength: 1000
}

triggers-count

检查触发词数量。

import { triggersCount } from '@skillbolt/lint';

配置选项:

{
  minTriggers: 1,
  maxTriggers: 10
}

steps-count

检查步骤数量。

import { stepsCount } from '@skillbolt/lint';

配置选项:

{
  maxSteps: 20
}

引用规则 (references)

no-broken-links

检查内部链接是否有效。

import { noBrokenLinks } from '@skillbolt/lint';

配置

配置文件

{
  "rules": {
    "frontmatter-required": ["error", { "required": ["name", "description"] }],
    "sections-required": ["warn", { "required": ["@Claude", "@User"] }],
    "examples-exist": ["warn"],
    "max-length": ["warn", { "maxSectionLength": 800 }]
  },
  "ignore": [
    "**/node_modules/**",
    "**/dist/**"
  ]
}

使用预设

import { defineConfig, presets } from '@skillbolt/lint';

export default defineConfig({
  extends: presets.recommended,
  rules: {
    'description-format': ['error', { 'minLength': 20 }]
  }
});

自定义配置

import { defineConfig } from '@skillbolt/lint';

export default defineConfig({
  rules: {
    'frontmatter-required': ['error'],
    'sections-required': ['warn'],
    'max-length': ['off']
  },
  ignore: ['**/examples/**']
});

自定义规则

创建自定义规则

import { createRule, RuleContext } from '@skillbolt/lint';

const customRule = createRule({
  name: 'custom-rule',
  meta: {
    type: 'suggestion',
    docs: {
      description: 'Custom rule description',
      category: 'custom'
    },
    fixable: true
  },
  create(context: RuleContext) {
    return {
      async visitSection(section) {
        if (section.content.length > 100) {
          context.report({
            message: 'Section is too long',
            node: section,
            fix(fixer) {
              return fixer.replaceText(section, section.content.slice(0, 100));
            }
          });
        }
      }
    };
  }
});

// 注册规则
export { customRule };

使用自定义规则

import { Linter } from '@skillbolt/lint';
import { customRule } from './custom-rule.js';

const linter = new Linter({
  rules: {
    'custom-rule': ['error']
  },
  customRules: {
    'custom-rule': customRule
  }
});

输出格式

Stylish 格式(默认)

skill lint ./skill.md

输出:

/path/to/skill.md
  1:1  error  Missing required frontmatter field: description  frontmatter-required
  10:1  warn   Section is too long                              max-length

✖ 2 problems (1 error, 1 warning)
  1 error and 0 warnings potentially fixable with the `--fix` option.

JSON 格式

skill lint ./skill.md --format json

输出:

{
  "files": [
    {
      "filePath": "/path/to/skill.md",
      "messages": [
        {
          "ruleId": "frontmatter-required",
          "severity": "error",
          "message": "Missing required frontmatter field: description",
          "line": 1,
          "column": 1,
          "fix": {
            "range": [0, 0],
            "text": "description: \"A skill description\"\n"
          }
        }
      ]
    }
  ],
  "summary": {
    "errorCount": 1,
    "warningCount": 1,
    "fixableErrorCount": 1,
    "fixableWarningCount": 0
  }
}

GitHub 格式

skill lint ./skill.md --format github

输出:

::error file=/path/to/skill.md,line=1,col=1::Missing required frontmatter field: description
::warning file=/path/to/skill.md,line=10,col=1::Section is too long

使用示例

示例 1: 基本 Lint

import { Linter } from '@skillbolt/lint';

async function lintSkill(skillPath: string) {
  const linter = new Linter();
  
  const result = await linter.lintFile(skillPath);
  
  if (result.hasErrors) {
    console.error(`Found ${result.summary.errorCount} errors`);
    result.messages.forEach(msg => {
      console.error(`${msg.line}:${msg.column} ${msg.severity}: ${msg.message}`);
    });
  } else {
    console.log('No errors found!');
  }
}

示例 2: 自动修复

import { Linter } from '@skillbolt/lint';

async function fixSkill(skillPath: string) {
  const linter = new Linter();
  
  const fixResult = await linter.fixFile(skillPath);
  
  console.log(`Fixed ${fixResult.fixedCount} issues`);
  console.log(`Remaining: ${fixResult.remainingIssues} issues`);
  
  if (fixResult.fixedCount > 0) {
    console.log('File has been updated');
  }
}

示例 3: 自定义配置

import { Linter } from '@skillbolt/lint';

async function lintWithConfig(skillPath: string) {
  const config = {
    rules: {
      'frontmatter-required': ['error'],
      'sections-required': ['warn'],
      'max-length': ['warn', { maxSectionLength: 800 }]
    },
    ignore: ['**/examples/**']
  };
  
  const linter = new Linter(config);
  const result = await linter.lintFile(skillPath);
  
  return result;
}

示例 4: 批量 Lint

import { Linter } from '@skillbolt/lint';
import { promises as fs } from 'fs';

async function lintDirectory(dir: string) {
  const linter = new Linter();
  const files = await fs.readdir(dir);
  
  let totalErrors = 0;
  let totalWarnings = 0;
  
  for (const file of files) {
    if (file.endsWith('.md')) {
      const result = await linter.lintFile(`${dir}/${file}`);
      totalErrors += result.summary.errorCount;
      totalWarnings += result.summary.warningCount;
      
      console.log(`${file}: ${result.summary.errorCount} errors, ${result.summary.warningCount} warnings`);
    }
  }
  
  console.log(`\nTotal: ${totalErrors} errors, ${totalWarnings} warnings`);
}

类型定义

interface LinterOptions {
  rules?: RulesConfig;
  ignore?: string[];
  fix?: boolean;
  format?: FormatterName;
}

interface LintResult {
  filePath: string;
  messages: LintMessage[];
  summary: LintSummary;
  hasErrors: boolean;
}

interface LintMessage {
  ruleId: string;
  severity: 'error' | 'warning' | 'suggestion';
  message: string;
  line: number;
  column: number;
  fix?: FixInfo;
}

interface FixInfo {
  range: [number, number];
  text: string;
}

interface LintSummary {
  errorCount: number;
  warningCount: number;
  fixableErrorCount: number;
  fixableWarningCount: number;
}

interface RuleConfig {
  [key: string]: RuleConfigValue;
}

type RuleConfigValue = 'off' | 'warn' | 'error' | [RuleConfigValue, Record<string, unknown>];

CLI 命令

skill lint <path>

# 选项
skill lint ./skill.md --fix
skill lint ./skill.md --config .skilllintrc.json
skill lint ./skill.md --format json
skill lint ./skill.md --preset recommended
skill lint ./skill.md --ignore '**/node_modules/**'

最佳实践

  1. 持续集成: 在 CI/CD 流程中运行 lint
  2. 自动修复: 使用 --fix 选项自动修复可修复的问题
  3. 配置文件: 使用配置文件统一项目规范
  4. 逐步修复: 先修复错误,再处理警告
  5. 自定义规则: 为项目特定的需求创建自定义规则

故障排除

规则未找到

如果遇到规则未找到的错误:

  1. 检查规则名称拼写
  2. 确认规则是否在内置规则列表中
  3. 检查自定义规则是否正确注册

修复失败

如果自动修复失败:

  1. 检查文件权限
  2. 确认文件未被其他程序锁定
  3. 查看详细的错误消息

性能问题

如果 lint 速度慢:

  1. 使用 ignore 配置排除不需要检查的目录
  2. 减少启用的规则数量
  3. 考虑使用缓存(如果支持)

API 参考

主要导出

// Linter
export { Linter };

// 规则
export {
  rules,
  allRules,
  formatRules,
  styleRules,
  bestPracticesRules,
  referencesRules
};

// 具体规则
export {
  frontmatterRequired,
  frontmatterFields,
  sectionsRequired,
  sectionNotEmpty,
  descriptionFormat,
  maxLength,
  examplesExist,
  triggersCount,
  stepsCount,
  noBrokenLinks
};

// 规则创建
export { createRule, runRule };

// 修复
export { createFixer, applyFixes };

// 配置
export {
  loadLintConfig,
  getResolvedConfig,
  defineConfig,
  defaultConfig,
  presets,
  recommendedRules,
  strictRules
};

// 格式化器
export {
  formatters,
  getFormatter,
  stylishFormatter,
  jsonFormatter,
  githubFormatter
};

贡献

欢迎贡献!请查看 CONTRIBUTING.md 了解详细信息。

许可证

MIT