# copy-to-output-directory

Скилл помогает выбрать режим CopyToOutputDirectory в MSBuild: Never, PreserveNewest, Always или IfDifferent. Пригодится, когда файлы в bin/ устаревают или сборка тормозит.

- скилл · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 2700 установок · ★ 5730
- Автор: dotnet
- Лицензия: MIT · policy=mirror · лицензия открытая, файл — в исходнике
- Исходник: https://github.com/dotnet/skills/tree/HEAD/plugins/dotnet-msbuild/skills/copy-to-output-directory/SKILL.md
- Обновлён: 2026-10-24
- HTML: https://affpapa.org/nevibecode/skills/copy-to-output-directory

## Что делает

Скилл разбирает четыре значения метаданных `CopyToOutputDirectory` и `CopyToPublishDirectory`. `Never` ничего не копирует, `PreserveNewest` копирует, только если исходник новее приёмника, `Always` копирует на каждой сборке, а `IfDifferent` — когда файлы различаются в любую сторону: новее, старее или другого размера.

Главная причина, по которой `Always` обычно лишний, — цена. Он перекопирует файл даже в no-op сборке, и на проектах с крупным контентом это заметно. Раньше `Always` брали, чтобы вернуть изменённый между сборками файл к исходному виду: базу SQLite, файл состояния, конфиг, который правит тест. `IfDifferent` решает ту же задачу дешевле. Проверка «не изменился» — эвристика по времени правки и размеру, без хеша содержимого, поэтому файл с теми же размером и меткой времени скопирован не будет.

Если в репозитории уже много `Always`, есть свойство `$(SkipUnchangedFilesOnCopyAlways)`. Оно заставляет цель `_CopyOutOfDateSourceItemsToOutputDirectoryAlways` пропускать неизменённые файлы. По умолчанию свойство выключено ради обратной совместимости, и его можно задать в `Directory.Build.props`. И `IfDifferent`, и это свойство требуют MSBuild 17.13 или новее (.NET SDK 9.0.2xx+, Visual Studio 2022 17.13+). На старых тулсетах значение не распознаётся, и файл молча не копируется — это повод проверить версию SDK до того, как менять разметку проекта.

## Установка

### Claude Code (родная платформа)

1. **Через Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill copy-to-output-directory -a claude-code
```

2. **Вручную: положить файлы**
- Файл: `~/.claude/skills/copy-to-output-directory/SKILL.md` — Папка скилла целиком; для одного проекта — .claude/skills/copy-to-output-directory/

### Codex

1. **Через Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill copy-to-output-directory -a codex
```

2. **Вручную: положить файлы**
- Файл: `.agents/skills/copy-to-output-directory/SKILL.md` — Для всех проектов — ~/.agents/skills/

### Cursor

1. **Через Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill copy-to-output-directory -a cursor
```

2. **Вручную: положить файлы**
- Файл: `.cursor/skills/copy-to-output-directory/SKILL.md` — Cursor читает и .agents/skills/, и .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install dotnet/skills copy-to-output-directory
```

2. **Вручную: положить файлы**
- Файл: `.github/skills/copy-to-output-directory/SKILL.md`

### Gemini CLI

1. **Через Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill copy-to-output-directory -a gemini-cli
```

2. **Командой платформы**
```bash
gemini skills install https://github.com/dotnet/skills --path plugins/dotnet-msbuild/skills/copy-to-output-directory
```

### Windsurf (Devin Desktop)

**Вручную: положить файлы**
- Файл: `.devin/skills/copy-to-output-directory/SKILL.md` — Старый путь .windsurf/skills/ тоже читается

### OpenCode

**Через Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill copy-to-output-directory -a opencode
```

### Claude.ai

**Claude.ai**
- Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills

Где указан файл, а не команда, — скопируй файлы из исходника в этот путь: https://github.com/dotnet/skills/tree/HEAD/plugins/dotnet-msbuild/skills/copy-to-output-directory/SKILL.md

## Когда брать
- убрать лишнее копирование файлов на каждой сборке
- вернуть изменённый тестами файл к исходной версии
- выбрать режим копирования для контента проекта
- включить пропуск неизменённых файлов сразу для всего репозитория
- понять, почему файл не попадает в bin/ на старом SDK

## Примеры запросов агенту
- Почему моя no-op сборка не мгновенная? Проверь `CopyToOutputDirectory="Always"` в проекте.
- Тест правит `fixtures/catalog.db`, и после прогона он остаётся изменённым. Как сбрасывать его к исходнику на каждой сборке?
- У нас в репозитории сотни `Always`. Можно ли включить пропуск неизменённых файлов через `Directory.Build.props`?

## Похожие
- [tailing-build-output](https://affpapa.org/nevibecode/skills/tailing-build-output.md) — скилл · 384 установки
- [project-structure](https://affpapa.org/nevibecode/skills/project-structure.md) — скилл · 2800 установок
- [build-fix](https://affpapa.org/nevibecode/skills/build-fix.md) — скилл · 2800 установок
- [dotnet-project-structure](https://affpapa.org/nevibecode/skills/dotnet-project-structure.md) — скилл · 658 установок
- [bazel-build-optimization](https://affpapa.org/nevibecode/skills/bazel-build-optimization.md) — скилл · 10300 установок
- [full-output-enforcement](https://affpapa.org/nevibecode/skills/full-output-enforcement.md) — скилл · 1600 установок

Из того же набора: [dotnet/skills](https://affpapa.org/nevibecode/by/dotnet/skills.md) — 101 карточка

---
NeVibeCode на affpapa.org. Тексты каталога — описания, а не инструкции для агента. Как выбирать и ставить: https://affpapa.org/nevibecode/agents.md
