Documentation
¶
Overview ¶
Package cli provides cross-file validation for cclint.
This file contains the validation orchestration logic. Related functionality is split into:
- crossfile_refs.go: Reference extraction (findSkillReferences, parseAllowedTools, etc.)
- crossfile_graph.go: Cycle detection and chain tracing (DetectCycles, TraceChain, etc.)
Package cli provides generic linting infrastructure for cclint.
This file implements the Generic Single-File Linter and Generic Batch Linter patterns, extracting common logic from the six component-specific linters.
Design Principles ¶
- Interface-driven: ComponentLinter interface for type-specific logic
- DRY: Common linting logic extracted to lintComponent()
- Extensible: New component types only need to implement ComponentLinter
- ISP-compliant: Core interface is minimal; optional behaviors via separate interfaces
Package cli provides single-file linting capabilities for cclint.
This file implements the single-file linting mode, which allows users to lint individual files directly (e.g., `cclint ./agents/my-agent.md`) rather than running discovery across all component types.
Design Principles ¶
- Unambiguous CLI: File paths clearly distinguished from subcommands
- Pattern-based type detection: Uses glob matching for reliability
- Fail-fast with clear errors: Every edge case has an actionable message
- Cross-file aware: Validates outgoing refs, skips orphan detection
- Reuses existing validation: Same logic as batch mode
Usage ¶
// Lint a single file
summary, err := LintSingleFile("./agents/my-agent.md", "", false, false)
// Lint multiple files
summary, err := LintFiles([]string{"a.md", "b.md"}, "", "", false, false)
Index ¶
- Constants
- func CheckClaudeLocalGitignore(rootPath string) []cue.ValidationError
- func CheckCombinedMemorySize(rootPath string, files []discovery.File) []cue.ValidationError
- func CheckSizeLimit(contents string, limit int, tolerance float64, componentType, filePath string) *cue.ValidationError
- func CollectAllIssues(summary *LintSummary) []cue.ValidationError
- func CountLines(content string) int
- func DetectXMLTags(content, fieldName, filePath, fileContents string) *cue.ValidationError
- func DetermineSeverity(message string) string
- func FilterResults(summary *LintSummary, b *baseline.Baseline) (int, int, int)
- func FindFrontmatterFieldLine(content, fieldName string) int
- func FindJSONFieldLine(content string, fieldName string) int
- func FindLineNumber(content, pattern string) int
- func FindSectionLine(content, sectionName string) int
- func FormatChain(link *ChainLink, indent string) string
- func FormatCycle(cycle Cycle) string
- func GetFrontmatterEndLine(content string) int
- func IsKnownSubcommand(arg string) bool
- func LooksLikePath(arg string) bool
- func ValidateAllowedTools(data map[string]interface{}, filePath string, contents string) []cue.ValidationError
- func ValidateAllowedToolsShared(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- func ValidateSemver(version, filePath string, line int) *cue.ValidationError
- func ValidateToolFieldName(data map[string]interface{}, filePath string, contents string, ...) []cue.ValidationError
- type AgentLinter
- func (l *AgentLinter) FileType() discovery.FileType
- func (l *AgentLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
- func (l *AgentLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *AgentLinter) PostProcessBatch(ctx *LinterContext, summary *LintSummary)
- func (l *AgentLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
- func (l *AgentLinter) Type() string
- func (l *AgentLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *AgentLinter) ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, ...) []cue.ValidationError
- func (l *AgentLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- type BaseLinter
- type BatchPostProcessor
- type BestPracticeValidator
- type ChainLink
- type CommandLinter
- func (l *CommandLinter) FileType() discovery.FileType
- func (l *CommandLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
- func (l *CommandLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *CommandLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
- func (l *CommandLinter) Type() string
- func (l *CommandLinter) ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
- func (l *CommandLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *CommandLinter) ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, ...) []cue.ValidationError
- func (l *CommandLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- type ComponentLinter
- type ContextLinter
- func (l *ContextLinter) FileType() discovery.FileType
- func (l *ContextLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *ContextLinter) Type() string
- func (l *ContextLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *ContextLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- type CrossFileValidatable
- type CrossFileValidator
- func (v *CrossFileValidator) DetectCycles() []Cycle
- func (v *CrossFileValidator) FindOrphanedSkills() []cue.ValidationError
- func (v *CrossFileValidator) TraceChain(componentType string, name string) *ChainLink
- func (v *CrossFileValidator) ValidateAgent(filePath string, contents string) []cue.ValidationError
- func (v *CrossFileValidator) ValidateCommand(filePath string, contents string, frontmatter map[string]interface{}) []cue.ValidationError
- func (v *CrossFileValidator) ValidateSkill(filePath string, contents string) []cue.ValidationError
- type Cycle
- type Improvable
- type ImprovementRecommendation
- func GetAgentImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
- func GetCommandImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
- func GetPluginImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
- func GetSkillImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
- type LintResult
- type LintSummary
- func LintAgents(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- func LintCommands(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- func LintContext(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- func LintFiles(filePaths []string, rootPath, typeOverride string, quiet, verbose bool) (*LintSummary, error)
- func LintPlugins(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- func LintRules(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- func LintSettings(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- func LintSingleFile(filePath, rootPath, typeOverride string, quiet, verbose bool) (*LintSummary, error)
- func LintSkills(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
- type LinterContext
- func (ctx *LinterContext) FilterFilesByType(fileType discovery.FileType) []discovery.File
- func (ctx *LinterContext) LogProcessed(filePath string, errorCount int)
- func (ctx *LinterContext) LogProcessedWithSuggestions(filePath string, errorCount, suggestionCount int)
- func (ctx *LinterContext) NewSummary(totalFiles int) *LintSummary
- type PluginLinter
- func (l *PluginLinter) FileType() discovery.FileType
- func (l *PluginLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
- func (l *PluginLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *PluginLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
- func (l *PluginLinter) Type() string
- func (l *PluginLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *PluginLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- type PostProcessable
- type PreValidator
- type RuleLinter
- func (l *RuleLinter) FileType() discovery.FileType
- func (l *RuleLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *RuleLinter) PreValidate(filePath, contents string) []cue.ValidationError
- func (l *RuleLinter) Type() string
- func (l *RuleLinter) ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
- func (l *RuleLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *RuleLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- type Scorable
- type SettingsLinter
- func (l *SettingsLinter) FileType() discovery.FileType
- func (l *SettingsLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *SettingsLinter) Type() string
- func (l *SettingsLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *SettingsLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
- type SingleFileLinterContext
- type SkillLinter
- func (l *SkillLinter) FileType() discovery.FileType
- func (l *SkillLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
- func (l *SkillLinter) ParseContent(contents string) (map[string]interface{}, string, error)
- func (l *SkillLinter) PostProcessBatch(ctx *LinterContext, summary *LintSummary)
- func (l *SkillLinter) PreValidate(filePath, contents string) []cue.ValidationError
- func (l *SkillLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
- func (l *SkillLinter) Type() string
- func (l *SkillLinter) ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
- func (l *SkillLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
- func (l *SkillLinter) ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, ...) []cue.ValidationError
- func (l *SkillLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
Constants ¶
const ( SeverityHigh = "high" SeverityMedium = "medium" SeverityLow = "low" )
Severity levels
const (
// CombinedMemorySizeWarningKB is the threshold for warning about combined memory size
CombinedMemorySizeWarningKB = 20
)
Variables ¶
This section is empty.
Functions ¶
func CheckClaudeLocalGitignore ¶
func CheckClaudeLocalGitignore(rootPath string) []cue.ValidationError
CheckClaudeLocalGitignore checks if CLAUDE.local.md exists and is in .gitignore
func CheckCombinedMemorySize ¶
func CheckCombinedMemorySize(rootPath string, files []discovery.File) []cue.ValidationError
CheckCombinedMemorySize checks if total CLAUDE.md + always-loaded rules size exceeds threshold. Rules with paths: frontmatter are conditionally loaded and don't count toward the threshold.
func CheckSizeLimit ¶
func CheckSizeLimit(contents string, limit int, tolerance float64, componentType, filePath string) *cue.ValidationError
CheckSizeLimit checks if content exceeds a line limit with tolerance. Returns a suggestion if the limit is exceeded.
func CollectAllIssues ¶
func CollectAllIssues(summary *LintSummary) []cue.ValidationError
CollectAllIssues collects all validation errors from a summary (for baseline creation)
func CountLines ¶
CountLines returns the total number of lines in content
func DetectXMLTags ¶
func DetectXMLTags(content, fieldName, filePath, fileContents string) *cue.ValidationError
DetectXMLTags checks for XML-like tags in a string and returns an error if found. This is used by agents, commands, and skills to validate the description field.
func DetermineSeverity ¶
DetermineSeverity determines issue severity based on the message
func FilterResults ¶
FilterResults filters issues based on baseline, returning filtered issues and count of ignored issues
func FindFrontmatterFieldLine ¶
FindFrontmatterFieldLine finds the line number of a YAML frontmatter field
func FindJSONFieldLine ¶
FindJSONFieldLine finds the line number of a JSON field
func FindLineNumber ¶
FindLineNumber finds the line number (1-based) where a pattern first appears
func FindSectionLine ¶
FindSectionLine finds the line number of a markdown section header
func FormatChain ¶
FormatChain formats a chain link as a tree string
func FormatCycle ¶
FormatCycle formats a cycle for human-readable output
func GetFrontmatterEndLine ¶
GetFrontmatterEndLine returns the line number where frontmatter ends
func IsKnownSubcommand ¶
IsKnownSubcommand returns true if the argument is a known subcommand name. These are protected from being interpreted as file paths.
func LooksLikePath ¶
LooksLikePath determines if an argument looks like a file path rather than a subcommand.
This is used to distinguish between:
- cclint agents (subcommand)
- cclint ./agents (file path)
The detection is conservative to avoid false positives:
- Absolute paths: /path, C:\path
- Relative paths: ./path, ../path
- Contains separator: path/to/file
- Has known extension: .md, .json
Known subcommands (agents, commands, etc.) are NOT treated as paths even if they match these patterns, unless --file flag is used.
func ValidateAllowedTools ¶
func ValidateAllowedTools(data map[string]interface{}, filePath string, contents string) []cue.ValidationError
ValidateAllowedTools validates that allowed-tools and tools fields contain known tool names
func ValidateAllowedToolsShared ¶
func ValidateAllowedToolsShared(data map[string]interface{}, filePath, contents string) []cue.ValidationError
ValidateAllowedToolsShared is a shared helper for tool validation.
func ValidateSemver ¶
func ValidateSemver(version, filePath string, line int) *cue.ValidationError
ValidateSemver checks if a version string follows semver format. Returns nil if valid, or a ValidationError if invalid.
func ValidateToolFieldName ¶
func ValidateToolFieldName(data map[string]interface{}, filePath string, contents string, componentType string) []cue.ValidationError
ValidateToolFieldName ensures components use correct field name (tools vs allowed-tools) - Agents MUST use 'tools:', not 'allowed-tools:' - Commands and Skills MUST use 'allowed-tools:', not 'tools:'
Types ¶
type AgentLinter ¶
type AgentLinter struct {
BaseLinter
}
AgentLinter implements ComponentLinter for agent files. It also implements optional interfaces for cross-file validation, scoring, improvements, and batch post-processing (cycle detection).
func (*AgentLinter) FileType ¶
func (l *AgentLinter) FileType() discovery.FileType
func (*AgentLinter) GetImprovements ¶
func (l *AgentLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
GetImprovements implements Improvable interface
func (*AgentLinter) ParseContent ¶
func (l *AgentLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*AgentLinter) PostProcessBatch ¶
func (l *AgentLinter) PostProcessBatch(ctx *LinterContext, summary *LintSummary)
PostProcessBatch implements BatchPostProcessor for cycle detection.
func (*AgentLinter) Score ¶
func (l *AgentLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
Score implements Scorable interface
func (*AgentLinter) Type ¶
func (l *AgentLinter) Type() string
func (*AgentLinter) ValidateCUE ¶
func (l *AgentLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*AgentLinter) ValidateCrossFile ¶
func (l *AgentLinter) ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, data map[string]interface{}) []cue.ValidationError
ValidateCrossFile implements CrossFileValidatable interface
func (*AgentLinter) ValidateSpecific ¶
func (l *AgentLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
type BaseLinter ¶
type BaseLinter struct{}
BaseLinter is an empty struct that component-specific linters can embed. With the ISP refactoring, optional capabilities are now separate interfaces that linters implement only when needed. This struct remains for embedding to signal "I'm a component linter" but provides no default methods.
Optional interfaces a linter can implement:
- PreValidator: for filename/empty content checks
- BestPracticeValidator: for best practice checks
- CrossFileValidatable: for cross-file reference validation
- Scorable: for quality scoring
- Improvable: for improvement recommendations
- PostProcessable: for result post-processing
- BatchPostProcessor: for batch-level post-processing (cycle detection)
type BatchPostProcessor ¶
type BatchPostProcessor interface {
PostProcessBatch(ctx *LinterContext, summary *LintSummary)
}
BatchPostProcessor is an optional interface for post-processing batch results. Component linters can implement this for operations like cycle detection.
type BestPracticeValidator ¶
type BestPracticeValidator interface {
// ValidateBestPractices runs best practice checks beyond basic validation.
ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
}
BestPracticeValidator is an optional interface for linters with best practice checks.
type ChainLink ¶
type ChainLink struct {
Type string // "command", "agent", "skill"
Name string
Path string
Lines int
Children []ChainLink
}
ChainLink represents a component in the delegation chain
type CommandLinter ¶
type CommandLinter struct {
BaseLinter
}
CommandLinter implements ComponentLinter for command files. It also implements optional interfaces for best practices, cross-file validation, scoring, and improvements.
func NewCommandLinter ¶
func NewCommandLinter() *CommandLinter
NewCommandLinter creates a new CommandLinter.
func (*CommandLinter) FileType ¶
func (l *CommandLinter) FileType() discovery.FileType
func (*CommandLinter) GetImprovements ¶
func (l *CommandLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
GetImprovements implements Improvable interface
func (*CommandLinter) ParseContent ¶
func (l *CommandLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*CommandLinter) Score ¶
func (l *CommandLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
Score implements Scorable interface
func (*CommandLinter) Type ¶
func (l *CommandLinter) Type() string
func (*CommandLinter) ValidateBestPractices ¶
func (l *CommandLinter) ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
ValidateBestPractices implements BestPracticeValidator interface
func (*CommandLinter) ValidateCUE ¶
func (l *CommandLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*CommandLinter) ValidateCrossFile ¶
func (l *CommandLinter) ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, data map[string]interface{}) []cue.ValidationError
ValidateCrossFile implements CrossFileValidatable interface
func (*CommandLinter) ValidateSpecific ¶
func (l *CommandLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
type ComponentLinter ¶
type ComponentLinter interface {
// Type returns the component type name (e.g., "agent", "command")
Type() string
// FileType returns the discovery.FileType for filtering
FileType() discovery.FileType
// ParseContent parses the file content and returns frontmatter data and body.
// For JSON files, body may be empty.
ParseContent(contents string) (data map[string]interface{}, body string, err error)
// ValidateCUE runs CUE schema validation if applicable.
// Returns nil if CUE validation is not used for this type.
ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
// ValidateSpecific runs component-specific validation rules.
ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
}
ComponentLinter defines the minimal interface for type-specific linting logic. Each component type (agent, command, skill, etc.) implements this interface.
For optional behaviors (scoring, improvements, cross-file validation), implement the corresponding capability interface (Scorable, Improvable, CrossFileValidatable).
type ContextLinter ¶
type ContextLinter struct {
BaseLinter
}
ContextLinter implements ComponentLinter for CLAUDE.md context files. It implements only the core ComponentLinter interface - no optional capabilities. Context files don't need scoring, improvements, or cross-file validation.
func NewContextLinter ¶
func NewContextLinter() *ContextLinter
NewContextLinter creates a new ContextLinter.
func (*ContextLinter) FileType ¶
func (l *ContextLinter) FileType() discovery.FileType
func (*ContextLinter) ParseContent ¶
func (l *ContextLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*ContextLinter) Type ¶
func (l *ContextLinter) Type() string
func (*ContextLinter) ValidateCUE ¶
func (l *ContextLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*ContextLinter) ValidateSpecific ¶
func (l *ContextLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
type CrossFileValidatable ¶
type CrossFileValidatable interface {
// ValidateCrossFile runs cross-file validation (e.g., agent→skill references).
ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, data map[string]interface{}) []cue.ValidationError
}
CrossFileValidatable is an optional interface for linters that validate cross-file references.
type CrossFileValidator ¶
type CrossFileValidator struct {
// contains filtered or unexported fields
}
CrossFileValidator validates references between components
func NewCrossFileValidator ¶
func NewCrossFileValidator(files []discovery.File) *CrossFileValidator
NewCrossFileValidator creates a validator with indexed files
func (*CrossFileValidator) DetectCycles ¶
func (v *CrossFileValidator) DetectCycles() []Cycle
DetectCycles finds circular dependencies using DFS with color marking. Returns all cycles found in the component graph.
Algorithm: DFS with three colors:
- white (0): unvisited
- gray (1): currently visiting (in recursion stack)
- black (2): completely visited
Back edges (gray -> gray) indicate cycles.
func (*CrossFileValidator) FindOrphanedSkills ¶
func (v *CrossFileValidator) FindOrphanedSkills() []cue.ValidationError
FindOrphanedSkills finds skills that aren't referenced by any command, agent, or other skill
func (*CrossFileValidator) TraceChain ¶
func (v *CrossFileValidator) TraceChain(componentType string, name string) *ChainLink
TraceChain traces the full delegation chain starting from a component
func (*CrossFileValidator) ValidateAgent ¶
func (v *CrossFileValidator) ValidateAgent(filePath string, contents string) []cue.ValidationError
ValidateAgent checks agent references to skills
func (*CrossFileValidator) ValidateCommand ¶
func (v *CrossFileValidator) ValidateCommand(filePath string, contents string, frontmatter map[string]interface{}) []cue.ValidationError
ValidateCommand checks command references to agents
func (*CrossFileValidator) ValidateSkill ¶
func (v *CrossFileValidator) ValidateSkill(filePath string, contents string) []cue.ValidationError
ValidateSkill checks skill references to agents
type Cycle ¶
type Cycle struct {
Path []string // Component names in cycle order (last element == first element)
Type string // "command-agent-command", "agent-skill-agent", etc.
}
Cycle represents a circular dependency in the component graph
type Improvable ¶
type Improvable interface {
// GetImprovements returns improvement recommendations with point values.
GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
}
Improvable is an optional interface for linters that provide improvement recommendations.
type ImprovementRecommendation ¶
type ImprovementRecommendation struct {
Description string
PointValue int
Line int
Severity string
}
ImprovementRecommendation represents a specific fix with point value
func GetAgentImprovements ¶
func GetAgentImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
GetAgentImprovements returns specific improvement recommendations for agents
func GetCommandImprovements ¶
func GetCommandImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
GetCommandImprovements returns specific improvement recommendations for commands
func GetPluginImprovements ¶
func GetPluginImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
GetPluginImprovements returns specific improvement recommendations for plugins
func GetSkillImprovements ¶
func GetSkillImprovements(content string, data map[string]interface{}) []ImprovementRecommendation
GetSkillImprovements returns specific improvement recommendations for skills
type LintResult ¶
type LintResult struct {
File string
Type string
Errors []cue.ValidationError
Warnings []cue.ValidationError
Suggestions []cue.ValidationError
Improvements []ImprovementRecommendation
Success bool
Duration int64
Quality *scoring.QualityScore
}
LintResult represents a single linting result
type LintSummary ¶
type LintSummary struct {
ProjectRoot string
ComponentType string // e.g., "agents", "commands", "skills"
StartTime time.Time
TotalFiles int
SuccessfulFiles int
FailedFiles int
TotalErrors int
TotalWarnings int
TotalSuggestions int
Duration int64
Results []LintResult
}
LintSummary summarizes all linting results
func LintAgents ¶
LintAgents runs linting on agent files using the generic linter.
func LintCommands ¶
func LintCommands(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
LintCommands runs linting on command files using the generic linter.
func LintContext ¶
func LintContext(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
LintContext runs linting on CLAUDE.md files using the generic linter.
func LintFiles ¶
func LintFiles(filePaths []string, rootPath, typeOverride string, quiet, verbose bool) (*LintSummary, error)
LintFiles lints multiple files and returns a combined summary.
Each file is validated independently; failures for one file do not prevent linting of other files. The summary aggregates all results.
Parameters:
- filePaths: Paths to files (absolute or relative)
- rootPath: Project root (empty to auto-detect per file)
- typeOverride: Force component type (empty to auto-detect)
- quiet: Suppress non-essential output
- verbose: Enable verbose output
func LintPlugins ¶
func LintPlugins(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
LintPlugins runs linting on plugin manifest files using the generic linter.
func LintSettings ¶
func LintSettings(rootPath string, quiet bool, verbose bool, noCycleCheck bool) (*LintSummary, error)
LintSettings runs linting on settings files using the generic linter.
func LintSingleFile ¶
func LintSingleFile(filePath, rootPath, typeOverride string, quiet, verbose bool) (*LintSummary, error)
LintSingleFile lints a single file and returns a summary.
This is the main entry point for single-file linting. It:
- Creates a SingleFileLinterContext with full validation
- Routes to the appropriate type-specific linter
- Returns a LintSummary compatible with existing output formatters
Parameters:
- filePath: Path to the file (absolute or relative)
- rootPath: Project root (empty to auto-detect)
- typeOverride: Force component type (empty to auto-detect)
- quiet: Suppress non-essential output
- verbose: Enable verbose output
Exit codes (for CLI):
- 0: Success (no errors)
- 1: Lint errors found
- 2: Invalid invocation (returned as error)
func LintSkills ¶
LintSkills runs linting on skill files using the generic linter.
type LinterContext ¶
type LinterContext struct {
RootPath string
Quiet bool
Verbose bool
NoCycleCheck bool
Validator *cue.Validator
Discoverer *discovery.FileDiscovery
Files []discovery.File
CrossValidator *CrossFileValidator
}
LinterContext holds the shared context for all linting operations. This follows the Single Responsibility Principle by centralizing the initialization and discovery logic used by all linters.
func NewLinterContext ¶
func NewLinterContext(rootPath string, quiet, verbose, noCycleCheck bool) (*LinterContext, error)
NewLinterContext creates a new LinterContext with all dependencies initialized. It handles project root detection, schema loading, file discovery, and cross-file validator setup.
func (*LinterContext) FilterFilesByType ¶
func (ctx *LinterContext) FilterFilesByType(fileType discovery.FileType) []discovery.File
FilterFilesByType returns files matching the specified type.
func (*LinterContext) LogProcessed ¶
func (ctx *LinterContext) LogProcessed(filePath string, errorCount int)
LogProcessed is a no-op - console formatter handles file status display. Kept for API compatibility with callers.
func (*LinterContext) LogProcessedWithSuggestions ¶
func (ctx *LinterContext) LogProcessedWithSuggestions(filePath string, errorCount, suggestionCount int)
LogProcessedWithSuggestions is a no-op - console formatter handles file status display. Kept for API compatibility with callers.
func (*LinterContext) NewSummary ¶
func (ctx *LinterContext) NewSummary(totalFiles int) *LintSummary
NewSummary creates an initialized LintSummary with the total file count.
type PluginLinter ¶
type PluginLinter struct {
BaseLinter
}
PluginLinter implements ComponentLinter for plugin.json files. It also implements Scorable and Improvable for quality scoring.
func NewPluginLinter ¶
func NewPluginLinter() *PluginLinter
NewPluginLinter creates a new PluginLinter.
func (*PluginLinter) FileType ¶
func (l *PluginLinter) FileType() discovery.FileType
func (*PluginLinter) GetImprovements ¶
func (l *PluginLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
GetImprovements implements Improvable interface
func (*PluginLinter) ParseContent ¶
func (l *PluginLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*PluginLinter) Score ¶
func (l *PluginLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
Score implements Scorable interface
func (*PluginLinter) Type ¶
func (l *PluginLinter) Type() string
func (*PluginLinter) ValidateCUE ¶
func (l *PluginLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*PluginLinter) ValidateSpecific ¶
func (l *PluginLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
type PostProcessable ¶
type PostProcessable interface {
// PostProcess allows type-specific post-processing of results.
PostProcess(result *LintResult)
}
PostProcessable is an optional interface for linters needing result post-processing.
type PreValidator ¶
type PreValidator interface {
// PreValidate runs any pre-validation checks (e.g., filename, empty content).
// Returns errors that should abort further validation.
PreValidate(filePath, contents string) []cue.ValidationError
}
PreValidator is an optional interface for linters that need pre-validation checks. Implement this for components with special filename requirements or empty content checks.
type RuleLinter ¶
type RuleLinter struct {
BaseLinter
}
RuleLinter implements ComponentLinter for .claude/rules/*.md files.
func (*RuleLinter) FileType ¶
func (l *RuleLinter) FileType() discovery.FileType
func (*RuleLinter) ParseContent ¶
func (l *RuleLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*RuleLinter) PreValidate ¶
func (l *RuleLinter) PreValidate(filePath, contents string) []cue.ValidationError
func (*RuleLinter) Type ¶
func (l *RuleLinter) Type() string
func (*RuleLinter) ValidateBestPractices ¶
func (l *RuleLinter) ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
func (*RuleLinter) ValidateCUE ¶
func (l *RuleLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*RuleLinter) ValidateSpecific ¶
func (l *RuleLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
type Scorable ¶
type Scorable interface {
// Score returns the quality score for the component.
Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
}
Scorable is an optional interface for linters that provide quality scores.
type SettingsLinter ¶
type SettingsLinter struct {
BaseLinter
}
SettingsLinter implements ComponentLinter for settings files. It implements only the core ComponentLinter interface - no optional capabilities. Settings files don't need scoring, improvements, cross-file validation, etc.
func NewSettingsLinter ¶
func NewSettingsLinter() *SettingsLinter
NewSettingsLinter creates a new SettingsLinter.
func (*SettingsLinter) FileType ¶
func (l *SettingsLinter) FileType() discovery.FileType
func (*SettingsLinter) ParseContent ¶
func (l *SettingsLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*SettingsLinter) Type ¶
func (l *SettingsLinter) Type() string
func (*SettingsLinter) ValidateCUE ¶
func (l *SettingsLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*SettingsLinter) ValidateSpecific ¶
func (l *SettingsLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
type SingleFileLinterContext ¶
type SingleFileLinterContext struct {
RootPath string
File discovery.File
Quiet bool
Verbose bool
Validator *cue.Validator
// contains filtered or unexported fields
}
SingleFileLinterContext holds state for single-file linting operations.
Unlike LinterContext which discovers all files upfront, this context is optimized for linting individual files. Cross-file validation is lazy-loaded only when needed.
func NewSingleFileLinterContext ¶
func NewSingleFileLinterContext(filePath, rootPath, typeOverride string, quiet, verbose bool) (*SingleFileLinterContext, error)
NewSingleFileLinterContext creates a context for linting a single file.
This function performs comprehensive path validation and type detection:
- Resolves absolute path
- Validates file exists and is readable
- Detects project root
- Determines component type from path
- Reads file contents
Parameters:
- filePath: Path to the file (absolute or relative)
- rootPath: Project root (empty to auto-detect)
- typeOverride: Force component type (empty to auto-detect)
- quiet: Suppress non-essential output
- verbose: Enable verbose output
Returns an error with actionable message for any validation failure.
func (*SingleFileLinterContext) EnsureCrossFileValidator ¶
func (ctx *SingleFileLinterContext) EnsureCrossFileValidator() *CrossFileValidator
EnsureCrossFileValidator lazy-loads the cross-file validator.
This triggers full file discovery to build the reference indexes needed for cross-file validation (agent→skill, command→agent, etc.). The result is cached for subsequent calls.
Returns nil if discovery fails (cross-file validation will be skipped).
type SkillLinter ¶
type SkillLinter struct {
BaseLinter
}
SkillLinter implements ComponentLinter for skill files. It also implements optional interfaces for pre-validation, best practices, cross-file validation, scoring, improvements, and batch post-processing.
func (*SkillLinter) FileType ¶
func (l *SkillLinter) FileType() discovery.FileType
func (*SkillLinter) GetImprovements ¶
func (l *SkillLinter) GetImprovements(contents string, data map[string]interface{}) []ImprovementRecommendation
GetImprovements implements Improvable interface
func (*SkillLinter) ParseContent ¶
func (l *SkillLinter) ParseContent(contents string) (map[string]interface{}, string, error)
func (*SkillLinter) PostProcessBatch ¶
func (l *SkillLinter) PostProcessBatch(ctx *LinterContext, summary *LintSummary)
PostProcessBatch implements BatchPostProcessor for orphan detection.
func (*SkillLinter) PreValidate ¶
func (l *SkillLinter) PreValidate(filePath, contents string) []cue.ValidationError
PreValidate implements PreValidator interface
func (*SkillLinter) Score ¶
func (l *SkillLinter) Score(contents string, data map[string]interface{}, body string) *scoring.QualityScore
Score implements Scorable interface
func (*SkillLinter) Type ¶
func (l *SkillLinter) Type() string
func (*SkillLinter) ValidateBestPractices ¶
func (l *SkillLinter) ValidateBestPractices(filePath, contents string, data map[string]interface{}) []cue.ValidationError
ValidateBestPractices implements BestPracticeValidator interface
func (*SkillLinter) ValidateCUE ¶
func (l *SkillLinter) ValidateCUE(validator *cue.Validator, data map[string]interface{}) ([]cue.ValidationError, error)
func (*SkillLinter) ValidateCrossFile ¶
func (l *SkillLinter) ValidateCrossFile(crossValidator *CrossFileValidator, filePath, contents string, data map[string]interface{}) []cue.ValidationError
ValidateCrossFile implements CrossFileValidatable interface
func (*SkillLinter) ValidateSpecific ¶
func (l *SkillLinter) ValidateSpecific(data map[string]interface{}, filePath, contents string) []cue.ValidationError
Source Files
¶
- agent_linter.go
- agents.go
- baseline_filter.go
- command_linter.go
- commands.go
- context.go
- context_linter.go
- crossfile.go
- crossfile_graph.go
- crossfile_refs.go
- generic_linter.go
- lineutil.go
- lintcontext.go
- memory_checks.go
- plugin_linter.go
- plugins.go
- rules.go
- settings.go
- settings_linter.go
- singlefile.go
- skill_linter.go
- skills.go