# How to Validate Skills with dart_skills_lint Before Committing

> Validate Agent Skill directories before committing using dart_skills_lint. Ensure compliance with the specification for smoother CI integration and prevent errors.

- Repository: [Flutter/skills](https://github.com/flutter/skills)
- Tags: how-to-guide
- Published: 2026-05-09

---

**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](https://github.com/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:

```bash

# 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`](https://github.com/flutter/skills/blob/main/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:

```yaml

# 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`](https://github.com/flutter/skills/blob/main/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`](https://github.com/flutter/skills/blob/main/SKILL.md) file
5. **YAML Extraction**: The validator reads [`SKILL.md`](https://github.com/flutter/skills/blob/main/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`:

```bash
#!/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:

```bash
chmod +x .git/hooks/pre-commit

```

### CI Pipeline Integration

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

```yaml
- 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:

```dart
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`:

```dart
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`](https://github.com/flutter/skills/blob/main/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`](https://github.com/flutter/skills/blob/main/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`](https://github.com/flutter/skills/blob/main/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`](https://github.com/flutter/skills/blob/main/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.