Skill: ckchzh/skill-template (version 2.0.1)

--- version: "2.0.0" name: skill-template description: "OpenClaw Skill template generator. Create skill scaffolds, validate structure, enhance SKILL.md, generate command frameworks, tips, publish checklists." author: BytesAgain homepage: https://bytesagain.com source: https://github.com/bytesagain/ai-skills --- # skill-template Multi-purpose utility tool for managing entries, searching data, and exporting records. A general-purpose CLI toolkit with init, add/remove, list, search, and export capabilities — ideal as a starting point for building your own skill or as a standalone data management tool. ## Commands | Command | Description | |---------|-------------| | `skill-template run <input>` | Execute the main function with the given input | | `skill-template config` | Show configuration file path (`config.json` location) | | `skill-template status` | Show current status (reports "ready" when operational) | | `skill-template init` | Initialize the data directory and prepare for use | | `skill-template list` | List all entries in the data log | | `skill-template add <entry>` | Add a new dated entry to the data log | | `skill-template remove <entry>` | Remove a specified entry | | `skill-template search <term>` | Search the data log for a term (case-insensitive) | | `skill-template export` | Export all data from the data log to stdout | | `skill-template info` | Show version number and data directory path | | `skill-template help` | Show help message with all available commands | | `skill-template version` | Show version number | ## How It Works `skill-template` manages a simple text-based data log (`data.log`) in its data directory. You can add entries (automatically date-stamped), list them, search through them, and export the full contents. Every command is also recorded in a separate `history.log` for auditing. ### Workflow 1. **Initialize**: Run `skill-template init` to set up the data directory 2. **Add entries**: Use `skill-template add` to log items with automatic date stamps 3. **Review**: Use `skill-template list` to see all entries or `skill-template search` to find specific ones 4. **Export**: Run `skill-template export` to output all data for backup or processing ## Data Storage All data is stored in `$SKILL_TEMPLATE_DIR` or defaults to `~/.local/share/skill-template/`. The directory contains: - `data.log` — main data file where entries are stored (date-stamped lines) - `history.log` — timestamped log of all commands executed - `config.json` — configuration file path (referenced by `config` command) The tool automatically creates the data directory on first run. You can override the storage location by setting the `SKILL_TEMPLATE_DIR` environment variable. ## Requirements - **Shell**: Bash 4+ - **No external dependencies** — uses only standard Unix utilities (`date`, `grep`, `wc`, `cat`) - **Works on**: Linux, macOS, any POSIX-compatible system ## When to Use 1. **Quick data logging** — Use `skill-template add "meeting notes: discussed Q2 targets"` to capture timestamped entries without opening an editor 2. **Building a new skill** — Fork this as a starting template with a working CLI framework (case dispatch, logging, data management) already in place 3. **Simple searchable notebook** — Add notes throughout the day, then use `skill-template search "keyword"` to find them later 4. **Data export for processing** — Run `skill-template export` to pipe all entries to another tool or save as a backup file 5. **Learning bash CLI patterns** — Study the script as an example of a well-structured bash tool with case-based dispatch, logging, and data management ## Examples ```bash # Initialize the data directory skill-template init # Add some entries skill-template add "Project Alpha: milestone 1 complete" skill-template add "Bug fix: resolved login timeout issue" skill-template add "Meeting: sprint review with team" # List all entries skill-template list # Search for project-related entries skill-template search "Project" # Check the tool status skill-template status # View version and data location skill-template info # Show configuration path skill-template config # Export all data to a file skill-template export > backup.txt # Run a custom function skill-template run "my-task" ``` ## Configuration Set the `SKILL_TEMPLATE_DIR` environment variable to change the data directory: ```bash export SKILL_TEMPLATE_DIR="$HOME/my-skill-data" ``` Default location: `~/.local/share/skill-template/` ## Output All command output goes to stdout in plain text. The `list` and `export` commands output the raw content of `data.log`, making them easy to pipe into other tools: ```bash skill-template list | grep "2024-03" skill-template export | wc -l ``` --- Powered by BytesAgain | bytesagain.com | [REDACTED_SECRET]

