Skip to content

feat(skills): add /skill validate for skill-file linting#175

Merged
emal-avala merged 2 commits intomainfrom
feat/skill-validator
Apr 23, 2026
Merged

feat(skills): add /skill validate for skill-file linting#175
emal-avala merged 2 commits intomainfrom
feat/skill-validator

Conversation

@emal-avala
Copy link
Copy Markdown
Member

Summary

Adds `/skill validate ` (also `/skill lint`) and the underlying `skills::validate_skill_file` function. Lints skill files and reports findings grouped by severity.

What it catches:

Severity Finding
Error missing `description`
Error body is empty
Error malformed frontmatter (unclosed `---`, etc.)
Warning `whenToUse` empty on a `userInvocable` skill
Warning `description` longer than 160 chars
Warning body shorter than 100 chars
Warning narrative phrases in body ("let me…", "I will…", "we should…")
Warning filename isn't kebab-case (skipped for `SKILL.md`)
Info body contains fenced shell blocks (heads-up about `disable_skill_shell_execution`)

Accepts a file or a directory; for a directory, walks all `.md` entries and prints per-file findings plus an aggregate summary.

Why

We've been shipping bundled skills at a rapid clip and the pattern is already drifting in tiny ways — some skills have empty `whenToUse`, some drift into first-person narrative, some have descriptions too long to display in `/help`. A linter keeps the house style enforceable both for bundled additions and for user-authored skills.

Implementation

  • New `validate_skill_file(path) -> Vec` in `crates/lib/src/skills/mod.rs` (~180 LOC incl. tests)
  • New `ValidationLevel` enum + `Finding` struct, both `pub`
  • New `execute_skill_validate` helper in `crates/cli/src/commands/mod.rs` that walks files + prints
  • Wired into the existing `/skill` subcommand (alongside `install` / `remove` / `search` / `installed`)

Errors returned as findings, not `Result::Err` — the validator reports everything in one pass rather than stopping at the first problem.

Test plan

  • `cargo fmt --all` clean
  • `cargo check` passes
  • `cargo clippy --no-deps` clean
  • `cargo test -p agent-code-lib --lib skills` — 19 tests pass (7 new for validate_skill_file + 1 for is_kebab_case + 11 existing)
  • Manual: `/skill validate .agent/skills/` on a directory with a clean skill, a missing-description skill, and a narrative skill — each findings emitted with the right severity

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Catches the common authoring mistakes before they ship as a skill:
missing description, empty whenToUse on user-invocable skills,
narrative first-person bodies ("let me…", "I will…"), oversize
descriptions, empty bodies, too-short bodies, non-kebab-case
filenames, malformed frontmatter, and fenced shell blocks that will
get stripped under `disable_skill_shell_execution`.

New `validate_skill_file(path) -> Vec<Finding>` returns ordered
findings with severity (Error / Warning / Info). `/skill validate
<path>` accepts a file or a directory (walks .md files), prints
per-file findings, and ends with an aggregate summary.

SKILL.md (directory-based skill layout) gets a filename-check
exemption since the skill name comes from the containing directory.

Errors like missing description or broken frontmatter are returned
as findings rather than `Result::Err` so the validator can report
everything in one pass.
@emal-avala emal-avala force-pushed the feat/skill-validator branch from 2cd489e to b455ac5 Compare April 23, 2026 01:30
@emal-avala emal-avala merged commit 37d2eec into main Apr 23, 2026
13 of 14 checks passed
@emal-avala emal-avala deleted the feat/skill-validator branch April 23, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant