#!/usr/bin/env bash # claude-harness: каркас нового проекта под обвязку. # Запуск: bash new-project.sh <папка> [ssh-url репозитория в Gitea] set -euo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" # Режим workspace: bash new-project.sh --workspace <папка> [--role admin] [--role qa] [--role analyst] if [ "${1:-}" = "--workspace" ]; then DIR="${2:?usage: new-project.sh --workspace [--role ...]}"; shift 2 ROLES=() while [ $# -gt 0 ]; do case "$1" in --role) ROLES+=("$2"); shift 2 ;; *) echo "ERR: неизвестный аргумент $1"; exit 1 ;; esac; done mkdir -p "$DIR" && cd "$DIR"; NAME="$(basename "$(pwd)")" [ -f CLAUDE.md ] || sed "s/{{PROJECT_NAME}}/$NAME/g" "$HERE/project-template/workspace/CLAUDE.md" > CLAUDE.md mkdir -p .claude/roles [ -e .claude/roles/dev.md ] || sed "s/{{PROJECT_NAME}}/$NAME/g" "$HERE/project-template/workspace/roles/dev.md" > .claude/roles/dev.md for r in "${ROLES[@]+"${ROLES[@]}"}"; do case "$r" in admin|analyst|qa) ;; *) echo "ERR: роль $r не из admin|analyst|qa"; exit 1 ;; esac d="$r"; [ "$r" = analyst ] && d="analysis" if [ -d "$d/.git" ]; then echo "$d/: уже git, не трогаю"; continue; fi mkdir -p "$d/.claude/roles" "$d/notes" sed -e "s/{{PROJECT_NAME}}/$NAME/g" -e "s/{{ROLE}}/$r/g" -e "s#{{DIR}}#$d#g" "$HERE/project-template/role-repo/CLAUDE.md" > "$d/CLAUDE.md" sed -e "s/{{PROJECT_NAME}}/$NAME/g" -e "s/{{ROLE}}/$r/g" -e "s#{{DIR}}#$d#g" "$HERE/project-template/role-repo/ROLE.md" > "$d/.claude/roles/$r.md" cp "$HERE/project-template/role-repo/notes/README.md" "$d/notes/README.md" echo "$r" > "$d/.claude/role" git -C "$d" init -q -b main && git -C "$d" add -A && git -C "$d" commit -qm "chore: репозиторий направления $r (claude-harness)" # строка таблицы: заменить заготовку {{owner/repo-}} на имя каталога, если заготовка есть sed -i.bak "s#| $d/ | {{owner/repo-[a-z]*}} | $r |#| $d/ | /$NAME-$d | $r |#" CLAUDE.md && rm -f CLAUDE.md.bak echo "$d/: репозиторий направления $r создан" done bash "$HERE/link-roles.sh" "$(pwd)" cat <.md. 2. Заведи репозитории направлений в Gitea и добавь remote (tea repos create …; git remote add origin …). 3. Если обвязка ставилась с --no-permissions: разреши агенту удалять ветки на сервере (чеклист закрытия, п. 4) — строка в .claude/settings.json → permissions.allow: "Bash(git push origin --delete:*)" 4. cd $(pwd) && claude -n "dev …" MSG exit 0 fi DIR="${1:?usage: new-project.sh [git-remote-url]}" REMOTE="${2:-}" NAME="$(basename "$DIR")" mkdir -p "$DIR" && cd "$DIR" [ -d .git ] || git init -b main sed "s/{{PROJECT_NAME}}/$NAME/" "$HERE/project-template/CLAUDE.md" > CLAUDE.md cp "$HERE/project-template/ARCHITECTURE.md" ARCHITECTURE.md cp "$HERE/project-template/gitignore" .gitignore mkdir -p tests/fixtures docs/superpowers/plans if command -v openspec >/dev/null 2>&1; then [ -d openspec ] || openspec init --tools claude 2>/dev/null || openspec init else echo "WARN: openspec не установлен (npm i -g @fission-ai/openspec)" fi if command -v codegraph >/dev/null 2>&1; then [ -d .codegraph ] || codegraph init >/dev/null 2>&1 || echo "WARN: codegraph init не удался" fi git add -A git commit -qm "chore: bootstrap project skeleton (claude-harness)" || true if [ -n "$REMOTE" ]; then git remote get-url origin >/dev/null 2>&1 || git remote add origin "$REMOTE" git push -u origin main fi cat <