blob: 2ee4aa7509958f53eb3be5aa0d0b5c975cdaad7c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#!/usr/bin/env bash
# Install a language ruleset into a target project.
# Usage: install-lang.sh <language> <project-path> [force]
#
# Copies the language's ruleset files into the project. Re-runnable
# (authoritative source overwrites). CLAUDE.md is preserved unless
# force=1, to avoid trampling project-specific customizations.
set -euo pipefail
LANG="${1:-}"
PROJECT="${2:-}"
FORCE="${3:-}"
if [ -z "$LANG" ] || [ -z "$PROJECT" ]; then
echo "Usage: $0 <language> <project-path> [force]" >&2
exit 1
fi
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SRC="$REPO_ROOT/languages/$LANG"
if [ ! -d "$SRC" ]; then
echo "ERROR: no ruleset for language '$LANG' (expected $SRC)" >&2
exit 1
fi
if [ ! -d "$PROJECT" ]; then
echo "ERROR: project path does not exist: $PROJECT" >&2
exit 1
fi
# Resolve to absolute path
PROJECT="$(cd "$PROJECT" && pwd)"
echo "Installing '$LANG' ruleset into $PROJECT"
# 1. Generic rules from claude-rules/ (shared across all languages)
if [ -d "$REPO_ROOT/claude-rules" ]; then
mkdir -p "$PROJECT/.claude/rules"
cp "$REPO_ROOT/claude-rules"/*.md "$PROJECT/.claude/rules/" 2>/dev/null || true
count=$(ls -1 "$REPO_ROOT/claude-rules"/*.md 2>/dev/null | wc -l)
echo " [ok] .claude/rules/ — $count generic rule(s) from claude-rules/"
fi
# 2. .claude/ — language-specific rules, hooks, settings (authoritative, always overwrite)
if [ -d "$SRC/claude" ]; then
mkdir -p "$PROJECT/.claude"
cp -rT "$SRC/claude" "$PROJECT/.claude"
if [ -d "$PROJECT/.claude/hooks" ]; then
find "$PROJECT/.claude/hooks" -type f -name '*.sh' -exec chmod +x {} \;
fi
echo " [ok] .claude/ — language-specific content"
fi
# 2. githooks/ — pre-commit etc.
if [ -d "$SRC/githooks" ]; then
mkdir -p "$PROJECT/githooks"
cp -rT "$SRC/githooks" "$PROJECT/githooks"
find "$PROJECT/githooks" -type f -exec chmod +x {} \;
if [ -d "$PROJECT/.git" ]; then
git -C "$PROJECT" config core.hooksPath githooks
echo " [ok] githooks/ installed, core.hooksPath=githooks"
else
echo " [ok] githooks/ installed (not a git repo — skipped core.hooksPath)"
fi
fi
# 3. CLAUDE.md — seed on first install, don't overwrite unless FORCE=1
if [ -f "$SRC/CLAUDE.md" ]; then
if [ -f "$PROJECT/CLAUDE.md" ] && [ "$FORCE" != "1" ]; then
echo " [skip] CLAUDE.md already exists (use FORCE=1 to overwrite)"
else
cp "$SRC/CLAUDE.md" "$PROJECT/CLAUDE.md"
echo " [ok] CLAUDE.md installed"
fi
fi
# 4. .gitignore — append missing lines (deduped, skip comments)
if [ -f "$SRC/gitignore-add.txt" ]; then
touch "$PROJECT/.gitignore"
added=0
while IFS= read -r line || [ -n "$line" ]; do
# Skip blank lines and comments in the source file
[ -z "$line" ] && continue
case "$line" in \#*) continue ;; esac
# Only add if not already present
if ! grep -qxF "$line" "$PROJECT/.gitignore"; then
# If this is the first line we're adding, prepend a header
if [ "$added" -eq 0 ]; then
printf '\n# --- %s ruleset ---\n' "$LANG" >> "$PROJECT/.gitignore"
fi
echo "$line" >> "$PROJECT/.gitignore"
added=$((added + 1))
fi
done < "$SRC/gitignore-add.txt"
if [ "$added" -gt 0 ]; then
echo " [ok] .gitignore: $added line(s) added"
else
echo " [skip] .gitignore entries already present"
fi
fi
echo ""
echo "Install complete."
|