claude-meta/scripts/install.sh

166 lines
4.3 KiB
Bash

#!/bin/bash
# install.sh — Link claude-meta config into ~/.claude/
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
SOURCE_DIR="$REPO_ROOT/home-claude"
CLAUDE_DIR="$HOME/.claude"
# Verify source exists
if [ ! -d "$SOURCE_DIR" ]; then
echo "ERROR: home-claude/ not found at $SOURCE_DIR"
exit 1
fi
# Ensure ~/.claude/ is a real directory
if [ -L "$CLAUDE_DIR" ]; then
echo "ERROR: ~/.claude/ is a symlink. It must be a real directory."
echo "Claude Code Bug #764: symlinked ~/.claude/ breaks file detection."
exit 1
fi
mkdir -p "$CLAUDE_DIR"
echo "Installing claude-meta config..."
echo " Source: $SOURCE_DIR"
echo " Target: $CLAUDE_DIR"
echo ""
# File symlinks
for file in CLAUDE.md settings.json; do
src="$SOURCE_DIR/$file"
dst="$CLAUDE_DIR/$file"
[ ! -f "$src" ] && echo " SKIP: $file" && continue
# Remove existing
[ -e "$dst" ] || [ -L "$dst" ] && rm -f "$dst"
ln -s "$src" "$dst"
echo " SYMLINK: $file -> $src"
done
# Directory symlinks
for dir in skills rules commands; do
src="$SOURCE_DIR/$dir"
dst="$CLAUDE_DIR/$dir"
[ ! -d "$src" ] && echo " SKIP: $dir/" && continue
# Remove existing
if [ -L "$dst" ]; then
rm "$dst"
elif [ -d "$dst" ]; then
rm -rf "$dst"
fi
ln -s "$src" "$dst"
echo " SYMLINK: $dir/ -> $src"
done
# Validation
echo ""
echo "Validating..."
for file in CLAUDE.md settings.json; do
dst="$CLAUDE_DIR/$file"
if [ -f "$dst" ] && [ -s "$dst" ]; then
echo " OK: $file readable"
else
echo " FAIL: $file"
fi
done
for dir in skills rules commands; do
dst="$CLAUDE_DIR/$dir"
if [ -d "$dst" ]; then
count=$(find "$dst" -type f | wc -l)
echo " OK: $dir/ ($count files)"
else
echo " FAIL: $dir/"
fi
done
echo ""
echo "Installing Gemini config..."
GEMINI_SOURCE_DIR="$REPO_ROOT/home-gemini"
GEMINI_DIR="$HOME/.gemini"
CLAUDE_RULES_DIR="$SOURCE_DIR/rules"
if [ ! -d "$GEMINI_SOURCE_DIR" ]; then
echo " SKIP: home-gemini/ not found"
else
echo " Source: $GEMINI_SOURCE_DIR"
echo " Target: $GEMINI_DIR"
echo ""
# Ensure ~/.gemini/ is a real directory
if [ -L "$GEMINI_DIR" ]; then
echo " ERROR: ~/.gemini/ is a symlink. Must be a real directory."
exit 1
fi
mkdir -p "$GEMINI_DIR"
# GEMINI.md — always copy (no symlink, Gemini CLI issue #11547)
src="$GEMINI_SOURCE_DIR/GEMINI.md"
dst="$GEMINI_DIR/GEMINI.md"
if [ -f "$src" ]; then
cp -f "$src" "$dst"
echo " COPY: GEMINI.md (symlinks not supported by Gemini CLI)"
fi
# settings.json — symlink
src="$GEMINI_SOURCE_DIR/settings.json"
dst="$GEMINI_DIR/settings.json"
if [ -f "$src" ]; then
[ -e "$dst" ] || [ -L "$dst" ] && rm -f "$dst"
ln -s "$src" "$dst"
echo " SYMLINK: settings.json -> $src"
fi
# rules/ — symlink to home-claude/rules/ (shared source of truth)
dst="$GEMINI_DIR/rules"
if [ -d "$CLAUDE_RULES_DIR" ]; then
[ -L "$dst" ] && rm "$dst" || { [ -d "$dst" ] && rm -rf "$dst"; }
ln -s "$CLAUDE_RULES_DIR" "$dst"
echo " SYMLINK: rules/ -> $CLAUDE_RULES_DIR"
fi
# skills/ — selective symlinks for review/ and plan-project/
mkdir -p "$GEMINI_DIR/skills"
for skill in review plan-project; do
skill_src="$SOURCE_DIR/skills/$skill"
skill_dst="$GEMINI_DIR/skills/$skill"
if [ ! -d "$skill_src" ]; then
echo " SKIP: skills/$skill/ (not in repo)"
continue
fi
[ -L "$skill_dst" ] && rm "$skill_dst" || { [ -d "$skill_dst" ] && rm -rf "$skill_dst"; }
ln -s "$skill_src" "$skill_dst"
echo " SYMLINK: skills/$skill/ -> $skill_src"
done
echo ""
echo "Validating Gemini..."
dst="$GEMINI_DIR/GEMINI.md"
if [ -f "$dst" ] && [ ! -L "$dst" ] && [ -s "$dst" ]; then
echo " OK: ~/.gemini/GEMINI.md (real file)"
elif [ -L "$dst" ]; then
echo " FAIL: ~/.gemini/GEMINI.md is a symlink (Gemini CLI rejects this!)"
else
echo " FAIL: ~/.gemini/GEMINI.md"
fi
dst="$GEMINI_DIR/rules"
if [ -d "$dst" ]; then
count=$(find "$dst" -type f | wc -l)
echo " OK: ~/.gemini/rules/ ($count files)"
else
echo " FAIL: ~/.gemini/rules/"
fi
fi
echo ""
echo "Installation complete!"