#!/usr/bin/env bash # install.sh — Install the Greyhaven Design System into a consuming project. # # Copies (does NOT symlink) files so the consuming project owns its copies. # Re-run this script to pull updated versions after design system changes. # # What it does (by default): # 1. Copies SKILL.md into .claude/skills/ (for Claude Code) # 2. Copies AGENTS.md into the project root (standard convention) # 3. Copies Aspekta font files + font-face.css into public/fonts/ # 4. Prints CSS import + MCP setup instructions # # With --brand-skill: # 5. Copies BRAND.md into .claude/skills/ (voice, tone, messaging rules) # 6. Copies Greyhaven logo SVGs into public/logos/ # # Usage: # ./skill/install.sh /path/to/your/project # ./skill/install.sh /path/to/your/project --brand-skill set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" SKILL_FILE="${SCRIPT_DIR}/SKILL.md" AGENTS_FILE="${SCRIPT_DIR}/AGENTS.md" AGENTS_BRAND_FILE="${SCRIPT_DIR}/AGENTS.brand.md" BRAND_FILE="${SCRIPT_DIR}/BRAND.md" FONTS_DIR="${REPO_ROOT}/public/fonts" PUBLIC_DIR="${REPO_ROOT}/public" # Parse arguments TARGET_PROJECT="" INSTALL_BRAND=false while [ $# -gt 0 ]; do case "$1" in --brand-skill) INSTALL_BRAND=true shift ;; -h|--help) echo "Usage: $0 [--brand-skill]" echo "" echo "Options:" echo " --brand-skill Also install BRAND.md (voice/tone/messaging) and logo SVGs" echo "" echo "Examples:" echo " $0 /path/to/my-app" echo " $0 /path/to/my-app --brand-skill" echo " $0 . --brand-skill" exit 0 ;; *) if [ -z "$TARGET_PROJECT" ]; then TARGET_PROJECT="$1" else echo "Error: Unexpected argument: $1" echo "Run '$0 --help' for usage." exit 1 fi shift ;; esac done if [ -z "$TARGET_PROJECT" ]; then echo "Usage: $0 [--brand-skill]" echo "Run '$0 --help' for details." exit 1 fi if [ ! -d "$TARGET_PROJECT" ]; then echo "Error: Directory not found: ${TARGET_PROJECT}" exit 1 fi TARGET_PROJECT="$(cd "$TARGET_PROJECT" && pwd)" # Helper: backup existing file/symlink and copy new one copy_with_backup() { local src="$1" local dst="$2" if [ -L "$dst" ]; then rm "$dst" elif [ -f "$dst" ]; then mv "$dst" "${dst}.bak" echo " (backed up existing file to $(basename "${dst}.bak"))" fi cp "$src" "$dst" } echo "Installing Greyhaven Design System into ${TARGET_PROJECT}" if [ "$INSTALL_BRAND" = true ]; then echo " (with --brand-skill: BRAND.md + logos)" fi echo "" # ── 1. SKILL.md ──────────────────────────────────────────────────────────── if [ -f "$SKILL_FILE" ]; then SKILLS_DIR="${TARGET_PROJECT}/.claude/skills" mkdir -p "$SKILLS_DIR" DST="${SKILLS_DIR}/greyhaven-design-system.md" copy_with_backup "$SKILL_FILE" "$DST" echo "[ok] SKILL.md: ${DST}" else echo "[skip] SKILL.md not found — run 'pnpm skill:build' first" fi # ── 2. AGENTS.md ─────────────────────────────────────────────────────────── # Pick the brand-augmented variant if --brand-skill is passed, so agents # working in the consuming project know how to use the brand skill + MCP tools. if [ "$INSTALL_BRAND" = true ] && [ -f "$AGENTS_BRAND_FILE" ]; then AGENTS_SRC="$AGENTS_BRAND_FILE" AGENTS_LABEL="AGENTS.md (with brand voice addendum)" else AGENTS_SRC="$AGENTS_FILE" AGENTS_LABEL="AGENTS.md" fi if [ -f "$AGENTS_SRC" ]; then DST="${TARGET_PROJECT}/AGENTS.md" copy_with_backup "$AGENTS_SRC" "$DST" echo "[ok] ${AGENTS_LABEL}: ${DST}" else echo "[skip] AGENTS source not found — run 'pnpm skill:build' first" fi # ── 3. Fonts ─────────────────────────────────────────────────────────────── if [ -d "$FONTS_DIR" ]; then TARGET_FONTS="${TARGET_PROJECT}/public/fonts" mkdir -p "$TARGET_FONTS" copied=0 for f in "$FONTS_DIR"/Aspekta-*.woff2; do [ -f "$f" ] || continue cp "$f" "$TARGET_FONTS/" copied=$((copied + 1)) done if [ -f "$FONTS_DIR/font-face.css" ]; then cp "$FONTS_DIR/font-face.css" "$TARGET_FONTS/" fi echo "[ok] Fonts: ${copied} Aspekta woff2 files copied to ${TARGET_FONTS}/" else echo "[skip] Fonts dir not found at ${FONTS_DIR}" fi # ── 4. Brand skill (opt-in via --brand-skill) ────────────────────────────── if [ "$INSTALL_BRAND" = true ]; then # 4a. BRAND.md into .claude/skills/ if [ -f "$BRAND_FILE" ]; then SKILLS_DIR="${TARGET_PROJECT}/.claude/skills" mkdir -p "$SKILLS_DIR" DST="${SKILLS_DIR}/greyhaven-brand.md" copy_with_backup "$BRAND_FILE" "$DST" echo "[ok] BRAND.md: ${DST}" else echo "[skip] BRAND.md not found at ${BRAND_FILE}" fi # 4b. Logo SVGs into public/logos/ TARGET_LOGOS="${TARGET_PROJECT}/public/logos" mkdir -p "$TARGET_LOGOS" logo_files=( "gh - logo - positive - full black.svg" "gh - logo - white.svg" "gh - logo - offblack.svg" "gh - symbol - full black.svg" "gh - symbol - full white.svg" "greyproxy - positive.svg" "greywall - positive.svg" ) # Rename files on copy to remove spaces — better for web paths copied=0 for f in "${logo_files[@]}"; do src="${PUBLIC_DIR}/${f}" if [ -f "$src" ]; then # "gh - logo - positive - full black.svg" → "gh-logo-positive-full-black.svg" clean_name=$(echo "$f" | sed 's/ - /-/g; s/ /-/g') cp "$src" "${TARGET_LOGOS}/${clean_name}" copied=$((copied + 1)) fi done echo "[ok] Logos: ${copied} SVGs copied to ${TARGET_LOGOS}/ (renamed: spaces → dashes)" fi # ── Next steps ───────────────────────────────────────────────────────────── cat <<'EOF' Done! ─── Next steps ──────────────────────────────────────────────────────────── 1. Add Aspekta @font-face to your global CSS: @font-face { font-family: 'Aspekta'; font-weight: 400; font-display: swap; src: url('/fonts/Aspekta-400.woff2') format('woff2'); } @font-face { font-family: 'Aspekta'; font-weight: 500; font-display: swap; src: url('/fonts/Aspekta-500.woff2') format('woff2'); } @font-face { font-family: 'Aspekta'; font-weight: 600; font-display: swap; src: url('/fonts/Aspekta-600.woff2') format('woff2'); } @font-face { font-family: 'Aspekta'; font-weight: 700; font-display: swap; src: url('/fonts/Aspekta-700.woff2') format('woff2'); } (Or import the full set: @import url('/fonts/font-face.css');) And set the font stack: --font-sans: 'Aspekta', ui-sans-serif, system-ui, sans-serif; 2. (Optional) Register the Greyhaven MCP server. Create .mcp.json in your project root: { "mcpServers": { "greyhaven": { "command": "npx", "args": ["tsx", "/mcp/server.ts"] } } } 3. Re-run this script after design system updates to refresh your copies. EOF