#!/usr/bin/env bash # # Package the cycling-training skill into a zip that installs as a Claude skill # (Claude Desktop / claude.ai "Skills", or Claude Code). # # The archive contains a single top-level `cycling-training/` directory holding # SKILL.md + supporting docs — the layout Claude expects when importing a skill. # # Usage: # scripts/build-skill-zip.sh [version] # Example: # scripts/build-skill-zip.sh v1.0.0 -> dist/cycling-training-v1.0.0.zip # scripts/build-skill-zip.sh -> dist/cycling-training-dev.zip # set -euo pipefail SKILL_NAME="cycling-training" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" VERSION="${1:-dev}" OUT_DIR="${ROOT}/dist" STAGE="${OUT_DIR}/${SKILL_NAME}" ZIP_NAME="${SKILL_NAME}-${VERSION}.zip" # The files that make up the installable skill (repo/CI cruft is excluded). INCLUDE=(SKILL.md README.md references assets) rm -rf "${OUT_DIR}" mkdir -p "${STAGE}" for item in "${INCLUDE[@]}"; do if [ ! -e "${ROOT}/${item}" ]; then echo "ERROR: expected '${item}' not found at repo root" >&2 exit 1 fi cp -R "${ROOT}/${item}" "${STAGE}/" done # Sanity checks: a skill is only valid with a SKILL.md that has name + description. test -f "${STAGE}/SKILL.md" || { echo "ERROR: SKILL.md missing from package" >&2; exit 1; } grep -q "^name:" "${STAGE}/SKILL.md" || { echo "ERROR: SKILL.md has no 'name:' frontmatter" >&2; exit 1; } grep -q "^description:" "${STAGE}/SKILL.md" || { echo "ERROR: SKILL.md has no 'description:' frontmatter" >&2; exit 1; } # Build the zip with the skill folder as the single top-level entry. ( cd "${OUT_DIR}" && zip -r -q "${ZIP_NAME}" "${SKILL_NAME}" -x '*.DS_Store' ) echo "Built ${OUT_DIR}/${ZIP_NAME}" echo "Contents:" ( cd "${OUT_DIR}" && unzip -l "${ZIP_NAME}" )