Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .github/workflows/check-skills.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Check skills directory

on:
pull_request:
push:
branches: [master]

jobs:
check-skills:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Verify all skills are exposed or explicitly skipped
run: |
set -euo pipefail

# Collect skipped skills from .skillsrc
skipped=()
if [[ -f .skillsrc ]]; then
while IFS= read -r line; do
line="${line%%#*}" # strip inline comments
line="${line// /}" # trim whitespace
[[ -z "$line" ]] && continue
skipped+=("$line")
done < .skillsrc
fi

is_skipped() {
local skill="$1"
for s in "${skipped[@]+"${skipped[@]}"}"; do
[[ "$s" == "$skill" ]] && return 0
done
return 1
}

errors=()

# Find every skill directory (contains a SKILL.md)
while IFS= read -r skill_md; do
skill_dir="$(dirname "$skill_md")"
# e.g. plugins/core/skills/init -> extract plugin-relative path: core/skills/init
rel="${skill_dir#plugins/}"
skill_name="$(basename "$skill_dir")"

if is_skipped "$rel"; then
# Ensure skipped skills do NOT have a symlink
if [[ -L "skills/$skill_name" ]]; then
errors+=("Skill '$skill_name' is in .skillsrc but also symlinked in skills/")
fi
continue
fi

# Non-skipped skills MUST have a symlink
if [[ ! -L "skills/$skill_name" ]]; then
errors+=("Skill '$skill_name' ($rel) is not symlinked in skills/ and not listed in .skillsrc")
else
# Verify the symlink target resolves correctly
if [[ ! -d "skills/$skill_name" ]]; then
errors+=("Symlink skills/$skill_name is broken (target does not exist)")
fi
fi
done < <(find plugins -name SKILL.md -type f | sort)

# Check for symlinks pointing to non-existent skills
if [[ -d skills ]]; then
for link in skills/*; do
[[ -L "$link" ]] || continue
if [[ ! -d "$link" ]]; then
errors+=("Symlink $link is broken")
fi
done
fi

if [[ ${#errors[@]} -gt 0 ]]; then
echo "::error::Skills directory check failed:"
for err in "${errors[@]}"; do
echo " - $err"
done
echo ""
echo "To fix: add a symlink in skills/ or add the skill to .skillsrc"
exit 1
fi

echo "All skills are accounted for."
13 changes: 13 additions & 0 deletions .skillsrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Skills listed here are excluded from the top-level skills/ directory.
# One skill path per line, relative to the repo root (plugin/skills/skill-name).
# Lines starting with # are comments. Blank lines are ignored.
droid-control/skills/agent-browser
droid-control/skills/capture
droid-control/skills/compose
droid-control/skills/droid-cli
droid-control/skills/droid-control
droid-control/skills/pty-capture
droid-control/skills/showcase
droid-control/skills/true-input
droid-control/skills/tuistory
droid-control/skills/verify
1 change: 1 addition & 0 deletions skills/autoresearch
1 change: 1 addition & 0 deletions skills/browser-navigation
1 change: 1 addition & 0 deletions skills/commit-security-scan
1 change: 1 addition & 0 deletions skills/frontend-design
1 change: 1 addition & 0 deletions skills/human-writing
1 change: 1 addition & 0 deletions skills/init
1 change: 1 addition & 0 deletions skills/review
1 change: 1 addition & 0 deletions skills/security-review
1 change: 1 addition & 0 deletions skills/session-navigation
1 change: 1 addition & 0 deletions skills/skill-creation
1 change: 1 addition & 0 deletions skills/threat-model-generation
1 change: 1 addition & 0 deletions skills/visual-design
1 change: 1 addition & 0 deletions skills/vulnerability-validation
1 change: 1 addition & 0 deletions skills/wiki
Loading