Files
Claude d15bc368fe Phase 7: Polish — README, LICENSE, SECURITY, CONTRIBUTING, CHANGELOG, install.sh, manifest
- README: full rewrite with TOC, badges, category navigation, quickstart,
  install snippets, roadmap section, popularity acknowledgement
- LICENSE: MIT (was claimed in README, file now present)
- SECURITY.md: rewritten with intended-use scope, disclosure policy,
  supply chain integrity guidance
- CONTRIBUTING.md: skill format spec, frontmatter standard, review process,
  splitting guidance for monolithic skills
- CHANGELOG.md: phased roadmap tracking
- install.sh: installer with --target, --category, --list, --dry-run modes
- tools/build_manifest.py: regenerates claude-skills.json from Skills/ tree
- claude-skills.json: machine-readable manifest of 45 skills, 13 categories
2026-05-06 07:56:52 +00:00

109 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# claude-red installer
# Copies offensive security skills into a Claude skills directory.
#
# Usage:
# ./install.sh # interactive (asks for target)
# ./install.sh --target ~/.claude/skills # explicit target
# ./install.sh --category web # one category only
# ./install.sh --target DIR --category web # combined
# ./install.sh --list # list available categories
# ./install.sh --dry-run # show what would be copied
#
# Default target: ~/.claude/skills/claude-red
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILLS_DIR="$SCRIPT_DIR/Skills"
DEFAULT_TARGET="${HOME}/.claude/skills/claude-red"
TARGET=""
CATEGORY=""
DRY_RUN=0
LIST_ONLY=0
usage() {
sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'
exit "${1:-0}"
}
list_categories() {
echo "Available categories:"
for d in "$SKILLS_DIR"/*/; do
[ -d "$d" ] || continue
name=$(basename "$d")
count=$(find "$d" -name SKILL.md | wc -l | tr -d ' ')
printf " %-20s %s skill(s)\n" "$name" "$count"
done
}
while [ $# -gt 0 ]; do
case "$1" in
--target) TARGET="$2"; shift 2 ;;
--category) CATEGORY="$2"; shift 2 ;;
--dry-run) DRY_RUN=1; shift ;;
--list) LIST_ONLY=1; shift ;;
-h|--help) usage 0 ;;
*) echo "Unknown option: $1" >&2; usage 1 ;;
esac
done
if [ "$LIST_ONLY" -eq 1 ]; then
list_categories
exit 0
fi
if [ ! -d "$SKILLS_DIR" ]; then
echo "Error: Skills directory not found at $SKILLS_DIR" >&2
exit 1
fi
# Interactive prompt if no target given
if [ -z "$TARGET" ]; then
if [ -t 0 ]; then
read -r -p "Install target [$DEFAULT_TARGET]: " TARGET || true
fi
TARGET="${TARGET:-$DEFAULT_TARGET}"
fi
# Validate category if specified
if [ -n "$CATEGORY" ]; then
if [ ! -d "$SKILLS_DIR/$CATEGORY" ]; then
echo "Error: Category '$CATEGORY' not found." >&2
echo "" >&2
list_categories >&2
exit 1
fi
SOURCE="$SKILLS_DIR/$CATEGORY"
DEST="$TARGET/$CATEGORY"
else
SOURCE="$SKILLS_DIR"
DEST="$TARGET"
fi
echo "Source: $SOURCE"
echo "Target: $DEST"
echo
if [ "$DRY_RUN" -eq 1 ]; then
echo "[dry-run] Would copy:"
find "$SOURCE" -name SKILL.md | sed "s|^$SOURCE| $DEST|"
exit 0
fi
mkdir -p "$DEST"
# Use rsync if available for nicer output, else cp -r
if command -v rsync >/dev/null 2>&1; then
rsync -a --info=stats1 "$SOURCE/" "$DEST/"
else
cp -r "$SOURCE/." "$DEST/"
echo "Copied via cp (install rsync for progress info)."
fi
skill_count=$(find "$DEST" -name SKILL.md | wc -l | tr -d ' ')
echo
echo "Installed $skill_count skill(s) to $DEST"
echo "Claude should now auto-discover them on next session start."