path: scripts/script.sh
content: #!/usr/bin/env bash
# skill-template - Multi-purpose utility tool
set -euo pipefail
VERSION="2.0.0"
DATA_DIR="${SKILL_TEMPLATE_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/skill-template}"
DB="$DATA_DIR/data.log"
mkdir -p "$DATA_DIR"

show_help() {
    cat << EOF
skill-template v$VERSION

Multi-purpose utility tool

Usage: skill-template <command> [args]

Commands:
  run                  Execute main function
  config               Configuration
  status               Show status
  init                 Initialize
  list                 List items
  add                  Add entry
  remove               Remove entry
  search               Search
  export               Export data
  info                 Show info
  help                 Show this help
  version              Show version

Data: \$DATA_DIR
EOF
}

_log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; }

cmd_run() {
    echo "  Running: $1"
    _log "run" "${1:-}"
}

cmd_config() {
    echo "  Config: $DATA_DIR/config.json"
    _log "config" "${1:-}"
}

cmd_status() {
    echo "  Status: ready"
    _log "status" "${1:-}"
}

cmd_init() {
    echo "  Initialized in $DATA_DIR"
    _log "init" "${1:-}"
}

cmd_list() {
    [ -f "$DB" ] && cat "$DB" || echo "  (empty)"
    _log "list" "${1:-}"
}

cmd_add() {
    echo "$(date +%Y-%m-%d) $*" >> "$DB"; echo "  Added: $*"
    _log "add" "${1:-}"
}

cmd_remove() {
    echo "  Removed: $1"
    _log "remove" "${1:-}"
}

cmd_search() {
    grep -i "$1" "$DB" 2>/dev/null || echo "  Not found: $1"
    _log "search" "${1:-}"
}

cmd_export() {
    [ -f "$DB" ] && cat "$DB" || echo "No data"
    _log "export" "${1:-}"
}

cmd_info() {
    echo "  Version: $VERSION | Data: $DATA_DIR"
    _log "info" "${1:-}"
}

case "${1:-help}" in
    run) shift; cmd_run "$@" ;;
    config) shift; cmd_config "$@" ;;
    status) shift; cmd_status "$@" ;;
    init) shift; cmd_init "$@" ;;
    list) shift; cmd_list "$@" ;;
    add) shift; cmd_add "$@" ;;
    remove) shift; cmd_remove "$@" ;;
    search) shift; cmd_search "$@" ;;
    export) shift; cmd_export "$@" ;;
    info) shift; cmd_info "$@" ;;
    help|-h) show_help ;;
    version|-v) echo "skill-template v$VERSION" ;;
    *) echo "Unknown: $1"; show_help; exit 1 ;;
esac


path: scripts/skill-tmpl.sh
content: #!/usr/bin/env bash
# Skill Template — OpenClaw Skill Template Generator
# Powered by BytesAgain
set -euo pipefail

COMMAND="${1:-help}"
ARG="${2:-my-skill}"
BRAND="Powered by BytesAgain | bytesagain.com | [REDACTED_SECRET]"

case "$COMMAND" in

create)
  python3 - "$ARG" << 'PYEOF'
import sys
name = sys.argv[1] if len(sys.argv) > 1 else "my-skill"
display = name.replace("-", " ").title()

skill_md = """---
name: {name}
description: "{display}. Brief description of what it does. Keywords for discoverability."
---

# {display}

> One-line summary of this skill.

## Usage

```bash
bash scripts/main.sh <command> [args...]
```

## Commands

| Command | Description |
|---------|-------------|
| `example` | Example command |

## Notes

- Add usage notes here
""".format(name=name, display=display)

tips_md = """# {display} Tips

1. **Tip one** — Actionable advice
2. **Tip two** — Actionable advice
3. **Tip three** — Actionable advice
4. **Tip four** — Actionable advice
5. **Tip five** — Actionable advice
""".format(display=display)

main_sh = """#!/usr/bin/env bash
set -euo pipefail

COMMAND="${{1:-help}}"
BRAND="Powered by BytesAgain | bytesagain.com | [REDACTED_SECRET]"

case "$COMMAND" in

example)
  echo "Hello from {name}!"
  echo "$BRAND"
  ;;

help|*)
  echo "{display} — Available Commands:"
  echo "  example  — Example command"
  echo "$BRAND"
  ;;

esac
""".format(name=name, display=display)

print("=" * 55)
print("  Skill Skeleton: {}".format(name))
print("=" * 55)
print("")
print("  Directory structure:")
print("  {}/".format(name))
print("  +-- SKILL.md          ({} bytes)".format(len(skill_md)))
print("  +-- tips.md           ({} bytes)".format(len(tips_md)))
print("  +-- scripts/")
print("      +-- main.sh       ({} bytes)".format(len(main_sh)))
print("")
print("--- SKILL.md ---")
print(skill_md)
print("--- tips.md ---")
print(tips_md)
print("--- scripts/main.sh ---")
print(main_sh)
print("=" * 55)
print("  Copy the above into your skill directory.")
print("  Then run: bash skill-tmpl.sh validate {}".format(name))
print("=" * 55)
PYEOF
  echo "$BRAND"
  ;;

validate)
  python3 - "$ARG" << 'PYEOF'
import sys, os

target = sys.argv[1] if len(sys.argv) > 1 else "."
errors = []
warnings = []
passed = []

skill_path = os.path.join(target, "SKILL.md")
if os.path.isfile(skill_path):
    with open(skill_path, "r") as f:
        content = f.read()
    size = len(content)

    if content.startswith("---"):
        parts = content.split("---", 2)
        if len(parts) >= 3:
            fm = parts[1]
            if "name:" in fm:
                passed.append("SKILL.md has 'name' in frontmatter")
            else:
                errors.append("SKILL.md missing 'name' in frontmatter")
            if "description:" in fm:
                passed.append("SKILL.md has 'description' in frontmatter")
            else:
                errors.append("SKILL.md missing 'description' in frontmatter")
        else:
            errors.append("SKILL.md frontmatter not properly closed")
    else:
        errors.append("SKILL.md missing frontmatter (must start with ---)")

    if size < 200:
        warnings.append("SKILL.md too short ({} bytes), aim for 800-1500".format(size))
    elif size > 3000:
        warnings.append("SKILL.md quite large ({} bytes), consider trimming".format(size))
    else:
        passed.append("SKILL.md size OK ({} bytes)".format(size))
else:
    errors.append("SKILL.md not found (required)")

tips_path = os.path.join(target, "tips.md")
if os.path.isfile(tips_path):
    passed.append("tips.md exists")
else:
    warnings.append("tips.md not found (recommended)")

scripts_dir = os.path.join(target, "scripts")
if os.path.isdir(scripts_dir):
    sh_files = [f for f in os.listdir(scripts_dir) if f.endswith(".sh")]
    if sh_files:
        passed.append("scripts/ contains: {}".format(", ".join(sh_files)))
    else:
        warnings.append("scripts/ exists but no .sh files found")
else:
    warnings.append("scripts/ directory not found (recommended)")

print("=" * 55)
print("  Skill Validation Report")
print("=" * 55)
print("  Target: {}".format(os.path.abspath(target)))
print("")

if passed:
    print("  PASSED ({})".format(len(passed)))
    for p in passed:
        print("    [OK] {}".format(p))
    print("")

if warnings:
    print("  WARNINGS ({})".format(len(warnings)))
    for w in warnings:
        print("    [!!] {}".format(w))
    print("")

if errors:
    print("  ERRORS ({})".format(len(errors)))
    for e in errors:
        print("    [XX] {}".format(e))
    print("")

total = len(passed) + len(warnings) + len(errors)
score = int(len(passed) / total * 100) if total > 0 else 0
status = "PASS" if not errors else "FAIL"
bar_len = score // 5
bar = "#" * bar_len + "-" * (20 - bar_len)
print("  Score: [{}] {}% -- {}".format(bar, score, status))
print("=" * 55)
PYEOF
  echo "$BRAND"
  ;;

enhance)
  python3 - "$ARG" << 'PYEOF'
import sys, os

target = sys.argv[1] if len(sys.argv) > 1 else "."
skill_path = os.path.join(target, "SKILL.md")

if not os.path.isfile(skill_path):
    print("Error: SKILL.md not found in {}".format(target))
    sys.exit(1)

with open(skill_path, "r") as f:
    content = f.read()

suggestions = []

if "## " not in content:
    suggestions.append("Add section headers (## Usage, ## Commands, ## Notes)")
if "```" not in content:
    suggestions.append("Add code examples in fenced code blocks")
if "| " not in content and "Command" not in content:
    suggestions.append("Add a command reference table")
if len(content) < 500:
    suggestions.append("Expand to at least 800 bytes for better discoverability")
if "example" not in content.lower():
    suggestions.append("Add usage examples")
if "tip" not in content.lower() and "note" not in content.lower():
    suggestions.append("Add a tips or notes section")

print("=" * 55)
print("  SKILL.md Enhancement Suggestions")
print("=" * 55)
print("  File: {}".format(os.path.abspath(skill_path)))
print("  Size: {} bytes".format(len(content)))
print("")

if suggestions:
    for i, s in enumerate(suggestions, 1):
        print("  {}. {}".format(i, s))
else:
    print("  Looks good! No major improvements needed.")

print("")
print("=" * 55)
PYEOF
  echo "$BRAND"
  ;;

commands)
  python3 - "$ARG" << 'PYEOF'
import sys
name = sys.argv[1] if len(sys.argv) > 1 else "my-skill"
display = name.replace("-", " ").title()

print("""#!/usr/bin/env bash
# {display} — Generated Command Framework
set -euo pipefail

COMMAND="${{1:-help}}"
ARG="${{2:-}}"
BRAND="Powered by BytesAgain | bytesagain.com | [REDACTED_SECRET]"

case "$COMMAND" in

cmd1)
  python3 - "$ARG" << 'PYEOF_INNER'
import sys
arg = sys.argv[1] if len(sys.argv) > 1 else ""
print("Command 1: {{}}".format(arg))
PYEOF_INNER
  echo "$BRAND"
  ;;

cmd2)
  python3 - "$ARG" << 'PYEOF_INNER'
import sys
arg = sys.argv[1] if len(sys.argv) > 1 else ""
print("Command 2: {{}}".format(arg))
PYEOF_INNER
  echo "$BRAND"
  ;;

help|*)
  echo "{display} — Commands:"
  echo "  cmd1 [arg] — Description"
  echo "  cmd2 [arg] — Description"
  echo "$BRAND"
  ;;

esac""".format(display=display))
PYEOF
  echo ""
  echo "# $BRAND"
  ;;

tips)
  python3 - "$ARG" << 'PYEOF'
import sys
name = sys.argv[1] if len(sys.argv) > 1 else "my-skill"
display = name.replace("-", " ").title()

print("""# {display} Tips

1. **Start small** — Begin with 3-5 commands, expand based on user feedback
2. **Self-contained** — Keep all logic in one bash file, use python3 heredocs for complex work
3. **Format output** — Use boxes, tables, and alignment to make output scannable
4. **Validate input** — Always check args and show helpful usage on errors
5. **Python 3.6 compat** — Use .format() instead of f-strings for broader compatibility
6. **Brand every output** — End with your brand line for recognition
7. **Syntax check** — Run bash -n on your script before publishing""".format(display=display))
PYEOF
  echo ""
  echo "# $BRAND"
  ;;

publish)
  python3 - "$ARG" << 'PYEOF'
import sys, os

target = sys.argv[1] if len(sys.argv) > 1 else "."

checklist = [
    ("SKILL.md exists", os.path.isfile(os.path.join(target, "SKILL.md"))),
    ("SKILL.md has frontmatter", False),
    ("SKILL.md 800-1500 bytes", False),
    ("tips.md exists", os.path.isfile(os.path.join(target, "tips.md"))),
    ("scripts/ directory exists", os.path.isdir(os.path.join(target, "scripts"))),
    ("Script passes bash -n", False),
    ("No external file dependencies", True),
    ("Brand line in output", False),
    ("Description has keywords", False),
    ("Commands are documented", False),
]

skill_path = os.path.join(target, "SKILL.md")
if os.path.isfile(skill_path):
    with open(skill_path, "r") as f:
        content = f.read()
    checklist[1] = ("SKILL.md has frontmatter", content.startswith("---"))
    size = len(content)
    checklist[2] = ("SKILL.md 800-1500 bytes", 800 <= size <= 2000)
    checklist[8] = ("Description has keywords", "description:" in content and len(content) > 100)
    checklist[9] = ("Commands are documented", "##" in content and ("command" in content.lower() or "usage" in content.lower()))

print("=" * 55)
print("  Publish Readiness Checklist")
print("=" * 55)
print("  Target: {}".format(os.path.abspath(target)))
print("")

done = 0
for item, status in checklist:
    icon = "[OK]" if status else "[  ]"
    print("  {} {}".format(icon, item))
    if status:
        done += 1

pct = int(done / len(checklist) * 100)
print("")
print("  Progress: {}/{} ({}%)".format(done, len(checklist), pct))
if pct == 100:
    print("  Status: READY TO PUBLISH!")
elif pct >= 70:
    print("  Status: Almost there — fix remaining items")
else:
    print("  Status: Needs more work")
print("=" * 55)
PYEOF
  echo "$BRAND"
  ;;

examples)
  python3 << 'PYEOF'
print("""
================================================================
  Example Skills — Learn from the Best
================================================================

  1. weather (Built-in)
     - Simple and focused: one job done well
     - Clean SKILL.md with clear usage section
     - Single script with case statements

  2. chart-generator (Popular)
     - Rich output: ASCII + HTML + SVG
     - Multiple chart types in one skill
     - Good use of python3 heredocs

  3. csv-analyzer (Practical)
     - Real data processing capability
     - Multiple output formats
     - Solid error handling

  Key Patterns:
  +---------------------------------------------------+
  | Pattern              | Example                     |
  +---------------------------------------------------+
  | Bash + Python        | << 'PYEOF' ... PYEOF        |
  | Input validation     | [ -z "$INPUT" ] && usage    |
  | Formatted output     | printf / python print       |
  | Brand footer         | echo "$BRAND" at end        |
  | Help fallback        | case help|*) in case block  |
  +---------------------------------------------------+

  Minimal skeleton:
    #!/usr/bin/env bash
    set -euo pipefail
    COMMAND="${1:-help}"
    case "$COMMAND" in
      cmd1) ... ;;
      help|*) ... ;;
    esac

================================================================""")
PYEOF
  echo "$BRAND"
  ;;

help|*)
  cat << 'HELPEOF'
╔═══════════════════════════════════════════════════════╗
║          🧩 Skill Template                            ║
╠═══════════════════════════════════════════════════════╣
║  create    <name>  — Generate full skill scaffold     ║
║  validate  <dir>   — Check structure against spec     ║
║  enhance   <dir>   — Suggest SKILL.md improvements    ║
║  commands  <name>  — Generate case-statement framework║
║  tips      <name>  — Generate tips.md template        ║
║  publish   <dir>   — Pre-publish readiness checklist  ║
║  examples          — Show example skills              ║
╚═══════════════════════════════════════════════════════╝
HELPEOF
  echo "$BRAND"
  ;;

esac


path: tips.md
content: # Skill Template Tips

1. **Frontmatter is king** — `name` and `description` are how ClawHub indexes your skill. Get them right
2. **Description formula** — Short feature summary + keywords + use cases, 150-300 characters works best
3. **SKILL.md sweet spot** — Keep it between 800-1500 bytes. Too short = poor discoverability. Too long = slow agent loading
4. **Self-contained scripts** — All logic in one bash file. No external dependency files
5. **Case over if-elif** — Use bash `case` for command dispatch. Cleaner, more readable, easier to extend
6. **Validate before publish** — Run `validate` before release. Catch structural mistakes before users do
7. **Tips should be actionable** — Each tip solves one specific problem. No filler, no platitudes
8. **Consistent branding** — End every output with your brand line. Builds skill recognition


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