claude-harness/install.sh
Andrey Epifancev d2b4ff2018 feat: skill aura-design — дизайн-система AURA для личных проектов (#17)
Скилл переносится из ~/.claude/skills/aura-design в репозиторий обвязки:
SKILL.md, справочники reference/ и набор kit/ (токены, base.css, компоненты
React, оболочка AppShell, тест токенов, test-setup, примеры входа).
install.sh ставит его в ~/.claude/skills/aura-design, --check его видит.
tests/test-aura-design.sh проверяет структуру и инварианты набора.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 12:10:34 +04:00

103 lines
5.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# claude-harness: установка глобальной части (CLAUDE.md, хуки, конфиг caveman, слияние settings.json).
# Идемпотентно. Запуск: bash install.sh | проверка окружения: bash install.sh --check
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
CC="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
check() {
local ok=0
echo "== Проверка окружения"
for bin in claude git python3 node npm tea openspec codegraph; do
if command -v "$bin" >/dev/null 2>&1; then echo " ok $bin ($(command -v "$bin"))"; else echo " MISS $bin"; ok=1; fi
done
if [ -f "$CC/plugins/installed_plugins.json" ]; then
for p in superpowers caveman; do
if grep -q "\"$p@" "$CC/plugins/installed_plugins.json"; then echo " ok plugin $p"; else echo " MISS plugin $p (/plugin install ...)"; fi
done
for p in beads template-bridge; do
grep -q "\"$p@" "$CC/plugins/installed_plugins.json" && echo " WARN plugin $p установлен — конфликтует с обвязкой, удалить" || true
done
else
echo " WARN не найден $CC/plugins/installed_plugins.json"
fi
if [ -f "$CC/settings.json" ] && grep -q 'codegraph prompt-hook' "$CC/settings.json"; then
echo " WARN codegraph prompt-hook в settings.json — рекомендуется отключить на время пилота"
fi
echo "== Установленная часть обвязки ($CC)"
for f in CLAUDE.md hooks/guard-main.sh hooks/require-plan.sh hooks/harness_target.py hooks/harness-check.sh hooks/role-hint.sh \
roles/dev.md roles/admin.md roles/analyst.md roles/qa.md skills/role/SKILL.md agents/briefing.md \
harness/adopt-project.sh harness/new-project.sh harness/link-roles.sh skills/harness-doctor/SKILL.md \
skills/aura-design/SKILL.md; do
[ -f "$CC/$f" ] && echo " ok $f" || { echo " MISS $f (bash install.sh)"; ok=1; }
done
return $ok
}
if [ "${1:-}" = "--check" ]; then check; exit $?; fi
mkdir -p "$CC/hooks" "$HOME/.config/caveman"
stamp=$(date +%Y%m%d-%H%M%S)
# 1. Глобальный CLAUDE.md
if [ -f "$CC/CLAUDE.md" ] && ! cmp -s "$HERE/global/CLAUDE.md" "$CC/CLAUDE.md"; then
cp "$CC/CLAUDE.md" "$CC/CLAUDE.md.bak.$stamp"; echo "backup: CLAUDE.md.bak.$stamp"
fi
cp "$HERE/global/CLAUDE.md" "$CC/CLAUDE.md"
# 2. Хуки
cp "$HERE/hooks/guard-main.sh" "$HERE/hooks/require-plan.sh" "$HERE/hooks/harness-check.sh" "$HERE/hooks/role-hint.sh" \
"$HERE/hooks/harness_target.py" "$CC/hooks/"
# 2a. Скрипты бутстрапа проекта — агент запускает их из сессии
mkdir -p "$CC/harness"
rm -rf "$CC/harness/project-template"
cp -R "$HERE/adopt-project.sh" "$HERE/new-project.sh" "$HERE/link-roles.sh" "$HERE/project-template" "$CC/harness/"
chmod +x "$CC/harness/"*.sh
# 2b. Skill диагностики
mkdir -p "$CC/skills"
rm -rf "$CC/skills/harness-doctor" && cp -R "$HERE/skills/harness-doctor" "$CC/skills/harness-doctor"
chmod +x "$CC/skills/harness-doctor/scripts/"*.sh
# 2b'. Skill aura-design: дизайн-система личных проектов (справочники + набор kit)
rm -rf "$CC/skills/aura-design" && cp -R "$HERE/skills/aura-design" "$CC/skills/aura-design"
# 2c. Роли, skill /role, агент briefing
mkdir -p "$CC/roles" "$CC/skills/role" "$CC/agents"
cp "$HERE/roles/"*.md "$CC/roles/"
cp "$HERE/skills/role/SKILL.md" "$CC/skills/role/SKILL.md"
cp "$HERE/agents/briefing.md" "$CC/agents/briefing.md"
chmod +x "$CC/hooks/"*.sh
# 3. caveman off by default
cp "$HERE/caveman/config.json" "$HOME/.config/caveman/config.json"
# 4. settings.json: слить блок hooks, вычистить хвосты beads/template-bridge
SETTINGS="$CC/settings.json"
[ -f "$SETTINGS" ] || echo '{}' > "$SETTINGS"
cp "$SETTINGS" "$SETTINGS.bak.$stamp"
python3 - "$SETTINGS" "$HERE/hooks/settings.hooks.json" <<'PY'
import json, sys
sp, hp = sys.argv[1], sys.argv[2]
s = json.load(open(sp)); h = json.load(open(hp))
hooks = s.setdefault("hooks", {})
pre = hooks.setdefault("PreToolUse", [])
def ours(entry):
return any(("guard-main.sh" in x.get("command","") or "require-plan.sh" in x.get("command","")) for x in entry.get("hooks",[]))
pre[:] = [e for e in pre if not ours(e)]
pre.extend(h["hooks"]["PreToolUse"])
ss = hooks.setdefault("SessionStart", [])
ours_ss = ("harness-check.sh", "role-hint.sh")
ss[:] = [e for e in ss if not any(any(n in x.get("command","") for n in ours_ss) for x in e.get("hooks",[]))]
ss.extend(h["hooks"]["SessionStart"])
for ev in ("SessionStart","PreCompact"):
if ev in hooks:
for e in hooks[ev]:
e["hooks"] = [x for x in e.get("hooks",[]) if "bd prime" not in x.get("command","") and "WORKFLOW REMINDER" not in x.get("command","")]
hooks[ev] = [e for e in hooks[ev] if e.get("hooks")]
if not hooks[ev]: del hooks[ev]
json.dump(s, open(sp,"w"), ensure_ascii=False, indent=2)
print("settings.json: hooks merged")
PY
echo "done: $CC/CLAUDE.md, $CC/skills/harness-doctor, $CC/skills/aura-design, $CC/hooks/{guard-main,require-plan,harness-check,role-hint}.sh + harness_target.py, $CC/roles/, $CC/skills/role, $CC/agents/briefing.md, $CC/harness/, ~/.config/caveman/config.json"
echo "Плагины Claude Code ставятся вручную: /plugin install superpowers@claude-plugins-official"
check || true