@skillbolt/lint
v1.0.1
Published
SKILL.md format linter for Skillbolt - check and fix your AI agent skills
Maintainers
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 strictAPI 使用
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/**'最佳实践
- 持续集成: 在 CI/CD 流程中运行 lint
- 自动修复: 使用
--fix选项自动修复可修复的问题 - 配置文件: 使用配置文件统一项目规范
- 逐步修复: 先修复错误,再处理警告
- 自定义规则: 为项目特定的需求创建自定义规则
故障排除
规则未找到
如果遇到规则未找到的错误:
- 检查规则名称拼写
- 确认规则是否在内置规则列表中
- 检查自定义规则是否正确注册
修复失败
如果自动修复失败:
- 检查文件权限
- 确认文件未被其他程序锁定
- 查看详细的错误消息
性能问题
如果 lint 速度慢:
- 使用 ignore 配置排除不需要检查的目录
- 减少启用的规则数量
- 考虑使用缓存(如果支持)
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
