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:
- CLI Entry Point:
bin/cli.dartinvokesrunApp(arguments), forwarding totool/dart_skills_lint/lib/src/entry_point.dart - Argument Parsing: The entry point builds a list of directories (
--skills-directory) or individual paths (--skill) - Configuration Loading:
ConfigParserreadsdart_skills_lint.yamlto determine enabled rules and severities - Directory Validation:
Validator.validate()intool/dart_skills_lint/lib/src/validator.dartcalls_checkDirectoryStructureto verify the folder exists and contains aSKILL.mdfile - YAML Extraction: The validator reads
SKILL.md, extracts YAML front-matter usingSkillContext.skillStartRegex, and parses it withloadYaml - Rule Execution: The
Validatorinstantiates rules fromtool/dart_skills_lint/lib/src/rule_registry.dartand runs them against theSkillContext. Each rule returnsValidationErrorobjects containingruleId, file location, message, andAnalysisSeverity - 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.dartexits with non-zero status onAnalysisSeverity.errorviolations, enabling blocking pre-commit hooks and CI gates - Configure rules and severities in
dart_skills_lint.yaml, parsed byConfigParserintool/dart_skills_lint/lib/src/config_parser.dart - The validation engine in
validator.dartchecks forSKILL.md, extracts YAML front-matter, and executes rules fromrule_registry.dartagainstSkillContext - Import the package to write Dart tests using
validateSkills()for programmatic validation - Extend functionality with custom
SkillRuleimplementations registered via thecustomRulesparameter
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →