From a07e1aac6e1f0e91d2c2c43207cc061fb80a09c4 Mon Sep 17 00:00:00 2001 From: Arun Kumar Thiagarajan Date: Tue, 24 Mar 2026 14:41:43 +0530 Subject: [PATCH] =?UTF-8?q?feat:=20gstack-skill-share=20=E2=80=94=20packag?= =?UTF-8?q?e=20skills=20for=20community=20sharing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creates .gstack-skill.tar.gz archives with metadata manifest: - Bundles .tmpl + supporting files (templates, checklists) - Generates manifest.json with name, version, author, gstack version - Optional --validate flag runs gstack-skill-validate before packaging - --list shows all installed skills with versions Shareable archive format for community skill distribution. Recipients install with: tar xzf skill.tar.gz -C ~/.claude/skills/gstack/ --- bin/gstack-skill-share | 100 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 bin/gstack-skill-share diff --git a/bin/gstack-skill-share b/bin/gstack-skill-share new file mode 100755 index 00000000..995ae35b --- /dev/null +++ b/bin/gstack-skill-share @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# gstack-skill-share — package a skill for community sharing +# +# Creates a shareable .tar.gz archive with metadata for community import. +# The archive includes the .tmpl file, any supporting files (templates, +# checklists), and a manifest with validation results. +# +# Usage: +# gstack-skill-share # package for sharing +# gstack-skill-share --validate # validate before packaging +# gstack-skill-share --list # list installed community skills +# +# Output: .gstack-skill.tar.gz (shareable archive) +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +GSTACK_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +case "${1:-}" in + --list) + echo "Installed skills:" + for d in "$GSTACK_DIR"/*/; do + [ -f "$d/SKILL.md.tmpl" ] || continue + name=$(basename "$d") + version=$(grep "^version:" "$d/SKILL.md.tmpl" 2>/dev/null | head -1 | awk '{print $2}' || echo "?") + desc=$(grep -A1 "^description:" "$d/SKILL.md.tmpl" 2>/dev/null | tail -1 | sed 's/^ *//' || echo "") + printf " /%-20s v%-8s %s\n" "$name" "$version" "${desc:0:50}" + done + exit 0 + ;; + --help|-h) + echo "Usage: gstack-skill-share [--validate]" + exit 0 + ;; +esac + +SKILL_DIR="${1:?Usage: gstack-skill-share }" +VALIDATE="${2:-}" + +# Resolve skill directory +if [ -d "$GSTACK_DIR/$SKILL_DIR" ]; then + FULL_DIR="$GSTACK_DIR/$SKILL_DIR" +elif [ -d "$SKILL_DIR" ]; then + FULL_DIR="$SKILL_DIR" +else + echo "ERROR: Skill directory not found: $SKILL_DIR" + exit 1 +fi + +SKILL_NAME=$(basename "$FULL_DIR") +TMPL="$FULL_DIR/SKILL.md.tmpl" + +[ -f "$TMPL" ] || { echo "ERROR: No SKILL.md.tmpl in $FULL_DIR"; exit 1; } + +# Validate if requested +if [ "$VALIDATE" = "--validate" ]; then + echo "Validating $SKILL_NAME..." + "$SCRIPT_DIR/gstack-skill-validate" "$TMPL" || exit 1 + echo "" +fi + +# Extract metadata +VERSION=$(grep "^version:" "$TMPL" 2>/dev/null | head -1 | awk '{print $2}' || echo "0.0.0") +DESC=$(grep -A3 "^description:" "$TMPL" 2>/dev/null | tail -2 | sed 's/^ *//' | tr '\n' ' ' | head -c 200 || echo "") + +# Create manifest +MANIFEST=$(mktemp) +cat > "$MANIFEST" << MEOF +{ + "name": "$SKILL_NAME", + "version": "$VERSION", + "description": "$(echo "$DESC" | sed 's/"/\\"/g')", + "author": "$(git config user.name 2>/dev/null || echo "unknown")", + "gstack_version": "$(cat "$GSTACK_DIR/VERSION" 2>/dev/null || echo "unknown")", + "created": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", + "files": [$(find "$FULL_DIR" -type f -not -name "SKILL.md" -not -path "*/.git/*" | while read f; do echo "\"$(basename "$f")\""; done | tr '\n' ',' | sed 's/,$//')] +} +MEOF + +# Package +ARCHIVE="${SKILL_NAME}.gstack-skill.tar.gz" +TMPDIR_PKG=$(mktemp -d) +mkdir -p "$TMPDIR_PKG/$SKILL_NAME" +cp "$TMPL" "$TMPDIR_PKG/$SKILL_NAME/" + +# Copy supporting files (templates, checklists, etc.) +for f in "$FULL_DIR"/*.md "$FULL_DIR"/templates/* "$FULL_DIR"/references/*; do + [ -f "$f" ] && [ "$(basename "$f")" != "SKILL.md" ] && cp "$f" "$TMPDIR_PKG/$SKILL_NAME/" 2>/dev/null || true +done + +cp "$MANIFEST" "$TMPDIR_PKG/$SKILL_NAME/manifest.json" +tar -czf "$ARCHIVE" -C "$TMPDIR_PKG" "$SKILL_NAME" +rm -rf "$TMPDIR_PKG" "$MANIFEST" + +SIZE=$(wc -c < "$ARCHIVE" | tr -d ' ') +echo "Packaged: $ARCHIVE ($((SIZE / 1024))KB)" +echo "" +echo "Share this file. Recipients install with:" +echo " tar xzf $ARCHIVE -C ~/.claude/skills/gstack/" +echo " bun run gen:skill-docs"