How to Validate Skills with dart_skills_lint Before Committing

Run dart run dart_skills_lint with --skills-directory paths to check Agent Skill directories against the specification; it exits with non-zero status on errors, making it ideal for pre-commit hooks and CI pipelines.

The dart_skills_lint tool in the flutter/skills repository is a static analysis linter that validates Agent Skill directories against the Agent Skills Specification. To validate skills with dart_skills_lint before they reach your repository, you can integrate the tool via command-line execution, configuration files, or programmatic Dart tests.

Installation and Basic CLI Usage

Activate the package globally or run it locally from your project:


# Install globally (one-time setup)

dart pub global activate dart_skills_lint

# Run from repository root

dart run dart_skills_lint \
  --skills-directory .agents/skills \
  --skills-directory .claude/skills \
  --quiet

The --quiet flag hides non-error output. When any rule returns AnalysisSeverity.error, the CLI exits with a non-zero status code, immediately aborting Git commits or CI jobs.

Configuration with dart_skills_lint.yaml

Creating the Configuration File

Create dart_skills_lint.yaml at your repository root to customize which rules run and their severity levels. The ConfigParser class in tool/dart_skills_lint/lib/src/config_parser.dart reads this file and builds the rule set:


# dart_skills_lint.yaml

dart_skills_lint:
  rules:
    check-trailing-whitespace: warning
    check-relative-paths: error
    check-absolute-paths: error
  directories:
    - path: ".agents/skills"
      ignore_file: ".agents/skills/dart_skills_lint_ignore.json"

With this file in place, running dart run dart_skills_lint without arguments automatically loads these settings.

Rule Severity Levels

Assign error, warning, or info severity to each rule. Only error-level violations cause the CLI to return a non-zero exit code, which is essential for blocking commits in pre-commit hooks.

Understanding the Validation Architecture

When you validate skills with dart_skills_lint, the execution flows through these components defined in the flutter/skills source code:

  1. CLI Entry Point: bin/cli.dart invokes runApp(arguments), forwarding to tool/dart_skills_lint/lib/src/entry_point.dart
  2. Argument Parsing: The entry point builds a list of directories (--skills-directory) or individual paths (--skill)
  3. Configuration Loading: ConfigParser reads dart_skills_lint.yaml to determine enabled rules and severities
  4. Directory Validation: Validator.validate() in tool/dart_skills_lint/lib/src/validator.dart calls _checkDirectoryStructure to verify the folder exists and contains a SKILL.md file
  5. YAML Extraction: The validator reads SKILL.md, extracts YAML front-matter using SkillContext.skillStartRegex, and parses it with loadYaml
  6. Rule Execution: The Validator instantiates rules from tool/dart_skills_lint/lib/src/rule_registry.dart and runs them against the SkillContext. Each rule returns ValidationError objects containing ruleId, file location, message, and AnalysisSeverity
  7. Result Aggregation: Errors aggregate into a ValidationResult. The CLI prints a summary and exits with non-zero status if any error-level rules failed

Pre-Commit Hook Integration

Git Hooks Setup

To automatically validate skills with dart_skills_lint before each commit, create .git/hooks/pre-commit:

#!/bin/sh

# Validate Agent Skills before committing

dart run dart_skills_lint --skills-directory .agents/skills

if [ $? -ne 0 ]; then
    echo "Commit aborted: dart_skills_lint found errors."
    exit 1
fi

Make the hook executable:

chmod +x .git/hooks/pre-commit

CI Pipeline Integration

For GitHub Actions, add a validation step that fails the build on lint errors:

- name: Validate Agent Skills
  run: |
    dart pub get
    dart run dart_skills_lint \
      --skills-directory .agents/skills \
      --skills-directory .claude/skills

The non-zero exit code automatically halts the pipeline if skills violate specification rules.

Programmatic Validation in Dart Tests

Import the library directly to validate skills with dart_skills_lint from within your test suite:

import 'package:dart_skills_lint/dart_skills_lint.dart';
import 'package:test/test.dart';

void main() {
  test('Skills must pass dart_skills_lint', () async {
    // Validate using the same logic as the CLI
    await validateSkills(
      skillDirPaths: ['.agents/skills', '.claude/skills'],
      resolvedRules: {
        'check-relative-paths': AnalysisSeverity.error,
        'check-absolute-paths': AnalysisSeverity.error,
      },
    );
  });
}

Running dart test fails the CI job if any skill violates the selected rules. The validateSkills function exposes the same validation engine used by the CLI wrapper in cli.dart.

Creating Custom Validation Rules

Extend the linter with project-specific constraints by subclassing SkillRule:

import 'package:dart_skills_lint/dart_skills_lint.dart';

class NoDeprecatedRule extends SkillRule {
  @override
  final String name = 'no-deprecated';
  
  @override
  final AnalysisSeverity severity = AnalysisSeverity.error;

  @override
  Future<List<ValidationError>> validate(SkillContext ctx) async {
    final errors = <ValidationError>[];
    final yaml = ctx.parsedYaml;
    
    if (yaml != null && yaml['metadata']?['deprecated'] == true) {
      errors.add(ValidationError(
        ruleId: name,
        file: SkillContext.skillFileName,
        message: 'Skill is marked as deprecated.',
        severity: severity,
      ));
    }
    return errors;
  }
}

// Usage in tests
await validateSkills(
  skillDirPaths: ['.agents/skills'],
  customRules: [NoDeprecatedRule()],
);

Custom rules are discovered automatically when passed to the Validator (see Validator._buildRules in tool/dart_skills_lint/lib/src/validator.dart).

Summary

  • dart_skills_lint is a static analysis tool in flutter/skills that validates Agent Skill directories against the specification
  • The CLI in bin/cli.dart exits with non-zero status on AnalysisSeverity.error violations, enabling blocking pre-commit hooks and CI gates
  • Configure rules and severities in dart_skills_lint.yaml, parsed by ConfigParser in tool/dart_skills_lint/lib/src/config_parser.dart
  • The validation engine in validator.dart checks for SKILL.md, extracts YAML front-matter, and executes rules from rule_registry.dart against SkillContext
  • Import the package to write Dart tests using validateSkills() for programmatic validation
  • Extend functionality with custom SkillRule implementations registered via the customRules parameter

Frequently Asked Questions

What file does dart_skills_lint look for in each skill directory?

The validator requires each skill directory to contain a SKILL.md file. In tool/dart_skills_lint/lib/src/validator.dart, the _checkDirectoryStructure method verifies this file exists before extracting and parsing its YAML front-matter.

How do I make dart_skills_lint blocking in my CI pipeline?

The CLI automatically exits with a non-zero status code when any rule configured with error severity fails. Simply include dart run dart_skills_lint --skills-directory <path> as a step in your CI workflow; the exit code will halt the pipeline if validation fails.

Can I validate a single skill instead of an entire directory?

Yes. Use the --skill flag instead of --skills-directory to validate a specific path: dart run dart_skills_lint --skill ./path/to/specific_skill/. The validator processes only that directory, checking its SKILL.md and running enabled rules against it.

Where are the built-in rules defined in the flutter/skills repository?

Built-in rules are registered in tool/dart_skills_lint/lib/src/rule_registry.dart and implemented in individual files within tool/dart_skills_lint/lib/src/rules/. Each rule extends SkillRule and validates specific aspects of the skill context, such as name formatting, trailing whitespace, or path validation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →