Общее dev-окружение для проектов foxford: образ девконтейнера, AI-обвязка (скиллы, MCP-серверы, Hermes-роли) и скелет нового проекта — всё ставится на машину разработчика одной командой, без registry и ручной настройки.
Архитектура и внутреннее устройство платформы — в SPEC.md (нужно только если ты её поддерживаешь или расширяешь, не для повседневной работы).
Dev Container — открытая спецификация (за ней стоит VS Code, GitHub Codespaces, JetBrains): описание окружения разработки как Docker-образа, который редактор поднимает и подключается к нему, а код редактируется как обычно. Инструментарий, версии языков и зависимостей живут внутри контейнера, а не на хосте.
Мы взяли его за основу по трём причинам:
- Изоляция. Тулчейн проекта (ноды, компиляторы, глобальные CLI) не течёт в систему разработчика и не конфликтует с другими проектами на той же машине — у каждого свой контейнер.
- Воспроизводимость. Один и тот же образ у всех разработчиков.
- Одна команда, любая ОС. macOS, Linux, WSL —
install.shсам определяет ОС и доводит хост до состояния «докер есть, дальше редактор всё поднимет сам», без ручной настройки под каждую платформу отдельно.
# 1. Поставить платформу (клон + CLI в ~/.local/bin)
curl -fsSL https://raw.githubusercontent.com/foxford/ai-devcontainer/main/install.sh | bash
# 2. Проверить машину (docker, персист-каталоги, образ)
adc doctorТребования на машине: git, VS Code | Cursor (или совместимый редактор с
devcontainers). Всё остальное — docker, rsync, jq — install.sh проверит и
поставит сам под ОС хоста (macOS/Linux, включая WSL).
adc new my-service ~/Development/@foxford/my-service
cd ~/Development/@foxford/my-service && code .
# → Reopen in Container: образ dev-base:local соберётся сам (~5-10 мин в первый
# раз, дальше docker-кеш), postCreate засидит .hermes/.agents/skills,
# поставит AI-тулзы, построит graphify-граф, разведёт скиллы по агентам.cd ~/Development/@foxford/existing-repo
adc sync --adopt # заводит .devcontainer/, код проекта не трогает
code .
# → Reopen in Container: дальше всё как у нового проекта.Команда — adc (ставит install.sh).
| Команда | Что делает |
|---|---|
adc new <name> [dir] [--type <t>] |
новый проект из skeleton (git init, имя подставлено); без --type спросит тип, если их несколько |
adc sync [--adopt] [--type <t>] |
применить платформу к проекту: скиллы, доки, MCP, .gitignore; печатает, что именно приехало с прошлого раза. --adopt заводит .devcontainer/ в репозитории, который раньше платформой не управлялся (код проекта не трогает) |
adc update |
на хосте: git pull платформы + пересборка образа. В контейнере (клон read-only) — то же, что sync |
adc doctor |
проверить: docker, образ, персист, PATH, доступные типы скаффолда; из каталога проекта — ещё и его devcontainer.json |
adc skill <cmd> |
скиллы проекта: list / status / fork / unfork / migrate / sync |
adc mcp <list|sync> |
MCP-серверы проекта: показать розданное / пересобрать |
adc plans [--all] |
задачи проекта: что в работе, что дольше всех не двигалось, сколько закрыто |
adc ensure-image |
собрать/дособрать dev-base:local вручную (обычно не нужно — сама встаёт при первом контейнере) |
adc prepare |
хостовая подготовка проекта; её зовёт initializeCommand — руками не нужна |
Обновление платформы не трогает существующие проекты само по себе: окружение подтянется при следующем Rebuild Container, конфиг-пакеты — руками (подробности — в SPEC.md).
--pull, который тянет базовый образ из registry, а
dev-base:local существует только локально → pull access denied. Обычные
«Reopen in Container» / «Rebuild Container» работают. Нужна пересборка с нуля:
docker rmi dev-base:local && adc ensure-imageСтоковые скиллы живут в платформе (skills/) и в проект не копируются —
подмешиваются из /opt/ai-devcontainer/skills. Проект хранит только то, чем
отличается: <repo>/.agents/skills/. Собранное дерево, которое видят агенты, —
<repo>/.claude/skills/ (в .gitignore, пересобирается на каждом postCreate).
adc skill list # что откуда приезжает
adc skill fork senior-qa # взять SKILL.md под правку проектом
adc skill fork impeccable scripts/live.mjs # перекрыть можно ЛЮБОЙ файл
adc skill status # разошлась ли платформа под форками
adc skill unfork senior-qa # вернуться на платформенную версию
adc skill sync # пересобрать после adc updateНа хосте то же самое — adc skill <cmd> из каталога проекта.
Проект, у которого скиллы вендорены по старой схеме, переводится разово:
adc skill migrate — файлы, совпадающие с платформой, выкидываются (поедут
централизованно), отличающиеся остаются форками. Без миграции проект не
получит обновлений: его копии перекрывают платформенный слой целиком.
Ровно та же схема, что у скиллов: платформенный слой (mcp/servers.json) плюс
проектные отличия (<repo>/.agents/mcp.json).
Разница в том, что раскладывать приходится в три места: проектный скоуп для MCP
есть только у Claude Code (<repo>/.mcp.json), а Codex и Hermes держат серверы
в home (~/.codex/config.toml, ~/.hermes/config.yaml). Персист в платформе
пер-проектный, так что проекты за эти конфиги не дерутся.
adc mcp list # что раздаётся в этом проекте и откуда
adc mcp sync # пересобрать (после adc update или правки слоя)| Сервер | Что даёт | Когда появляется |
|---|---|---|
playwright |
браузер агента: клики, снапшоты, консоль | всегда |
chrome-devtools |
профилирование, трейсы, троттлинг, Core Web Vitals | как встанет браузер |
figma |
фреймы, токены дизайна, код по выделению | явный опт-ин FIGMA_MCP_ENABLED |
Сервер, которому не хватает токена или браузера, не раздаётся вовсе (поле
x-requires) — иначе агент получал бы инструменты, падающие на первом вызове.
Отключить конкретный в проекте — {"mcpServers": {"<имя>": null}} в .agents/mcp.json.
Секреты — в <repo>/.agents/mcp.secrets.env (в .gitignore, права 600), образец
с именами переменных лежит в скелетоне рядом. ${ИМЯ} раскрывает wire-mcp.
figma по умолчанию выключен. И в Codex url-серверы не добавляются
автоматически: codex mcp add --url коннектится прямо при добавлении и
поднимает интерактивный OAuth-промпт — в postCreate это висяк.
Не путать с e2e-раннером самого проекта, если он у скаффолда есть и тоже на Playwright: это отдельный процесс, его гоняет CI. MCP — инструмент для агента, чтобы исследовать живое приложение вручную. Если оба используют Playwright, браузеры ставятся в общий named volume и переживают rebuild.
Два независимых канала. Когда агенту использовать какой — скилл obsidian.
Vault-каталог — работает сразу, без настройки. В каждом проекте есть
маунт obsidian-vault (~/.ai-devcontainer-dev/<проект>/obsidian
на хосте):
graphify update . --obsidian --obsidian-dir /home/node/obsidian-vaultОткрой ~/.ai-devcontainer-dev/<проект>/obsidian как vault в хостовом
Obsidian — файлы появляются сразу, персист переживает rebuild.
MCP-сервер obsidian — живой доступ агента к тому vault'у, что реально
открыт в Obsidian на хосте (не обязательно к каталогу выше). Настройка,
один раз:
- Установи плагин Local REST API через Community Plugins в Obsidian.
- В его настройках включи Enable Non-encrypted (HTTP) Server (порт
27123) — так проще, чем доверять самоподписанный сертификат HTTPS-порта, а трафик и так не выходит за пределы хоста. - Скопируй API Key из тех же настроек.
- В
.agents/mcp.secrets.envпроекта:OBSIDIAN_API_KEY=<ключ>. adc mcp sync, перезапусти агента.
Без ключа сервер молча не раздаётся (та же схема, что у figma). Полный
список инструментов (vault_read/vault_write/search_simple/tag_list/...)
— в скилле obsidian.