Skill: 1va7/skill-refiner (version 1.0.0)

--- name: skill-refiner description: Audit and fix all skills in the workspace for compliance with skill-creator requirements. Use when asked to "refine skills", "audit skills", "check skill quality", or "fix non-compliant skills". Exhaustively searches the entire workspace (not just skills/) to find every SKILL.md, then audits and repairs each one. --- # Skill Refiner Finds every skill in the workspace, audits each against skill-creator requirements, and fixes non-compliant ones. ## Workflow ### Step 1 — Discover all skills ```bash bash scripts/find_skills.sh [workspace_dir] ``` This searches the **entire workspace** for `SKILL.md` files (not just `skills/`). Skills created without following skill-creator conventions may end up anywhere. ### Step 2 — Audit each skill ```bash python3 scripts/audit_skill.py <skill-dir> ``` Returns JSON with: - `issues` — blocking problems that must be fixed - `warnings` — advisory improvements - `compliant` — true only when issues is empty Run this on every path returned by Step 1. Batch example: ```bash bash scripts/find_skills.sh | while read dir; do python3 scripts/audit_skill.py "$dir" done ``` ### Step 3 — Report findings Summarize results in a table: | Skill | Location | Issues | Warnings | Status | |-------|----------|--------|----------|--------| | my-skill | skills/my-skill | 0 | 1 | ⚠️ | | bad-skill | temp/bad-skill | 2 | 0 | ❌ | ### Step 4 — Fix non-compliant skills For each skill with issues, fix in this order: 1. **Missing/malformed frontmatter** — Add or correct the `---` block with `name` and `description` only 2. **Extra frontmatter fields** — Remove any fields other than `name` and `description` 3. **Weak description** — Rewrite to include: what the skill does + trigger conditions ("Use when...") 4. **Extraneous files** — Delete README.md, INSTALLATION_GUIDE.md, CHANGELOG.md, etc. 5. **Wrong location** — If a skill is outside `skills/`, move it to `~/.openclaw/workspace/skills/<skill-name>/` 6. **Naming violations** — Rename directory to lowercase-hyphen-case For warnings (advisory): - Long SKILL.md (>500 lines): extract detailed content into `references/` files and link from SKILL.md - Unlinked references: add links in SKILL.md body - Weak description: improve trigger language ### Step 5 — Validate fixes Re-run `audit_skill.py` on each fixed skill to confirm `"compliant": true`. Optionally package with: ```bash python3 /opt/homebrew/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py <skill-dir> ``` ## Compliance Checklist A compliant skill must have: - [ ] `SKILL.md` at the root of a named directory - [ ] YAML frontmatter with exactly `name` and `description` (no other fields) - [ ] `description` includes what the skill does AND when to trigger it - [ ] Directory name: lowercase letters, digits, hyphens only; ≤64 chars - [ ] No extraneous files (README.md, CHANGELOG.md, etc.) - [ ] Resources only in `scripts/`, `references/`, or `assets/` - [ ] All `references/` files linked from SKILL.md body - [ ] SKILL.md body ≤500 lines (split into references/ if longer)

path: README.md
content: # skill-refiner

