# Scaffold Project

> |

- **Type:** Skill
- **Install:** `agentstack add skill-ymuromcev-claude-scaffold-project-claude-scaffold-project`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ymuromcev](https://agentstack.voostack.com/s/ymuromcev)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ymuromcev](https://github.com/ymuromcev)
- **Source:** https://github.com/ymuromcev/claude-scaffold-project

## Install

```sh
agentstack add skill-ymuromcev-claude-scaffold-project-claude-scaffold-project
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# scaffold-project — bootstrap нового проекта

Когда пользователь говорит «новый проект» — этот скилл разворачивает
полный скелет за один диалог. После scaffold все задачи в проекте идут
через `dev-workflow`.

## Шаг 0 — определить режим

Скилл различает три режима по триггер-фразе пользователя:

| Триггер | Режим |
|---|---|
| «новый проект», «init project», «scaffold проект», «развернуть проект», и т.п. | **fresh / extension** (Шаги 1–5 ниже) |
| «причеши проект», «оформи как dev-проект», «back-fill бэклог», «добавь дев-обвязку», `/scaffold-project --backfill` | **back-fill** (секция «Back-fill mode» — пропускаем Шаги 1–5, идём туда) |

Если триггер двусмысленный (например, просто `/scaffold-project` в каталоге с `CLAUDE.md`) — спросить пользователя один раз: «у проекта уже есть `CLAUDE.md`. Это fresh-init где-то ещё, или back-fill сюда?».

## Шаг 1 — pre-checks (fresh / extension режим)

Перед стартом скилл проверяет целевой каталог:

| Состояние | Действие |
|---|---|
| Каталог не существует / пустой | Продолжаем (mkdir создаст). |
| Не пуст, нет `CLAUDE.md`/`package.json`/`pyproject.toml` | Продолжаем, но предупреждаем «каталог не пуст, продолжить?». |
| Есть `package.json` или `pyproject.toml` без `CLAUDE.md` | Предлагаем **extension mode**: добавить недостающие base-файлы, не трогая существующее. |
| Есть `CLAUDE.md` | Отказ + подсказка: «проект уже инициализирован. Если хочешь добавить недостающую дев-обвязку — скажи `back-fill` или `причеши проект` (см. секцию Back-fill mode)». |

## Шаг 2 — диалог

Скилл задаёт **пять** вопросов. Не больше, не меньше.

1. **Имя проекта** (kebab-case). Валидация: `^[a-z][a-z0-9-]{1,40}$`.
   Не проходит — спрашиваем заново.
2. **Однострочное описание** — 1 предложение, чем проект полезен.
   Если пользователь хочет дать развёрнутый scope — приветствуется,
   уйдёт в `{{SCOPE_DESCRIPTION}}` as-is.
3. **Стек**:
   - `node-cli` — Node 20+ CLI или библиотека, тесты через `node --test`.
   - `python-mcp` — Python MCP-сервер или скрипт, тесты через `pytest`.
   - `both` — оба extension'а.
   - `none` — только base, никакого языкового скелета.
4. **Внешние сервисы, которые предполагаются сразу** (Notion / Gmail /
   Stripe / Sentry / другое). Список справочный — попадёт в
   `.env.example` и в комментарий к BL-001. Если ничего — `none`.
5. **Работа с user data?** — `yes` / `no`. Это любые
   пользовательские данные: профили, контент пользователя, сообщения,
   email/telegram-чаты, транзакции. Если `yes` — обязательно подключаем
   extension `multi-user-base` (см. секцию «Identity & PII rules»).
   Это не «потом докрутим» — потом стоит недели работы.

## Шаг 3 — preview + approve

Перед записью — плоский список файлов, которые скилл создаст:

```
/
├── CLAUDE.md
├── README.md
├── DEVELOPMENT.md
├── CHANGELOG.md
├── incidents.md
├── .gitignore
├── .env.example
├── rfc/_README.md
├── docs/decisions/_README.md
├── private/backlog.base                  # Obsidian Bases view
├── private/backlog/_README.md            # конвенции: frontmatter, статусы, теги версий
├── private/backlog/BL-1.md               # первый таск (scaffold), in_progress
├── package.json                          (если node-cli)
├── engine/index.js                       (если node-cli)
├── engine/index.test.js                  (если node-cli)
├── pyproject.toml                        (если python-mcp)
├── server.py                             (если python-mcp)
└── tests/test_smoke.py                   (если python-mcp)
```

**Жду явного «ok» от пользователя.**

## Шаг 4 — запись

По approve:

0. **Pre-flight check.** До любых mkdir / write:
   - `git --version` отвечает (git установлен).
   - `git config --get user.name` и `git config --get user.email` оба
     возвращают значение.
   Если что-то из этого не выполнено — отказ с понятным сообщением
   («настрой `git config --global user.email …` и попробуй заново»).
   **Никаких файлов не создаём, пока pre-flight красный** — иначе
   получим скаффолд без коммита и тупик в следующем запуске («есть
   CLAUDE.md, отказ»).
1. `mkdir -p ` если не существует. Запомним флаг
   `created_root = (true | false)` — пригодится для отката.
2. Для каждого файла из `templates/base/` (и выбранных
   `templates/extensions//`):
   - читаем шаблон,
   - подменяем плейсхолдеры (см. ниже),
   - пишем в `/` без `.tpl` в имени.
   - **исключение**: файл `README.md` в корне каждого
     `templates/extensions//` — это документация самого extension'а
     (для скилла, не для проекта). Не копируется в проект.
   - запоминаем список **записанных файлов** (`created_files[]`) —
     для отката.
3. Sanity-check: `grep -l '{{' ` (только по
   только-что-записанным файлам, не по всему каталогу — иначе ловим
   ложные срабатывания на `_README.md`-примерах). Если что-то
   осталось — error и **откат**:
   - **fresh-mode** (`created_root = true`): `rm -rf` всего каталога.
   - **extension-mode** (`created_root = false`): удаляем только
     `created_files[]`, не трогая ничего другого. **Никогда не
     удаляем целиком чужой каталог.**
4. `cd ` → `git init` → `git add .` →
   `git commit -m "scaffold from scaffold-project v{{SCAFFOLD_VERSION}}"`.
5. Спросить про push в origin (по правилу из workspace-CLAUDE.md
   «после каждого коммита спрашивать про push»). Если remote ещё нет —
   предложить `gh repo create` (с подтверждением).

## Плейсхолдеры

| Плейсхолдер | Источник |
|---|---|
| `{{PROJECT_NAME}}` | ответ пользователя |
| `{{PROJECT_NAME_UPPER}}` | UPPER_SNAKE_CASE из имени (`-` → `_`) |
| `{{SHORT_DESCRIPTION}}` | ответ на вопрос 2, первое предложение |
| `{{SCOPE_DESCRIPTION}}` | ответ на вопрос 2 целиком (или то же, что short) |
| `{{STACK}}` | human-readable mapping: `node-cli` → `Node.js 20+ (CLI / library)`, `python-mcp` → `Python 3.11+ (MCP server)`, `both` → `Node.js 20+ + Python 3.11+`, `none` → `TBD — choose during BL-001` |
| `{{DATE}}` | сегодняшняя дата `YYYY-MM-DD` |
| `{{AUTHOR}}` | `git config user.name`, или `unknown` |
| `{{SCAFFOLD_VERSION}}` | версия скилла из его `CHANGELOG.md` |
| `{{EXTERNAL_SERVICES}}` | ответ на вопрос 4, или `none` |
| `{{today}}` | сегодняшняя дата `YYYY-MM-DD` (alias к `{{DATE}}` для frontmatter) |
| `{{project_name}}` | то же что `{{PROJECT_NAME}}` (alias для frontmatter-шаблонов) |

Подмена — простой текстовый replaceAll по содержимому файла.

## Шаг 5 — после scaffold

После первого коммита Claude:

1. Резюмирует что создано (файлы, какие extensions подключены).
2. Указывает на `private/backlog/BL-1.md` как первую задачу
   (`in_progress`, scaffold). Открыть `private/backlog.base` в Obsidian
   — увидишь backlog как таблицу с view'ми Active / Archived / Cards.
3. Напоминает: «дальше работаем через `dev-workflow`. Все M/L задачи —
   через RFC, тесты, code-review».

## Back-fill mode — добавить дев-обвязку в существующий проект

Режим для проектов, у которых уже есть `CLAUDE.md` и свой контент, но
нет (или есть не вся) дев-обвязка: `private/backlog/`, `backlog.base`,
`rfc/`, `incidents.md`, `CHANGELOG.md`. Скилл добавляет недостающее
**из тех же `templates/base/`**, чтобы формат был один к одному с тем,
что получают свежие проекты.

**Зачем:** раньше Claude в таких проектах делал обвязку руками, сочинял
собственные поля в frontmatter, нарушал конвенции и потом приходилось
переделывать. Back-fill mode закрывает эту дыру — формат всегда из
templates, ничего не сочиняется.

### Когда триггерится

- Триггер-фраза: «причеши проект», «оформи как dev-проект»,
  «back-fill бэклог», «добавь дев-обвязку», `/scaffold-project --backfill`.
- Каталог: `CLAUDE.md` уже существует (иначе это fresh-init, не back-fill).

### Что back-fill делает (scope)

| Файл шаблона | Действие |
|---|---|
| `templates/base/CHANGELOG.md.tpl` | добавить если нет |
| `templates/base/incidents.md.tpl` | добавить если нет |
| `templates/base/rfc/_README.md` | добавить если `rfc/_README.md` нет |
| `templates/base/docs/decisions/_README.md` | добавить если нет (опционально, спросить) |
| `templates/base/private/backlog/_README.md` | добавить если `private/backlog/_README.md` нет |
| `templates/base/private/backlog.base.tpl` | добавить если `private/backlog.base` нет |
| `templates/base/.gitignore.tpl` | **merge**: если в существующем `.gitignore` нет правила, закрывающего `private/` — append блок про private и Obsidian. Иначе не трогать. |

### Что back-fill НЕ делает (out of scope)

- **Не перезаписывает** существующие `CLAUDE.md`, `README.md`,
  `DEVELOPMENT.md`, `.env.example`, `CHANGELOG.md`, `incidents.md`,
  `.gitignore` — только добавляет недостающие или мерджит `.gitignore`.
- **Не создаёт BL-1.** В fresh-mode `BL-1` — это «задача scaffold».
  В back-fill у проекта уже есть свой backlog и/или своя первая
  задача — навязывать наш не нужно.
- **Не мигрирует** существующий `BACKLOG.md` или `tasks/` в формат
  `private/backlog/BL-NN.md`. Если найден `BACKLOG.md` — скилл скажет
  «найден старый формат, миграция руками или отдельной задачей,
  back-fill не трогает».
- **Не нормализует frontmatter** существующих `BL-NN.md`. Если в них
  не-каноничные поля (`area`, `type`, статусы вроде `wip`/`backlog`) —
  скилл предупреждает, но не правит. Это отдельная задача (см.
  `dev-workflow groom`).
- **Не подключает stack-extensions** (`node-cli`, `python-mcp`) — у
  существующего проекта стек свой.
- **Не делает `git init`** — проект уже git.

### Алгоритм

1. **Pre-check.** Убедиться, что `CLAUDE.md` существует в cwd. Если
   нет — отказ «back-fill применяется в существующем проекте, а здесь
   нет CLAUDE.md. Если хотел fresh-init — скажи "новый проект"».

2. **Сканирование.** Для каждого пункта из таблицы scope выше — проверить
   target. Собрать checklist:
   - ✓ файл присутствует (для backlog — проверить что есть хотя бы
     `_README.md` или `BL-*.md`);
   - `+` файл отсутствует, будем добавлять;
   - `~` файл существует, но требуется merge (`.gitignore`);
   - `⚠` файл существует, но в нём подозрительные несоответствия (см.
     ниже) — не трогаем, флагуем пользователю.

   Дополнительные проверки:
   - `private/backlog/BL-*.md` существуют → прочитать frontmatter первого
     попавшегося. Если поля отличаются от каноничных (например, есть
     `area`/`type`/`updated`/`related` или статус не из набора
     `open|in_progress|done|archived`) — `⚠` с пояснением.
   - В корне есть `BACKLOG.md` → `⚠` «старый формат, миграция вручную».

3. **Render checklist** пользователю. Пример:
   ```
   Back-fill сканер по :
     ✓ CHANGELOG.md
     ✓ incidents.md
     ✓ rfc/_README.md
     + docs/decisions/_README.md
     ✓ private/backlog/_README.md
     ✓ private/backlog.base
     ~ .gitignore (добавить блок про private/)
     ⚠ private/backlog/BL-3.md содержит поле `area:` (не в каноне) — не трогаю
   ```

4. **Если все строки `✓`** — вывести «всё уже на месте, ничего делать
   не надо» и завершиться. Никаких записей, никаких коммитов.

5. **Иначе — preview.** Показать ровно те файлы, которые будут записаны
   (`+`) или смерджены (`~`). Никаких других файлов в preview быть не
   должно.

6. **Один вопрос approve**: «добавить?» — yes / no.

7. **На yes:**
   - `mkdir -p` для родительских каталогов под новые файлы.
   - Для каждого `+`: прочитать шаблон, подменить плейсхолдеры,
     записать. Запомнить в `created_files[]`.
   - Для `~` `.gitignore`: прочитать существующий → если каких-то
     строк из шаблона нет, дописать в конец отдельным блоком с
     комментарием `# Added by scaffold-project back-fill v{{SCAFFOLD_VERSION}}`.
     **Никогда не удалять и не переупорядочивать существующие строки.**
   - Sanity-check: `grep -l '{{' ` — если остатки
     плейсхолдеров, error и **откат только `created_files[]`** (не
     трогать ничего другого в каталоге).

8. **Git.** `git add` только тех файлов, которые попадают в git (не
   `private/`, потому что он gitignored). Предложить коммит-сообщение:
   ```
   chore: back-fill dev scaffolding via scaffold-project v{{SCAFFOLD_VERSION}}
   ```
   **Не коммитим без явного approve пользователя** (правило из global
   CLAUDE.md).

### Плейсхолдеры в back-fill

Только те, что встречаются в файлах из scope:
- `{{SCAFFOLD_VERSION}}` — версия скилла из его `CHANGELOG.md`.
- `{{DATE}}` — сегодня `YYYY-MM-DD`.
- `{{PROJECT_NAME}}` — `basename` cwd (как fallback, если в файле
  плейсхолдер встретится; в текущих шаблонах back-fill scope его нет).

### Edge cases

- **Каталог не git-репозиторий** → выполнить back-fill, но не предлагать
  `git add`/коммит. Сказать «это не git-репо, инициализируй git руками,
  если хочешь».
- **Есть `CLAUDE.md`, но нет любого другого индикатора проекта (только
  пустой CLAUDE.md)** → продолжить back-fill, это валидный случай.
- **Пользователь сказал «новый проект» в каталоге с CLAUDE.md** →
  отказ + подсказка про back-fill (см. Шаг 1).
- **Пользователь сказал «back-fill» в пустом каталоге** → отказ «здесь
  нет CLAUDE.md, ты, видимо, хотел fresh-init. Скажи "новый проект"».

## Self-update triggers — петля обратной связи

Когда пользователь работает **внутри проекта**, созданного через
scaffold-project (или живущего по тем же конвенциям), и впервые
появляется один из паттернов ниже — **до коммита** Claude **обязан**
сказать:

> «Это первый раз, когда мы делаем X в этом проекте. Хочешь, я вынесу
> обвязку в `~/.claude/skills/scaffold-project/templates/extensions//`,
> чтобы следующие проекты получали её сразу?»

| Триггер | Имя extension'а |
|---|---|
| Профильно-пользовательская архитектура (multi-user, identity, PII разделение) | `multi-user-base` |
| Подключение event analytics (PostHog/Amplitude/Mixpanel/GA4) | `ui-analytics` |
| Подключение error tracking (Sentry/Bugsnag/Rollbar) | `error-tracking` |
| Auth-флоу (OAuth/Clerk/Supabase Auth/Auth0) | `auth` |
| Платежи (Stripe/Paddle/LemonSqueezy) | `payments` |
| Первый GitHub Actions workflow | `ci-github` |
| Pre-commit secret-guard, написанный руками | `secret-guard` |
| Feature flags (GrowthBook/LaunchDarkly/Unleash) | `feature-flags` |
| DB migrations (Prisma/Alembic/Knex) | `db-migrations` |
| Dockerfile + deploy-config (Fly/Railway/Render) | `deploy-saas` |
| UI SPA scaffold (React/Vue/Svelte) | `ui-spa` |
| MCP server в Node | `mcp-node` |

**Решение принимает пользователь.** Если «не сейчас» — в этом же
проекте Claude больше не спрашивает про этот паттерн (на текущую
сессию). В другом проекте — спросит снова.

### Как добавить новый extension (по approve пользователя)

1. Создать каталог
   `~/.claude/skills/scaffold-project/templates/extensions//`.
2. Положить туда файлы паттерна с плейсхолдерами вместо
   project-specific значений (имена, токены, URL, продакт-named
   константы).
3. Добавить короткий `README.md` в самом extension'е: что включает,
   когда подключать, какие env-vars ждёт, как тестировать локально.
4. Обновить `CHANGELOG.md` скилла: новая запись «extension ``
   added» с датой и кратким резюме.
5. Обновить таблицу выше (триггер → имя extension'а), если паттерн
   новый.
6. Обновить Шаг 2 / вопрос про стек, если extension может быть
   подключён на старте проекта (а не только инкрементально).
7. Если extension должен подсказывать threat-model в RFC (для auth,
   payments, secret-guard) — упомянуть это в его README.

После этого вынос в текущем проекте идёт как обычно: код в проекте
коммитится, а его обобщённая копия живёт в скилле.

## Backlog как DB (Obsidian Bases)

С v0.3.0 бэклог скаффолдится как **база**, а не как страница.

- Один таск = один файл `BL-NN.md` (только номер, без слага в имени).
- В каждом — frontmatter: `id`, `title`, `status`, `priority`, `tier`, `created`, `tags` (опц. `closed`, `refs`, `blocked_by`).
- Статусы — **только** 4: `open`, `in_progress`, `done`, `archived`.
- Версии (`mvp-0`, `v0.5`, `v1.0`, `v2.0`) — через теги, не отдельные поля.
- `private/backlog.base` — Obsidian Bases view с готовыми таблицами (Active / Archived / Cards). Юзер открывает в Obsidian и видит всё как DB.

Конвенции расписаны в `templates/base/private/backlog/_README.md`. Шаблон первого таска — в `BL-1.md.tpl`. Правило: **не создавать единый `BA

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ymuromcev](https://github.com/ymuromcev)
- **Source:** [ymuromcev/claude-scaffold-project](https://github.com/ymuromcev/claude-scaffold-project)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ymuromcev-claude-scaffold-project-claude-scaffold-project
- Seller: https://agentstack.voostack.com/s/ymuromcev
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
