From d1d7cf8ef2e3b3c51e7c91f84a94e1a7e3d4278f Mon Sep 17 00:00:00 2001 From: Sergey <93754860+slaid098@users.noreply.github.com> Date: Fri, 24 Jul 2026 00:21:02 +0300 Subject: [PATCH] refactor: opencode-config skill rewrite + rename /configure-opencode (#27) * refactor: rename opencode-config to configure-opencode - command: .opencode/commands/opencode-config.md -> configure-opencode.md - skill dir: .opencode/skills/opencode-config/ -> configure-opencode/ - command body: skill({name: "opencode-config"}) -> skill({name: "configure-opencode"}) - project-map/README.md: update command+skill entries * refactor: rewrite configure-opencode skill for .opencode/ auto-discovery - flip canonical rule: config/opencode.json + bind-mount -> .opencode/opencode.json (project-local, auto-discovered, zero env var) - repo is the template users clone (git clone && opencode) - drop: bind-mount as primary (-> optional Docker), OPENCODE_CONFIG_DIR as required (-> power-user/Docker), Windows/ADR-009, internal env vars (ANTIDETECT/CONTEX7/CLOUDFLARE -> generic {env:MY_API_KEY}) - rename paths: config/ -> .opencode/, slaid098/opencode -> slaid098/opencode-config - preserve: MCP/provider/permission formats, top-level keys, findLast semantic, check-permissions.py guard - project-map: update entry descriptions for renamed command+skill * docs(handoff): add pr-12 handoff + ADR-007 * docs(handoff): rename pr-12 handoff/ADR to pr-27 (actual PR number) --------- Co-authored-by: opencode-agent --- .opencode/commands/configure-opencode.md | 5 +++ .opencode/commands/opencode-config.md | 5 --- .../SKILL.md | 45 +++++++++---------- .../007-pr-27-configure-opencode-rewrite.md | 19 ++++++++ .../pr-27-configure-opencode-rewrite.md | 23 ++++++++++ docs/project-map/README.md | 4 +- 6 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 .opencode/commands/configure-opencode.md delete mode 100644 .opencode/commands/opencode-config.md rename .opencode/skills/{opencode-config => configure-opencode}/SKILL.md (52%) create mode 100644 docs/decisions/007-pr-27-configure-opencode-rewrite.md create mode 100644 docs/handoff/pr-27-configure-opencode-rewrite.md diff --git a/.opencode/commands/configure-opencode.md b/.opencode/commands/configure-opencode.md new file mode 100644 index 0000000..52166d7 --- /dev/null +++ b/.opencode/commands/configure-opencode.md @@ -0,0 +1,5 @@ +--- +description: Edit opencode.json config (MCP, providers, permissions, agents) +agent: build +--- +Load the `configure-opencode` skill via `skill({name: "configure-opencode"})` and apply its canonical rules to the user's request about opencode.json changes (MCP servers, providers, permissions, agents, plugins). Follow the skill's rules strictly: always write to `.opencode/opencode.json` in slaid098/opencode-config repo (project-local, auto-discovered), never project-local in other repos. \ No newline at end of file diff --git a/.opencode/commands/opencode-config.md b/.opencode/commands/opencode-config.md deleted file mode 100644 index 6161677..0000000 --- a/.opencode/commands/opencode-config.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Edit opencode.json config (MCP, providers, permissions, agents) -agent: build ---- -Load the `opencode-config` skill via `skill({name: "opencode-config"})` and apply its canonical rules to the user's request about opencode.json changes (MCP servers, providers, permissions, agents, plugins). Follow the skill's rules strictly: always write to `config/opencode.json` in slaid098/opencode-config repo, never project-local. \ No newline at end of file diff --git a/.opencode/skills/opencode-config/SKILL.md b/.opencode/skills/configure-opencode/SKILL.md similarity index 52% rename from .opencode/skills/opencode-config/SKILL.md rename to .opencode/skills/configure-opencode/SKILL.md index d19e031..06c5f85 100644 --- a/.opencode/skills/opencode-config/SKILL.md +++ b/.opencode/skills/configure-opencode/SKILL.md @@ -1,33 +1,32 @@ --- -name: opencode-config -description: Use when adding, changing, or removing MCP servers, providers, permissions, agents, plugins, or any block in opencode.json. Always writes to config/opencode.json in slaid098/opencode-config repo (bind-mounted to global ~/.config/opencode/). Also when user says "добавь MCP", "подключи интеграцию", "пропиши permissions", "добавь провайдера", "измени конфиг opencode", "куда писать конфиг". +name: configure-opencode +description: Use when adding, changing, or removing MCP servers, providers, permissions, agents, plugins, or any block in opencode.json. Always writes to .opencode/opencode.json in slaid098/opencode-config (project-local, auto-discovered, zero env var). Also when user says "добавь MCP", "подключи интеграцию", "пропиши permissions", "добавь провайдера", "измени конфиг opencode", "куда писать конфиг". --- -# opencode-config +# configure-opencode -Канонический скилл для правок `opencode.json` в репо `slaid098/opencode-config`. Фиксирует контракт «куда писать конфиг» и форматы блоков. +Канонический скилл для правок `opencode.json` в репо `slaid098/opencode-config`. Фиксирует контракт «куда писать конфиг» и форматы блоков. Конфиг-репо — это шаблон, который клонируют пользователи. ## 1. Каноническое правило (canonical rule) -- **Всегда** пишем конфиг в `config/opencode.json` в репо `slaid098/opencode-config` → bind-mount `./config:/root/.config/opencode` (docker-compose.yml) → global `/root/.config/opencode/opencode.json`. -- **НЕ создавать** project-local `opencode.json` в других репо (например `.opencode/opencode.json` в `other-repo`). -- **НЕ спрашивать** пользователя «куда писать конфиг» — ответ всегда `config/opencode.json` в `slaid098/opencode-config`. -- **Исключение:** явный override-сценарий (project-local конфиг нужен для изоляции) — тогда указать явно в комментарии к изменению. - -Memory: `technical/opencode-config-global-vs-local.md` — детально описывает механизм bind-mount. +- **Всегда** пишем конфиг в `.opencode/opencode.json` в репо `slaid098/opencode-config` (project-local, auto-discovered). opencode автоматически подхватывает `.opencode/opencode.json` при запуске — без env var, без bind-mount, без symlink. +- **Репо `slaid098/opencode-config` сам по себе — шаблон**, который пользователь клонирует: `git clone … && opencode` в корне клона — и конфиг работает. +- **НЕ создавать** отдельный project-local `opencode.json` в других репо (например `.opencode/opencode.json` в `other-repo`) для глобальных настроек. Глобальные правки идут в `slaid098/opencode-config`. +- **НЕ спрашивать** пользователя «куда писать конфиг» — ответ всегда `.opencode/opencode.json` в `slaid098/opencode-config`. +- **Исключение:** явный override-сценарий (project-local конфиг нужен для изоляции в конкретном проекте) — тогда указать явно в комментарии к изменению. +- **Docker (опционально):** для контейнерного запуска можно bind-mount `.opencode/` → `~/.config/opencode/` (см. `docker-compose.yml`) — но это optional path, не канон. Репо обязан работать и bare-`opencode` в клона. ## 2. Применение изменений - `commit` + `push` в репо `slaid098/opencode-config` (через `commit` skill). -- На хосте: `git pull` в корне репо `slaid098/opencode-config`. -- Рестарт контейнера: MCP-серверы, skills, agents грузятся при старте (см. `add-skill/SKILL.md`, ADR-013). До рестарта правки не видны. -- Для Windows bare-metal (`windows/start.bat`): см. ADR-009 — `OPENCODE_CONFIG_DIR` НЕ выставляется (LSP-конфликт с `pyproject.toml` в cwd), конфиг на винде — отдельная задача. +- В клонах: `git pull` + рестарт opencode (MCP-серверы, skills, agents грузятся при старте — см. `add-skill/SKILL.md`). До рестарта правки не видны. +- Для Docker-сетапа: `git pull` на хосте + `docker compose restart opencode` (или эквивалент) — MCP/skills/agents грузятся при старте контейнера. ## 3. Структура top-level ключей `opencode.json` - `$schema` — JSON-schema URL для автокомплита в IDE. - `plugin` — npm-пакет плагина (например `@mathew-cf/opencode-memory`). -- `skills.paths` — массив путей к skill-директориям (по умолчанию `[".opencode/skills"]`, global из bind-mount добавляется автоматически). +- `skills.paths` — массив путей к skill-директориям (по умолчанию `[".opencode/skills"]`). - `compaction` — настройки сжатия контекста. - `disabled_providers` — массив отключённых провайдеров. - `provider` — current provider config (см. ниже). @@ -58,7 +57,7 @@ Memory: `technical/opencode-config-global-vs-local.md` — детально оп } ``` -**Env-плейсхолдеры:** `"{env:VAR_NAME}"` — значение подставляется из env контейнера. **НЕ хардкодить** секреты (API keys, tokens) в JSON. Пример: `"url": "{env:ANTIDETECT_BROWSER_MCP_URL}"`, `"--api-key", "{env:CONTEX7_API_KEY}"`. +**Env-плейсхолдеры:** `"{env:VAR_NAME}"` — значение подставляется из env. **НЕ хардкодить** секреты (API keys, tokens) в JSON. Пример: `"url": "{env:MY_API_URL}"`, `"--api-key", "{env:MY_API_KEY}"`. **timeout** — в миллисекундах, обязателен для медленных MCP (LLM-агенты, скрапинг). Для быстрых (well-known manifests) — можно опустить (default). @@ -93,24 +92,24 @@ Memory: `technical/opencode-config-global-vs-local.md` — детально оп - `allow` — команда выполняется без подтверждения. - `ask` — opencode спрашивает пользователя перед выполнением. - `deny` — команда блокируется (deny-лог в `opencode.log`). -- **Guard:** после правок `permission.bash` запускать локально `python3 config/scripts/check-permissions.py` — детектирует опасные паттерны (например `gh pr checks*`, ADR-006). CI (`permissions-check.yml`) запускает тот же скрипт. +- **Guard:** после правок `permission.bash` запускать локально `python3 .opencode/scripts/check-permissions.py` — детектирует опасные паттерны (например `gh pr checks*`, см. ADR-006). CI (`permissions-check.yml`) запускает тот же скрипт. - См. ADR-006 (детерминированный guard), ADR-005 (Actions API вместо Checks API в allow-list'ах). ## 7. Gotchas -- **bind-mount требует рестарта:** правки в `config/opencode.json` НЕ видны opencode до рестарта контейнера (MCP/skills/agents грузятся при старте). После commit+push — `git pull` на хосте + `docker compose restart opencode` (или эквивалент). -- **env-плейсхолдеры не хардкод:** секреты в `.env` (не в git), плейсхолдер `"{env:VAR}"` в `opencode.json` (в git). Пример: `ANTIDETECT_BROWSER_MCP_URL`, `CONTEX7_API_KEY`, `CLOUDFLARE_TUNNEL_TOKEN`. -- **`OPENCODE_CONFIG_DIR` env var:** указывает на директорию с `opencode.json`. На сервере задаётся `docker-compose.yml:environment`, на Windows bare-metal НЕ выставляется (ADR-009 — LSP-конфликт с `pyproject.toml` в cwd). +- **Рестарт обязателен:** правки в `.opencode/opencode.json` НЕ видны opencode до рестарта (MCP/skills/agents грузятся при старте). В клонах — рестарт opencode; в Docker — `docker compose restart opencode`. +- **env-плейсхолдеры не хардкод:** секреты в `.env` (не в git), плейсхолдер `"{env:VAR}"` в `opencode.json` (в git). Пример: `MY_API_URL`, `MY_API_KEY`, `MY_TUNNEL_TOKEN`. +- **`OPENCODE_CONFIG_DIR` env var (power-user/Docker):** указывает на директорию с `opencode.json` — загружается ПОСЛЕ `.opencode/` и МОЖЕТ переопределять его. Канонический путь `.opencode/` не требует этого env var; `OPENCODE_CONFIG_DIR` нужен только для кастомного layout (Docker, power-user). - **`findLast` семантика:** при конфликте правил побеждает последнее. Если добавить `deny` после `allow` — `deny` wins. Если `allow` после `deny` — `allow` wins. Порядок имеет значение. -- **CI проверяет permissions:** `permissions-check.yml` запускается на PR с изменениями `config/opencode.json`, `config/agents/**`, `config/scripts/check-permissions.py`. Локальная проверка перед commit: `python3 config/scripts/check-permissions.py` → exit 0, "OK: No dangerous permission rules found." +- **CI проверяет permissions:** `permissions-check.yml` запускается на PR с изменениями `.opencode/opencode.json`, `.opencode/agents/**`, `.opencode/scripts/check-permissions.py`. Локальная проверка перед commit: `python3 .opencode/scripts/check-permissions.py` → exit 0, "OK: No dangerous permission rules found." ## 8. Commit message - Формат: `feat(config): ...` / `chore(config): ...` / `fix(config): ...` (conventional commits, English, ≤72 chars). - Перед commit — загрузить `commit` skill, проверить `git log --oneline -20`, match existing style. -- Примеры: `feat(config): add integrations.sh MCP server`, `fix(config): correct timeout for integrations discover tool`. +- Примеры: `feat(config): add integrations MCP server`, `fix(config): correct timeout for integrations discover tool`. ## 9. Не дублировать блоки между репо -- `opencode.json` в `slaid098/opencode-config` — единственный источник правды для global-конфига. -- Project-local `opencode.json` в других репо — только для явного override (например отключить MCP для конкретного проекта). В 99% случаев не нужен. \ No newline at end of file +- `.opencode/opencode.json` в `slaid098/opencode-config` — единственный источник правды для конфига. Репо сам по себе — шаблон, который клонируют. +- Project-local `opencode.json` в других репо — только для явного override (например отключить MCP для конкретного проекта). В 99% случаев не нужен — клонируй `slaid098/opencode-config` или используй `instructions` array с remote URLs. \ No newline at end of file diff --git a/docs/decisions/007-pr-27-configure-opencode-rewrite.md b/docs/decisions/007-pr-27-configure-opencode-rewrite.md new file mode 100644 index 0000000..a0b019d --- /dev/null +++ b/docs/decisions/007-pr-27-configure-opencode-rewrite.md @@ -0,0 +1,19 @@ +# ADR-007: opencode-config skill rewrite for .opencode/ auto-discovery + +## Статус +Accepted + +## Контекст +`configure-opencode` skill (ранее `opencode-config`, создан в приватном репо) описывал старую архитектуру: `config/opencode.json` + bind-mount + `OPENCODE_CONFIG_DIR` + Windows bare-metal (`windows/start.bat`, LSP-конфликт `pyproject.toml` на Windows — не релевантен публичному Linux-шаблону). Новый репо `slaid098/opencode-config` использует `.opencode/` auto-discovery (project-local, zero env var) — см. ADR-002 (миграция config/ → .opencode/). Skill противоречил ADR-002 и вводил в заблуждение пользователей публичного шаблона. + +## Решение +- **Flip canonical rule (§1, §9):** `.opencode/opencode.json` (project-local, auto-discovered) вместо `config/opencode.json` + bind-mount. Репо сам — шаблон, который клонируют (`git clone … && opencode`). +- **Drop:** bind-mount как primary механизм (→ optional Docker path), `OPENCODE_CONFIG_DIR` как required concept (→ power-user/Docker env var only), Windows bare-metal / LSP-конфликт `pyproject.toml` (не мигрировал в публичный репо), internal env vars (`ANTIDETECT_BROWSER_MCP_URL`, `CONTEX7_API_KEY`, `CLOUDFLARE_TUNNEL_TOKEN`) → generic `{env:MY_API_KEY}`. +- **Rename paths:** `config/...` → `.opencode/...`, `slaid098/opencode` → `slaid098/opencode-config` (кроме `opencode-memory`). +- **Rename command + skill:** `/opencode-config` → `/configure-opencode` (command file, skill dir, `skill({name: ...})` ref, frontmatter `name`). +- **Preserve:** форматы MCP/provider/permission (архитектурно-агностичны), top-level keys reference, `findLast` semantic, `check-permissions.py` guard, ADR-005/ADR-006 refs. + +## Альтернативы +- **Drop skill entirely** — отклонено: форматы MCP/provider/permission не очевидны из официальных доков opencode; `findLast` semantic и `check-permissions.py` guard — repo-specific знания, которые нужно сохранить. +- **Keep old skill** — отклонено: противоречит ADR-002 (`.opencode/` architecture), вводит в заблуждение пользователей публичного шаблона (они не используют bind-mount). +- **Rewrite без rename** — отклонено: rename `/opencode-config` → `/configure-opencode` устраняет коллизию имени с репо `slaid098/opencode-config` и лучше отражает action-verb naming остальных commands (`/pipeline-driver`, `/spec-driver`). \ No newline at end of file diff --git a/docs/handoff/pr-27-configure-opencode-rewrite.md b/docs/handoff/pr-27-configure-opencode-rewrite.md new file mode 100644 index 0000000..d933ea2 --- /dev/null +++ b/docs/handoff/pr-27-configure-opencode-rewrite.md @@ -0,0 +1,23 @@ +# PR: opencode-config skill rewrite + rename /configure-opencode + +## Что сделано +- Rename: /opencode-config → /configure-opencode (command file + skill dir + `skill({name: ...})` ref) +- Rewrite canonical rule: `config/opencode.json` + bind-mount → `.opencode/opencode.json` (project-local, auto-discovered, zero env var). Репо сам — шаблон, который клонируют. +- Dropped: bind-mount как primary механизм (→ optional Docker path), `OPENCODE_CONFIG_DIR` как required concept (→ power-user/Docker env var only), Windows bare-metal / `windows/start.bat` (LSP-конфликт `pyproject.toml` на Windows — не релевантен публичному Linux-шаблону), internal env vars (`ANTIDETECT_BROWSER_MCP_URL`, `CONTEX7_API_KEY`, `CLOUDFLARE_TUNNEL_TOKEN`) → generic `{env:MY_API_KEY}` +- Renamed paths: `config/...` → `.opencode/...` (включая `check-permissions.py` guard ref), `slaid098/opencode` → `slaid098/opencode-config` (кроме `opencode-memory`) +- Preserved: форматы MCP/provider/permission, top-level keys reference, `findLast` semantic, `check-permissions.py` guard, ADR-005/ADR-006 refs +- Side: `docs/project-map/README.md` — обновлены строки `opencode-config.md` → `configure-opencode.md`, `opencode-config/SKILL.md` → `configure-opencode/SKILL.md` (минимально, чтобы не оставлять битые refs после rename) + +## Почему +Skill описывал старую архитектуру (`config/opencode.json` + bind-mount + `OPENCODE_CONFIG_DIR` + Windows bare-metal). Новый репо использует `.opencode/` auto-discovery (см. ADR-002 — миграция config/ → .opencode/). Форматы MCP/provider/permission архитектурно-агностичны — сохранены. + +## Pending +- Нет + +## Watch out +- Форматы MCP/provider/permission сохранены (архитектурно-агностичны) — правки только в canonical rule (§1, §9), gotchas (§7), paths +- `OPENCODE_CONFIG_DIR` оставлен как power-user/Docker опция (не удалён полностью) — загружается ПОСЛЕ `.opencode/`, может переопределять; канонический путь `.opencode/` не требует его +- `bind-mount` оставлен как optional Docker path (см. `docker-compose.yml`) — репо обязан работать и bare-`opencode` в клона +- Skill `opencode-config` (создан в приватном репо) — superseded этим rewrite. ADR-002 (этого репо) фиксирует миграцию архитектуры `config/` → `.opencode/` +- `docs/project-map/README.md` правки вне issue scope, но без них rename оставил бы битые refs в project map +- ADR refs в SKILL.md (`ADR-005`, `ADR-006`) валидируются `check-adr-refs.py` — `.opencode/` исключён из сканирования, но ADR-005/006 существуют в `docs/decisions/` (если сканирование расширят) \ No newline at end of file diff --git a/docs/project-map/README.md b/docs/project-map/README.md index 033481c..72a309c 100644 --- a/docs/project-map/README.md +++ b/docs/project-map/README.md @@ -18,7 +18,7 @@ opencode-config/ │ │ ├── memory-syncer.md # Distills gotchas from handoffs into opencode-memory │ │ └── reviewer.md # Code review subagent (verdict APPROVE|REQUEST_CHANGES) │ ├── commands/ -│ │ ├── opencode-config.md # /opencode-config — edit opencode.json +│ │ ├── configure-opencode.md # /configure-opencode — edit opencode.json │ │ ├── pipeline-driver.md # /pipeline-driver — 7-phase PR pipeline │ │ └── spec-driver.md # /spec-driver — 9-phase spec generation │ ├── skills/ @@ -29,7 +29,7 @@ opencode-config/ │ │ ├── get-project-map/SKILL.md # Maintain docs/project-map/ │ │ ├── issue/SKILL.md # GitHub issue creation │ │ ├── memory/SKILL.md # opencode-memory usage guide -│ │ ├── opencode-config/SKILL.md # Canonical rule: write to .opencode/ +│ │ ├── configure-opencode/SKILL.md # Canonical rule: write to .opencode/ │ │ ├── pipeline-driver/SKILL.md # 7-phase pipeline orchestration │ │ ├── python-development/SKILL.md # Python dev patterns │ │ ├── release/SKILL.md # Tag + GitHub Release