Validate OpenClaw SKILL.md files in CI. Annotate PRs with inline errors. Zero config.
Every time you open a PR that touches a SKILL.md, this action:
- Finds all
SKILL.mdfiles in your repository - Validates them against the OpenClaw skill spec
- Annotates your PR diff with inline error/warning comments — no context switching
- Posts a summary to the GitHub Actions job summary tab
- Fails the build if errors are found (configurable for warnings too)
The kind of things it catches:
| Rule | Level | Example |
|---|---|---|
missing-name |
🔴 Error | name: field is absent |
missing-description |
🔴 Error | description: field is absent |
missing-openclaw-metadata |
No metadata.openclaw block |
|
missing-emoji |
metadata.openclaw.emoji not set (used in ClawHub UI) |
|
description-too-short |
Description under 20 chars — hurts discovery | |
missing-examples |
No ## Examples or ## Commands section |
|
missing-setup |
Has requires but no ## Setup section |
|
install-missing-kind |
Install entry missing kind: (brew/apt/manual) |
|
env-not-uppercase |
Env var name isn't UPPER_CASE | |
name-format |
Name isn't kebab-case |
Add this file to your skill repo as .github/workflows/lint.yml:
name: Lint Skill
on:
push:
branches: [main]
paths:
- '**/SKILL.md'
pull_request:
paths:
- '**/SKILL.md'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: effectorHQ/skill-lint-action@v1That's it. Open a PR with a SKILL.md change and you'll see inline annotations.
| Input | Required | Default | Description |
|---|---|---|---|
path |
No | . |
Path to search for SKILL.md files. Can be a directory or a specific file. |
fail-on-warnings |
No | false |
Exit with code 1 if any warnings are found (not just errors). |
glob |
No | '' |
Glob pattern to find SKILL.md files. Overrides path when set. |
json |
No | false |
Output results as JSON instead of human-readable text. |
| Output | Description |
|---|---|
errors |
Number of validation errors found |
warnings |
Number of validation warnings found |
files-checked |
Number of SKILL.md files checked |
Use outputs to conditionally run downstream steps:
- name: Lint
id: lint
uses: effectorHQ/skill-lint-action@v1
- name: Only runs if lint passed
if: steps.lint.outputs.errors == '0'
run: clawhub publish- uses: effectorHQ/skill-lint-action@v1- uses: effectorHQ/skill-lint-action@v1
with:
fail-on-warnings: 'true'- uses: effectorHQ/skill-lint-action@v1
with:
path: 'skills/'- uses: effectorHQ/skill-lint-action@v1
with:
path: 'skills/my-skill/SKILL.md'Lint must pass before releasing to ClawHub:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: effectorHQ/skill-lint-action@v1
with:
fail-on-warnings: 'true'
publish:
needs: lint
runs-on: ubuntu-latest
steps:
- run: clawhub publish
env:
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}See examples/workflows/ for complete workflow files.
skill-lint is the standalone CLI — run it locally before committing.
skill-lint-action wraps the same rules and adds:
- Inline PR annotations — errors appear directly on the diff line, not just in logs
- Job summary — a formatted table in the Actions summary tab
- Zero setup — no
npm installstep, no config, just add the action - Outputs — use
steps.lint.outputs.errorsin downstream steps
Use both: CLI locally while writing, Action in CI as the gate.
- Zero external dependencies — uses only Node.js 20 built-ins
- No Docker overhead — runs directly on the GitHub runner (fast startup)
- Works offline/in enterprise — no network calls during linting
dist/index.jsis committed and self-contained — no build step required to use this action
Issues and PRs welcome. See CONTRIBUTING.md.
The core validation rules live in dist/index.js (self-contained) and the corresponding source in src/. If you're adding a new rule, add it in both places and add a test fixture + test case.
skill-lint— the CLI version of this linterplugin-template— SKILL.md starter templatecookbook— example skills you can reference- ClawHub — publish your validated skill to the registry
MIT License — effectorHQ Contributors