#!/usr/bin/env bash set -euo pipefail SKILL_NAME="${1:-}" VERSION="${2:-latest}" REPO_URL="${OMNICLAW_SKILLS_REPO:-https://git.omniclaw.store/zsb/omniclaw-skills.git}" RAW_BASE_URL="${OMNICLAW_SKILLS_RAW_BASE_URL:-https://git.omniclaw.store/zsb/omniclaw-skills/raw/branch/main}" DEST_DIR="${CODEX_HOME:-$HOME/.codex}/skills" if [[ -z "$SKILL_NAME" ]]; then echo "Usage: install.sh [version]" >&2 exit 2 fi require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "Missing required command: $1" >&2 exit 2 fi } require_cmd mktemp require_cmd node require_cmd tar require_cmd shasum tmp_dir="$(mktemp -d)" cleanup() { rm -rf "$tmp_dir" } trap cleanup EXIT manifest="$tmp_dir/manifest.json" if [[ -d "$RAW_BASE_URL" && -f "$RAW_BASE_URL/registry/manifest.json" ]]; then cp "$RAW_BASE_URL/registry/manifest.json" "$manifest" elif command -v curl >/dev/null 2>&1; then curl -fsSL "$RAW_BASE_URL/registry/manifest.json" -o "$manifest" || true elif command -v wget >/dev/null 2>&1; then wget -qO "$manifest" "$RAW_BASE_URL/registry/manifest.json" || true else : > "$manifest" fi if [[ ! -s "$manifest" ]]; then require_cmd git git clone --depth 1 "$REPO_URL" "$tmp_dir/repo" if [[ ! -f "$tmp_dir/repo/registry/manifest.json" ]]; then echo "Unable to find registry/manifest.json from $REPO_URL" >&2 exit 1 fi cp "$tmp_dir/repo/registry/manifest.json" "$manifest" RAW_BASE_URL="$tmp_dir/repo" fi node_script=' const fs = require("fs"); const manifest = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); const name = process.argv[2]; const version = process.argv[3]; const skill = manifest.skills.find((item) => item.name === name && (version === "latest" || item.version === version)); if (!skill) { console.error(`Skill not found: ${name}@${version}`); process.exit(1); } console.log(JSON.stringify(skill)); ' skill_json="$(node -e "$node_script" "$manifest" "$SKILL_NAME" "$VERSION")" package_path="$(printf '%s' "$skill_json" | node -e 'let s="";process.stdin.on("data",c=>s+=c);process.stdin.on("end",()=>console.log(JSON.parse(s).package));')" expected_sha="$(printf '%s' "$skill_json" | node -e 'let s="";process.stdin.on("data",c=>s+=c);process.stdin.on("end",()=>console.log(JSON.parse(s).sha256));')" archive="$tmp_dir/skill.tar.gz" if [[ -d "$RAW_BASE_URL" ]]; then cp "$RAW_BASE_URL/$package_path" "$archive" elif command -v curl >/dev/null 2>&1; then curl -fsSL "$RAW_BASE_URL/$package_path" -o "$archive" else wget -qO "$archive" "$RAW_BASE_URL/$package_path" fi actual_sha="$(shasum -a 256 "$archive" | awk '{print $1}')" if [[ "$actual_sha" != "$expected_sha" ]]; then echo "Checksum mismatch for $package_path" >&2 echo "expected: $expected_sha" >&2 echo "actual: $actual_sha" >&2 exit 1 fi mkdir -p "$DEST_DIR" target="$DEST_DIR/$SKILL_NAME" if [[ -e "$target" ]]; then backup="$target.backup.$(date +%Y%m%d%H%M%S)" mv "$target" "$backup" echo "Existing skill moved to $backup" fi tar -xzf "$archive" -C "$DEST_DIR" echo "Installed $SKILL_NAME to $DEST_DIR/$SKILL_NAME" echo "Restart Codex to pick up new skills."