Documentation
¶
Overview ¶
Package skilllint is a linter for agent skill files (SKILL.md per the agentskills.io specification). It follows the conventions of linters like golangci-lint and ruff: named rules, per-rule severity, config-driven enable/disable, multiple output formats.
Typical use from the CLI:
skilllint lint .claude/skills
Or as a library:
import (
"github.com/bueti/skilllint"
_ "github.com/bueti/skilllint/rules" // register built-in rules
)
issues, err := skilllint.New().LintDir(".claude/skills")
See https://agentskills.io/specification for the underlying file format.
Index ¶
- func ApplyFixes(data []byte, edits []Edit) ([]byte, error)
- func Counts(issues []Issue) (errors, warnings int)
- func FindConfig(startDir string) string
- func HasErrors(issues []Issue) bool
- func HasWarnings(issues []Issue) bool
- func OptionAs[T any](ctx *Context, key string) (T, bool)
- func Register(r Rule)
- func Rel(base, target string) string
- func Write(w io.Writer, issues []Issue, f Format) error
- type CheckFunc
- type Config
- type Context
- type Edit
- type FixOptions
- type FixResult
- type Format
- type Issue
- type Linter
- func (l *Linter) FixDir(dir string, opts FixOptions) ([]FixResult, error)
- func (l *Linter) FixFile(path string, opts FixOptions) (FixResult, error)
- func (l *Linter) LintBytes(source string, data []byte) ([]Issue, error)
- func (l *Linter) LintDir(dir string) ([]Issue, error)
- func (l *Linter) LintFile(path string) ([]Issue, error)
- type Option
- type Rule
- type RuleConfig
- type Severity
- type SuppressEntry
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyFixes ¶ added in v0.3.0
ApplyFixes returns a new copy of data with every edit applied. Edits are sorted by StartByte descending before application so earlier offsets remain valid as later ones are rewritten. An overlap between any two edits causes ApplyFixes to return an error without touching data — the caller should re-run lint and apply the remaining fixes in a subsequent iteration.
func FindConfig ¶
FindConfig walks from startDir toward the filesystem root looking for a config file (.skilllint.yaml or .skilllint.yml). Returns "" if none found.
func HasWarnings ¶
HasWarnings reports whether any of the issues is at SeverityWarning.
func OptionAs ¶
Option returns the option value for key, or the zero value for T if the key is missing or the wrong type.
func Register ¶
func Register(r Rule)
Register adds a rule to the global registry. Intended for use in package-level init() functions — for example, the built-in rules are registered by importing github.com/bueti/skilllint/rules. Panics on a duplicate ID, an empty ID, a nil Check, or a Default of SeverityUnset; all four indicate programming errors that should be caught at boot.
Types ¶
type Config ¶
type Config struct {
// Rules maps rule ID → override. The override may be a bare severity
// ("error") or an object with severity + arbitrary rule options.
Rules map[string]RuleConfig `yaml:"rules,omitempty"`
// Suppress disables specific rules for files matching path globs.
Suppress []SuppressEntry `yaml:"suppress,omitempty"`
}
Config captures the user's lint customization: per-rule severity overrides, rule-specific options, and per-path rule suppressions.
func LoadConfig ¶
LoadConfig reads a config file (YAML). Returns an empty Config with no error if path is empty or the file is missing.
type Context ¶
type Context struct {
// Skill is the parsed SKILL.md (frontmatter + body + metadata).
Skill *parse.Skill
// Source is the file path (for reporting).
Source string
// Options carries rule-specific configuration (e.g. the `min-length`
// knob on `description-too-short`). Rules may ignore this entirely.
Options map[string]any
}
Context carries the data a rule needs to make its decision.
type Edit ¶ added in v0.3.0
Edit is a single byte-range replacement against the original file bytes. Edits are applied in reverse StartByte order so earlier offsets stay valid. An empty Replacement deletes the range; StartByte == EndByte inserts without removing.
type FixOptions ¶ added in v0.3.0
type FixOptions struct {
// DryRun, when true, computes edits and reports what would happen but
// does not write files.
DryRun bool
}
FixOptions controls FixFile / FixDir behavior.
type FixResult ¶ added in v0.3.0
type FixResult struct {
// Source is the file path that was (or would be) rewritten.
Source string
// Fixes is the count of edits applied across all iterations.
Fixes int
// Remaining is the issues still present after fixing is done.
Remaining []Issue
// Written reports whether the file on disk was actually updated. False
// when FixDir ran in dry-run mode or the file had no fixable issues.
Written bool
}
FixResult summarizes one file's fix pass.
type Format ¶
type Format string
Format selects an output renderer for a set of Issues.
const ( // FormatText is the default one-line-per-issue output: // path/to/SKILL.md:12: error name-length: name is 80 chars; spec limit is 64 FormatText Format = "text" // FormatJSON emits a JSON array of issue objects plus a summary footer. FormatJSON Format = "json" // FormatGitHubActions emits `::error` / `::warning` workflow commands // that render inline on GitHub pull requests. FormatGitHubActions Format = "github-actions" )
type Issue ¶
type Issue struct {
Rule string // rule ID, e.g. "name-length"
Severity Severity // as resolved by the linter (rule default + config overrides)
Source string // file path relative to CWD when possible
Line int // 1-based, 0 if unknown
Column int // 1-based, 0 if unknown
Field string // frontmatter field or "body" for body-scoped findings
Message string // human-readable detail
// Fix is an optional mechanical repair for this issue. Offsets reference
// the original file bytes that were parsed into ctx.Skill.Raw. When
// empty, the issue is report-only; the --fix CLI flag skips it and the
// user has to resolve it by hand.
Fix []Edit
}
Issue is a single lint finding.
type Linter ¶
type Linter struct {
// contains filtered or unexported fields
}
Linter runs registered rules against parsed skills, applying the user's configuration to resolve per-rule severity and per-path suppressions.
func New ¶
New returns a Linter that runs every rule currently in the registry, with the given config (empty config means each rule uses its default severity).
func (*Linter) FixDir ¶ added in v0.3.0
func (l *Linter) FixDir(dir string, opts FixOptions) ([]FixResult, error)
FixDir walks dir and applies fixes to every SKILL.md it finds, returning one FixResult per file that had at least one issue (fixable or not).
func (*Linter) FixFile ¶ added in v0.3.0
func (l *Linter) FixFile(path string, opts FixOptions) (FixResult, error)
FixFile applies available fixes to path and writes the result back to disk, iterating until no progress is made or maxFixIterations is reached. Remaining issues after the loop are returned for the caller to report.
type Option ¶
type Option func(*Linter)
Option configures a Linter.
func WithConfig ¶
WithConfig installs the user's configuration (rule overrides + path suppressions). Passing a zero Config is equivalent to no option.
type Rule ¶
type Rule struct {
// ID is a stable, kebab-case identifier used in config and output.
ID string
// Title is a one-line human-readable summary.
Title string
// Description is the long-form rationale, shown by `skilllint rules show`.
Description string
// Default is the severity applied when the user's config doesn't
// override this rule. For spec hard limits use SeverityError; for soft
// limits and quality checks use SeverityWarning.
Default Severity
// Check runs the rule against a parsed skill. Return zero or more
// findings; the Linter fills in Rule / Severity / Source fields.
Check CheckFunc
}
Rule is a single named check. Rules are registered at package init time via Register and then run by the Linter in registration order.
type RuleConfig ¶
RuleConfig is a per-rule configuration. A string form in YAML ("name-length: error") and an object form ("name-length: {severity: error, min-length: 60}") are both accepted.
func (*RuleConfig) UnmarshalYAML ¶
func (r *RuleConfig) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML accepts either a bare severity string or an object with severity + rule-specific options.
type Severity ¶
type Severity int
Severity classifies a finding. Rules declare a default severity, and the user's config can raise or lower it, or disable the rule entirely with SeverityOff.
The zero value is SeverityUnset, not SeverityOff. This is deliberate: a rule that forgets to set Rule.Default would otherwise be silently disabled. Register panics on SeverityUnset and ParseSeverity returns it on unknown input so callers that ignore the error fail loud, not silent.
const ( // SeverityUnset is the zero value. It is an error for a rule or a // resolved config entry to carry this value; downstream code should // treat it as a programming mistake. SeverityUnset Severity = iota // SeverityOff disables a rule. Issues from a disabled rule are never emitted. SeverityOff // SeverityWarning is a soft finding that doesn't fail the lint run. SeverityWarning // SeverityError is a hard finding that fails the lint run (exit code 1). SeverityError )
func ParseSeverity ¶
ParseSeverity parses a severity label from config. Accepts "error", "warning", "warn", "off", "disabled". On unknown input it returns SeverityUnset (not SeverityOff) to fail closed on config typos — a caller that ignores the error still won't silently disable a rule.
type SuppressEntry ¶
SuppressEntry disables rules for files matching a path pattern. Patterns use Go's path.Match semantics, applied against the lint target's filepath.ToSlash form.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
skilllint
command
Command skilllint is the CLI for github.com/bueti/skilllint.
|
Command skilllint is the CLI for github.com/bueti/skilllint. |
|
Package parse reads SKILL.md files into a structured Skill value that rules can inspect.
|
Package parse reads SKILL.md files into a structured Skill value that rules can inspect. |
|
Package rules provides the built-in rule set for skilllint.
|
Package rules provides the built-in rule set for skilllint. |