Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
run: go test -race ./... -count=1

- name: Build
run: go build -o skill-validator .
run: go build -o skill-validator ./cmd/skill-validator
1 change: 1 addition & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version: 2

builds:
- binary: skill-validator
main: ./cmd/skill-validator
env:
- CGO_ENABLED=0
goos:
Expand Down
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ Spec compliance is table stakes. `skill-validator` goes further: it checks that
## Table of Contents

- [Install](#install)
- [Homebrew](#homebrew)
- [Using Go](#using-go)
- [Pre-commit hook](#pre-commit-hook)
- [CLI](#install-cli)
- [Homebrew](#homebrew)
- [Using Go](#using-go)
- [Pre-commit hook](#pre-commit-hook)
- [As a library](#as-a-library)
- [Command Usage](#command-usage)
- [validate structure](#validate-structure)
- [validate links](#validate-links)
Expand All @@ -36,34 +38,36 @@ Spec compliance is table stakes. `skill-validator` goes further: it checks that

## Install

You can install in three ways:
### Install CLI

You can install the CLI in three ways:

- [Homebrew](#homebrew)
- [Using Go](#using-go)
- [Pre-commit hook](#pre-commit-hook)

### Homebrew
#### Homebrew

```
brew tap dacharyc/tap
brew install skill-validator
```

### Using Go
#### Using Go

```
go install github.com/dacharyc/skill-validator@latest
go install github.com/dacharyc/skill-validator/cmd/skill-validator@latest
```

Or build from source:

```
git clone https://github.com/dacharyc/skill-validator.git
cd skill-validator
go build -o skill-validator .
go build -o skill-validator ./cmd/skill-validator
```

### Pre-commit hook
#### Pre-commit hook

`skill-validator` supports [pre-commit](https://pre-commit.com). Platform-specific hooks are provided for all major agent platforms, so the correct skills directory is used automatically. For example, the following configuration runs the skill-validator [`check`](#check) command on the `".claude/skills/"` path:

Expand All @@ -85,6 +89,20 @@ hooks:
args: ["check", "path/to/skills/"]
```

### As a library

The validation and scoring packages are importable for use in custom tooling, CI pipelines, and enterprise integrations:

```go
import (
"github.com/dacharyc/skill-validator/skillcheck"
"github.com/dacharyc/skill-validator/structure"
"github.com/dacharyc/skill-validator/judge"
)
```

See the [package documentation](https://pkg.go.dev/github.com/dacharyc/skill-validator) for available APIs.

## Command Usage

Commands map to skill development lifecycle stages:
Expand Down
41 changes: 7 additions & 34 deletions cmd/analyze_contamination.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package cmd

import (
"path/filepath"

"github.com/spf13/cobra"

"github.com/dacharyc/skill-validator/internal/contamination"
"github.com/dacharyc/skill-validator/internal/content"
"github.com/dacharyc/skill-validator/internal/validator"
"github.com/dacharyc/skill-validator/orchestrate"
"github.com/dacharyc/skill-validator/types"
)

var perFileContamination bool
Expand All @@ -32,13 +29,13 @@ func runAnalyzeContamination(cmd *cobra.Command, args []string) error {
}

switch mode {
case validator.SingleSkill:
r := runContaminationAnalysis(dirs[0])
case types.SingleSkill:
r := orchestrate.RunContaminationAnalysis(dirs[0])
return outputReportWithPerFile(r, perFileContamination)
case validator.MultiSkill:
mr := &validator.MultiReport{}
case types.MultiSkill:
mr := &types.MultiReport{}
for _, dir := range dirs {
r := runContaminationAnalysis(dir)
r := orchestrate.RunContaminationAnalysis(dir)
mr.Skills = append(mr.Skills, r)
mr.Errors += r.Errors
mr.Warnings += r.Warnings
Expand All @@ -47,27 +44,3 @@ func runAnalyzeContamination(cmd *cobra.Command, args []string) error {
}
return nil
}

func runContaminationAnalysis(dir string) *validator.Report {
rpt := &validator.Report{SkillDir: dir}

s, err := validator.LoadSkill(dir)
if err != nil {
rpt.Results = append(rpt.Results,
validator.ResultContext{Category: "Contamination"}.Error(err.Error()))
rpt.Errors = 1
return rpt
}

// Get code languages from content analysis
cr := content.Analyze(s.RawContent)
skillName := filepath.Base(dir)
rpt.ContaminationReport = contamination.Analyze(skillName, s.RawContent, cr.CodeLanguages)

rpt.Results = append(rpt.Results,
validator.ResultContext{Category: "Contamination"}.Pass("contamination analysis complete"))

validator.AnalyzeReferences(dir, rpt)

return rpt
}
34 changes: 7 additions & 27 deletions cmd/analyze_content.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package cmd
import (
"github.com/spf13/cobra"

"github.com/dacharyc/skill-validator/internal/content"
"github.com/dacharyc/skill-validator/internal/validator"
"github.com/dacharyc/skill-validator/orchestrate"
"github.com/dacharyc/skill-validator/types"
)

var perFileContent bool
Expand All @@ -29,13 +29,13 @@ func runAnalyzeContent(cmd *cobra.Command, args []string) error {
}

switch mode {
case validator.SingleSkill:
r := runContentAnalysis(dirs[0])
case types.SingleSkill:
r := orchestrate.RunContentAnalysis(dirs[0])
return outputReportWithPerFile(r, perFileContent)
case validator.MultiSkill:
mr := &validator.MultiReport{}
case types.MultiSkill:
mr := &types.MultiReport{}
for _, dir := range dirs {
r := runContentAnalysis(dir)
r := orchestrate.RunContentAnalysis(dir)
mr.Skills = append(mr.Skills, r)
mr.Errors += r.Errors
mr.Warnings += r.Warnings
Expand All @@ -44,23 +44,3 @@ func runAnalyzeContent(cmd *cobra.Command, args []string) error {
}
return nil
}

func runContentAnalysis(dir string) *validator.Report {
rpt := &validator.Report{SkillDir: dir}

s, err := validator.LoadSkill(dir)
if err != nil {
rpt.Results = append(rpt.Results,
validator.ResultContext{Category: "Content"}.Error(err.Error()))
rpt.Errors = 1
return rpt
}

rpt.ContentReport = content.Analyze(s.RawContent)
rpt.Results = append(rpt.Results,
validator.ResultContext{Category: "Content"}.Pass("content analysis complete"))

validator.AnalyzeReferences(dir, rpt)

return rpt
}
Loading