Audit and fix [OpenClaw](https://github.com/openclaw/openclaw) agent skills for [skill-creator](https://github.com/openclaw/openclaw/tree/main/skills/skill-creator) compliance.

[中文文档](./README.zh.md)

## Why?

OpenClaw skills need to follow specific conventions to be properly discovered and triggered. Common issues include:

- Missing or malformed YAML frontmatter
- Extra frontmatter fields (only `name` and `description` allowed)
- Extraneous files (README.md, CHANGELOG.md in skill directories)
- Weak descriptions that don't specify trigger conditions

This tool finds all skills in your workspace and reports compliance issues.

## Quick Start

```bash
# Scan your OpenClaw workspace
npx skill-refiner

# Scan a specific directory
npx skill-refiner /path/to/workspace
```

## Installation

### As an OpenClaw Skill

```bash
clawhub install skill-refiner
```

Then ask your agent: "audit my skills" or "check skill compliance"

### Global CLI

```bash
npm install -g skill-refiner
skill-refiner ~/.openclaw/workspace
```

## What It Checks

| Check | Severity | Description |
|-------|----------|-------------|
| SKILL.md exists | 🔴 Issue | Every skill needs a SKILL.md |
| YAML frontmatter | 🔴 Issue | Must start with `---` block |
| Required fields | 🔴 Issue | `name` and `description` required |
| Extra fields | 🔴 Issue | Only `name` + `description` allowed |
| Extraneous files | 🔴 Issue | No README.md, CHANGELOG.md, etc. |
| Naming convention | 🔴 Issue | lowercase-hyphen-case, ≤64 chars |
| Trigger conditions | 🟡 Warning | Description should include "Use when..." |
| SKILL.md length | 🟡 Warning | Recommended max 500 lines |
| Unlinked references | 🟡 Warning | Files in references/ should be linked |

## Output Example

```
🔍 skill-refiner — scanning: /Users/me/.openclaw/workspace

✅ markdown-converter
✅ weather
❌ my-broken-skill
  ✗  Frontmatter has extra fields: metadata, author
  ✗  Extraneous file: README.md
⚠️ another-skill
  ⚠️  Description doesn't clearly state trigger conditions

─────────────────────────────────
Total: 4  ✅ 2  ❌ 1  ⚠️ 1
```

## Programmatic Usage

```bash
# Find all skills
bash scripts/find_skills.sh /path/to/workspace

# Audit a single skill (returns JSON)
python3 scripts/audit_skill.py /path/to/skill-dir
```

## License

MIT


path: README.zh.md
content: # skill-refiner

审计并修复 [OpenClaw](https://github.com/openclaw/openclaw) agent skills，确保符合 [skill-creator](https://github.com/openclaw/openclaw/tree/main/skills/skill-creator) 规范。

[English](./README.md)

## 为什么需要这个工具？

OpenClaw skills 需要遵循特定规范才能被正确发现和触发。常见问题包括：

- 缺失或格式错误的 YAML frontmatter
- 多余的 frontmatter 字段（只允许 `name` 和 `description`）
- 多余的文件（skill 目录中不应有 README.md、CHANGELOG.md 等）
- 描述不清晰，没有说明触发条件

这个工具会扫描 workspace 中的所有 skills 并报告合规问题。

## 快速开始

```bash
# 扫描你的 OpenClaw workspace
npx skill-refiner

# 扫描指定目录
npx skill-refiner /path/to/workspace
```

## 安装

### 作为 OpenClaw Skill 安装

```bash
clawhub install skill-refiner
```

然后对你的 agent 说："审计我的 skills" 或 "检查 skill 合规性"

### 全局 CLI 安装

```bash
npm install -g skill-refiner
skill-refiner ~/.openclaw/workspace
```

## 检查项

| 检查项 | 严重程度 | 说明 |
|--------|----------|------|
| SKILL.md 存在 | 🔴 问题 | 每个 skill 必须有 SKILL.md |
| YAML frontmatter | 🔴 问题 | 必须以 `---` 块开头 |
| 必填字段 | 🔴 问题 | 必须有 `name` 和 `description` |
| 多余字段 | 🔴 问题 | 只允许 `name` + `description` |
| 多余文件 | 🔴 问题 | 不能有 README.md、CHANGELOG.md 等 |
| 命名规范 | 🔴 问题 | 小写字母+连字符，≤64 字符 |
| 触发条件 | 🟡 警告 | 描述应包含 "Use when..." 或 "用于..." |
| SKILL.md 长度 | 🟡 警告 | 建议不超过 500 行 |
| 未链接的引用 | 🟡 警告 | references/ 中的文件应在 SKILL.md 中链接 |

## 输出示例

```
🔍 skill-refiner — scanning: /Users/me/.openclaw/workspace

✅ markdown-converter
✅ weather
❌ my-broken-skill
  ✗  Frontmatter has extra fields: metadata, author
  ✗  Extraneous file: README.md
⚠️ another-skill
  ⚠️  Description doesn't clearly state trigger conditions

─────────────────────────────────
Total: 4  ✅ 2  ❌ 1  ⚠️ 1
```

## 编程使用

```bash
# 查找所有 skills
bash scripts/find_skills.sh /path/to/workspace

# 审计单个 skill（返回 JSON）
python3 scripts/audit_skill.py /path/to/skill-dir
```

## 许可证

MIT


path: bin/skill-refiner.sh
content: #!/usr/bin/env bash
# skill-refiner: Audit and fix OpenClaw skills for skill-creator compliance
# Usage: npx skill-refiner [workspace_dir]

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE="${1:-$HOME/.openclaw/workspace}"

echo "🔍 skill-refiner — scanning: $WORKSPACE"
echo ""

# Find all skills
SKILLS=$(bash "$SCRIPT_DIR/../scripts/find_skills.sh" "$WORKSPACE")

if [ -z "$SKILLS" ]; then
  echo "No skills found in $WORKSPACE"
  exit 0
fi

TOTAL=0
COMPLIANT=0
NON_COMPLIANT=0

while IFS= read -r skill_dir; do
  TOTAL=$((TOTAL + 1))
  result=$(python3 "$SCRIPT_DIR/../scripts/audit_skill.py" "$skill_dir")
  name=$(echo "$result" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('skill_name','?'))")
  is_compliant=$(echo "$result" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('compliant',False))")
  issues=$(echo "$result" | python3 -c "import sys,json; d=json.load(sys.stdin); print('\n  '.join(d.get('issues',[])))")
  warnings=$(echo "$result" | python3 -c "import sys,json; d=json.load(sys.stdin); print('\n  '.join(d.get('warnings',[])))")

  if [ "$is_compliant" = "True" ]; then
    COMPLIANT=$((COMPLIANT + 1))
    echo "✅ $name"
    if [ -n "$warnings" ]; then
      echo "  ⚠️  $warnings"
    fi
  else
    NON_COMPLIANT=$((NON_COMPLIANT + 1))
    echo "❌ $name"
    if [ -n "$issues" ]; then
      echo "  ✗  $issues"
    fi
    if [ -n "$warnings" ]; then
      echo "  ⚠️  $warnings"
    fi
  fi
done <<< "$SKILLS"

echo ""
echo "─────────────────────────────────"
echo "Total: $TOTAL  ✅ $COMPLIANT  ❌ $NON_COMPLIANT"


path: package.json
content: {
  "name": "skill-refiner",
  "version": "1.0.0",
  "description": "Audit and fix OpenClaw agent skills for skill-creator compliance",
  "keywords": ["openclaw", "agent", "skill", "ai", "codex"],
  "license": "MIT",
  "bin": {
    "skill-refiner": "./bin/skill-refiner.sh"
  },
  "files": [
    "bin/",
    "scripts/",
    "SKILL.md",
    "README.md",
    "README.zh.md"
  ],
  "engines": {
    "node": ">=18"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/1va7/skill-refiner.git"
  },
  "homepage": "https://github.com/1va7/skill-refiner"
}


path: scripts/audit_skill.py
content: #!/usr/bin/env python3
"""
Audit a skill directory for compliance with skill-creator requirements.
Usage: audit_skill.py <skill-dir>
Output: JSON with issues (blocking) and warnings (advisory)
"""

import sys
import re
import json
from pathlib import Path


EXTRANEOUS_FILES = {
    'README.md', 'INSTALLATION_GUIDE.md', 'QUICK_REFERENCE.md',
    'CHANGELOG.md', 'INSTALL.md', 'SETUP.md', 'CONTRIBUTING.md',
}
ALLOWED_SUBDIRS = {'scripts', 'references', 'assets', 'locales', 'docs'}
TRIGGER_KEYWORDS = ['use when', 'trigger', 'when to use', 'activate when', 'use for', 'when user', 'when asked']


def audit_skill(skill_dir: str) -> dict:
    path = Path(skill_dir)

    if not path.is_dir():
        return {"skill_dir": skill_dir, "error": "Not a directory", "issues": [], "warnings": [], "compliant": False}

    issues = []
    warnings = []
    skill_md = path / "SKILL.md"

    # 1. SKILL.md must exist
    if not skill_md.exists():
        return {"skill_dir": skill_dir, "skill_name": path.name, "issues": ["SKILL.md not found"], "warnings": [], "compliant": False}

    content = skill_md.read_text(encoding='utf-8')
    lines = content.splitlines()

    # 2. YAML frontmatter
    if not content.startswith('---'):
        issues.append("Missing YAML frontmatter (must start with ---)")
    else:
        end = content.find('\n---', 3)
        if end == -1:
            issues.append("Malformed YAML frontmatter (no closing ---)")
        else:
            fm = content[3:end].strip()

            has_name = bool(re.search(r'^name:\s*\S', fm, re.MULTILINE))
            has_desc = bool(re.search(r'^description:\s*\S', fm, re.MULTILINE))

            if not has_name:
                issues.append("Frontmatter missing required field: 'name'")
            if not has_desc:
                issues.append("Frontmatter missing required field: 'description'")

            # No extra fields allowed
            field_names = re.findall(r'^([a-zA-Z_]+)\s*:', fm, re.MULTILINE)
            extra = set(field_names) - {'name', 'description'}
            if extra:
                issues.append(f"Frontmatter has extra fields (only name+description allowed): {', '.join(sorted(extra))}")

            # Description quality: should mention when to use
            if has_desc:
                desc_block = re.search(r'^description:\s*(?:\|[-]?\s*\n)?([\s\S]+?)(?=\n[a-zA-Z_]+\s*:|$)', fm, re.MULTILINE)
                if desc_block:
                    desc_text = desc_block.group(1).strip().lower()
                    # Strip YAML block scalar indent
                    desc_text = re.sub(r'\n\s+', ' ', desc_text)
                    if not any(kw in desc_text for kw in TRIGGER_KEYWORDS):
                        warnings.append("Description doesn't clearly state trigger conditions (add 'Use when...' or similar)")
                    if len(desc_text) < 60:
                        warnings.append(f"Description is very short ({len(desc_text)} chars) — should be comprehensive for reliable triggering")

    # 3. Naming convention
    name = path.name
    if not re.match(r'^[a-z0-9][a-z0-9-]*$', name):
        issues.append(f"Directory name '{name}' violates convention (lowercase letters, digits, hyphens only; no leading hyphen)")
    if len(name) > 64:
        issues.append(f"Directory name too long ({len(name)} chars, max 64)")

    # 4. Extraneous files
    for fname in EXTRANEOUS_FILES:
        if (path / fname).exists():
            issues.append(f"Extraneous file: {fname} (remove — skills should not contain auxiliary docs)")

    # 5. Unexpected subdirectories
    for item in path.iterdir():
        if item.is_dir() and not item.name.startswith('.') and item.name not in ALLOWED_SUBDIRS:
            warnings.append(f"Unexpected subdirectory: {item.name}/ (allowed: scripts/, references/, assets/)")

    # 6. SKILL.md length
    if len(lines) > 500:
        warnings.append(f"SKILL.md is {len(lines)} lines — consider splitting into references/ files (recommended max: 500)")

    # 7. References linked from SKILL.md
    refs_dir = path / 'references'
    if refs_dir.exists():
        for ref in refs_dir.iterdir():
            if ref.is_file() and ref.name not in content:
                warnings.append(f"references/{ref.name} is not linked from SKILL.md")

    return {
        "skill_dir": str(path.resolve()),
        "skill_name": name,
        "issues": issues,
        "warnings": warnings,
        "compliant": len(issues) == 0,
    }


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Usage: audit_skill.py <skill-dir>", file=sys.stderr)
        sys.exit(1)
    print(json.dumps(audit_skill(sys.argv[1]), indent=2))


path: scripts/find_skills.sh
content: #!/bin/bash
# Find all skill directories in the workspace.
# Searches for SKILL.md files anywhere in the workspace tree.
# Usage: find_skills.sh [workspace_dir]
# Output: one skill directory path per line

WORKSPACE="${1:-$HOME/.openclaw/workspace}"

find "$WORKSPACE" \
  -name "SKILL.md" \
  -not -path "*/node_modules/*" \
  -not -path "*/.git/*" \
  | while read -r skill_md; do
      dirname "$skill_md"
    done \
  | sort -u


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)