- skills list / catalog list распознают неинициализированные сабмодули: жёлтое предупреждение, строка «не инициализирован», в итоге — «Стянуть: harness catalog init» - новый action catalog init: стягивает сабмодули на зафиксированных коммитах, идемпотентен - catalog update теперь работает из свежего клона: сначала init, потом --remote - skills install подсказывает про catalog init, если источники не стянуты - русское склонение чисел (plural): 1 скилл / 2 скилла / 5 скиллов - README: раздел «Свежий клон», правило 10 в «Правилах вывода списков»
327 lines
15 KiB
Markdown
327 lines
15 KiB
Markdown
# Harness 🛠️
|
||
|
||
**Универсальный менеджер скиллов, агентов, MCP-серверов и конфигов для Hermes и OpenCode.**
|
||
|
||
Репа-каталог, где живут ссылки на полезные skills, MCP-серверы, тулзы и агенты — с единым скриптом управления.
|
||
|
||
```
|
||
dev/harness/
|
||
├── agents/ # Определения агентов OpenCode (leader, fixer, devops, admin, ...)
|
||
├── catalog/ # Скиллы: git submodule'ы на внешние репы
|
||
│ ├── jakubkrehel-skills/ # → github.com/jakubkrehel/skills (11 скиллов UI)
|
||
│ └── developer-documentation-skill/ # → NateBJones-Projects/… (доки; ставится вручную)
|
||
├── scripts/
|
||
│ └── harness # Основной CLI-скрипт
|
||
└── README.md
|
||
```
|
||
|
||
## Грамматика
|
||
|
||
**Объект — первым, действие — вторым:** `harness <объект> <действие> [аргументы]`
|
||
|
||
| Объект | Что это | Действия |
|
||
|--------|---------|----------|
|
||
| `status` | среда целиком | — |
|
||
| `skills` | скиллы из каталога | `list`, `installed`, `install`, `remove` |
|
||
| `agents` | агенты (только OpenCode) | `list`, `install`, `remove` |
|
||
| `mcp` | MCP-серверы Hermes | `list`, `add`, `rm` |
|
||
| `catalog` | внешние репозитории каталога | `list`, `init`, `update` |
|
||
| `hermes` | сам Hermes | `config`, `restart`, `update` |
|
||
| `opencode` | сам OpenCode | `install`, `restart` |
|
||
|
||
```bash
|
||
./scripts/harness status
|
||
./scripts/harness skills list
|
||
./scripts/harness skills install jakubkrehel-skills better-ui --target all
|
||
./scripts/harness agents install leader
|
||
./scripts/harness mcp list
|
||
./scripts/harness catalog update
|
||
./scripts/harness hermes restart
|
||
```
|
||
|
||
## Быстрый старт
|
||
|
||
```bash
|
||
./scripts/harness status # Обзор среды
|
||
./scripts/harness skills list # Что доступно в каталоге (+ отметки установки)
|
||
./scripts/harness skills installed # Что реально стоит у агентов
|
||
./scripts/harness agents list # Агенты: доступные в репо + установленные
|
||
./scripts/harness mcp list # MCP-серверы Hermes
|
||
./scripts/harness catalog list # Источники каталога
|
||
```
|
||
|
||
## Правила вывода списков
|
||
|
||
Все списочные команды идут через один рендерер — `render_listing()`. Новую
|
||
списочную команду нужно добавлять так же: собрать `rows` и вызвать рендерер,
|
||
а не печатать таблицу самой.
|
||
|
||
```
|
||
СКИЛЛЫ — доступно к установке ← 1. заголовок ВЕРХНИМ РЕГИСТРОМ
|
||
Каталог: /mnt/data/Agent/dev/harness/catalog ← 2. источник, dim
|
||
✓ — установлено, · — нет ← 3. легенда, если есть отметки
|
||
|
||
jakubkrehel-skills (11 скиллов, 267330e) ← 4. группа, мета в скобках
|
||
├─ better-ui hermes · opencode ✓ ← 5. имя, мета, отметки
|
||
│ Polishes and improves the UI in your… ← 6. описание, обрезка до 72
|
||
|
||
Итого: 12 скиллов, установлено 0 ← 7. итог
|
||
hermes ~/.hermes/skills/catalog ← куда ставится, dim
|
||
```
|
||
|
||
1. **Заголовок** — ВЕРХНИМ РЕГИСТРОМ, формат `<ОБЪЕКТ> — что именно`.
|
||
2. **Источник** — второй строкой, dim: `Каталог: <путь>` / `Источник: <путь>`.
|
||
3. **Легенда отметок** — `✓ — установлено, · — нет`, только если отметки есть.
|
||
4. **Группы** — жёлтым, метаданные в скобках (кол-во, sha, `⚠ сдвинут`), между
|
||
группами пустая строка. Нет групп — строки идут сразу после легенды.
|
||
5. **Элемент** — `├─ <имя>` (cyan, выравнивание по самому длинному имени), затем
|
||
мета (dim, выровнена), затем отметки `<цель> ✓` / `<цель> ·`, затем пометка (yellow).
|
||
6. **Описание** — строкой ниже, dim, обрезано до 72 символов.
|
||
7. **Итог** — `Итого: N <единица>, установлено M`, ниже dim-строками — куда ставится.
|
||
8. **Только русский.** Никаких `Available` / `Installed` вперемешку с русским.
|
||
9. **Порядок отметок** = порядок целей из `--target` / `--scope`.
|
||
10. **Числа — со склонением** через `plural()`: 1 скилл, 2 скилла, 5 скиллов.
|
||
|
||
Правила продублированы комментарием в `scripts/harness` над `render_listing()`.
|
||
|
||
## `skills` — скиллы из каталога
|
||
|
||
### `skills list` — что доступно к установке
|
||
|
||
Показывает содержимое каталога и где скилл уже стоит. `✓` — установлено, `·` — нет.
|
||
|
||
```bash
|
||
./scripts/harness skills list
|
||
./scripts/harness skills list --target opencode
|
||
```
|
||
|
||
```
|
||
СКИЛЛЫ — доступно к установке
|
||
Каталог: /mnt/data/Agent/dev/harness/catalog
|
||
✓ — установлено, · — нет
|
||
|
||
jakubkrehel-skills (11 скиллов, 267330e)
|
||
├─ better-ui hermes · opencode ✓
|
||
│ Polishes and improves the UI in your project…
|
||
├─ better-colors hermes · opencode ·
|
||
│ Helps you build a color system…
|
||
...
|
||
|
||
Итого: 12 скиллов, установлено 1
|
||
Поставить: harness skills install <источник> <скилл>|--all
|
||
hermes ~/.hermes/skills/catalog
|
||
opencode ~/.claude/skills ~/.config/opencode/skills
|
||
```
|
||
|
||
Для git-источников в скобках группы виден короткий sha; `⚠ сдвинут` — submodule
|
||
ушёл вперёд и это ещё не закоммичено.
|
||
|
||
### `skills installed` — что реально стоит
|
||
|
||
Полное дерево каталогов агента, включая скиллы не из каталога.
|
||
|
||
```bash
|
||
./scripts/harness skills installed
|
||
./scripts/harness skills installed --target hermes
|
||
```
|
||
|
||
### `skills install` / `skills remove`
|
||
|
||
```bash
|
||
# Один скилл
|
||
./scripts/harness skills install jakubkrehel-skills better-ui --target opencode
|
||
./scripts/harness skills install jakubkrehel-skills/better-ui --target all
|
||
|
||
# Все скиллы источника
|
||
./scripts/harness skills install jakubkrehel-skills --all --target opencode
|
||
|
||
# Удалить
|
||
./scripts/harness skills remove better-ui
|
||
./scripts/harness skills remove better-ui --target hermes
|
||
```
|
||
|
||
Скиллы ставятся **симлинками**:
|
||
|
||
| Агент | Куда ставится |
|
||
|-------|--------------|
|
||
| Hermes | `~/.hermes/skills/catalog/<name>/` |
|
||
| OpenCode | `~/.claude/skills/<name>/` |
|
||
| OpenCode | `~/.config/opencode/skills/<name>/` |
|
||
|
||
## `agents` — агенты (только OpenCode)
|
||
|
||
Источник — `harness/agents/*.md`. Имя агента = имя файла без `.md`.
|
||
|
||
```bash
|
||
./scripts/harness agents list
|
||
./scripts/harness agents list --scope global
|
||
./scripts/harness agents list --scope project --project ~/work/myrepo
|
||
|
||
./scripts/harness agents install leader # в ~/.config/opencode/agents/
|
||
./scripts/harness agents install --all --scope global
|
||
./scripts/harness agents install devops --scope project --project ~/work/myrepo
|
||
|
||
./scripts/harness agents remove leader
|
||
./scripts/harness agents remove leader --scope global
|
||
```
|
||
|
||
| `--scope` | Куда ставится |
|
||
|-----------|--------------|
|
||
| `global` (по умолчанию) | `~/.config/opencode/agents/<name>.md` |
|
||
| `project` | `<project>/.opencode/agents/<name>.md` (по умолчанию — cwd) |
|
||
|
||
Ставятся симлинками, так что правки в репе сразу видны OpenCode. Все агенты имеют
|
||
`mode: all` (кроме `leader` — `primary`), чтобы лидер мог вызывать их как сабагентов.
|
||
|
||
> **Hermes агентов не поддерживает** — только runtime-делегирование через
|
||
> `delegate_task`. Пользовательских определений агентов у него нет.
|
||
|
||
## `mcp` — MCP-серверы Hermes
|
||
|
||
```bash
|
||
./scripts/harness mcp list
|
||
|
||
# По URL (HTTP/SSE)
|
||
./scripts/harness mcp add my-server http://localhost:8000/mcp
|
||
|
||
# Командой (stdio)
|
||
./scripts/harness mcp add github npx \
|
||
--env GITHUB_TOKEN=ghp_xxx \
|
||
--arg -y --arg @modelcontextprotocol/server-github
|
||
|
||
./scripts/harness mcp rm my-server
|
||
```
|
||
|
||
`add` и `rm` сами перезапускают `hermes-gateway`, чтобы изменения подхватились.
|
||
|
||
## `catalog` — внешние репозитории
|
||
|
||
```bash
|
||
./scripts/harness catalog list # источники, sha, признак «сдвинут»
|
||
./scripts/harness catalog init # стянуть submodule'ы на зафиксированных коммитах
|
||
./scripts/harness catalog update # подтянуть свежие коммиты upstream (потом закоммитить)
|
||
```
|
||
|
||
### Свежий клон
|
||
|
||
Submodule'ы **не** тянутся при обычном `git clone` — каталоги `catalog/*/` окажутся
|
||
пустыми. `skills list` это распознаёт и подсказывает, что делать:
|
||
|
||
```
|
||
СКИЛЛЫ — доступно к установке
|
||
Каталог: /path/to/catalog
|
||
✓ — установлено, · — нет
|
||
⚠ submodule'ы не стянуты: jakubkrehel-skills
|
||
|
||
├─ jakubkrehel-skills не инициализирован
|
||
|
||
Итого: 0 скиллов, установлено 0
|
||
Стянуть: harness catalog init
|
||
```
|
||
|
||
Дальше — `harness catalog init`. Либо сразу клонировать с сабмодулями:
|
||
|
||
```bash
|
||
git clone --recurse-submodules git@git.itphx.loc:eka/harness.git
|
||
```
|
||
|
||
`catalog init` идемпотентен: если всё на месте, просто сообщит об этом.
|
||
`catalog update`, в отличие от него, двигает коммиты на актуальные upstream —
|
||
сначала стягивает недостающие, потом обновляет.
|
||
|
||
## `hermes` / `opencode` — сам агент
|
||
|
||
```bash
|
||
./scripts/harness hermes config # показать конфиг
|
||
./scripts/harness hermes config --set model.default=gpt-4o
|
||
./scripts/harness hermes config --set agent.max_turns=200
|
||
./scripts/harness hermes restart # systemctl --user restart hermes-gateway + webui
|
||
./scripts/harness hermes update # hermes update + рестарт сервисов
|
||
|
||
./scripts/harness opencode install # curl-установщик opencode.ai
|
||
./scripts/harness opencode restart # systemctl --user restart opencode + openchamber
|
||
```
|
||
|
||
`hermes config --set` меняет `~/.hermes/config.yaml` и перезапускает сервисы.
|
||
|
||
## Как добавить скилл в каталог
|
||
|
||
Каталог — это **git submodule'ы**: в репе фиксируется ссылка на внешний репозиторий
|
||
и точный коммит, а не копия файлов.
|
||
|
||
```bash
|
||
git submodule add https://github.com/user/skills-repo.git catalog/user-skills
|
||
git commit -m "chore: add user-skills to catalog"
|
||
```
|
||
|
||
После этого `harness skills list` покажет найденные скиллы, а
|
||
`harness catalog update` подтянет свежие коммиты во всех submodule'ах.
|
||
|
||
### Раскладка репозитория и ручная установка
|
||
|
||
CLI понимает одну раскладку — `<репа>/skills/<name>/SKILL.md`. Репозитории с другой
|
||
структурой (`SKILL.md` в корне, `.agents/skills/`, вложенные категории) он показывает
|
||
без списка скиллов, и такие скиллы ставятся вручную. Ограничение только у CLI: сам
|
||
OpenCode сканирует рекурсивно (`skills/**/SKILL.md`, а через `skills.paths` —
|
||
`**/SKILL.md` на любой глубине).
|
||
|
||
Пример — `developer-documentation-skill` держит `SKILL.md` в корне репы:
|
||
|
||
```bash
|
||
ln -s /mnt/data/Agent/dev/harness/catalog/developer-documentation-skill \
|
||
~/.agents/skills/developer-documentation
|
||
```
|
||
|
||
Альтернатива без симлинков — указать в конфиге OpenCode корень каталога:
|
||
|
||
```json
|
||
{ "skills": { "paths": ["/mnt/data/Agent/dev/harness/catalog"] } }
|
||
```
|
||
|
||
Тогда OpenCode найдёт все `SKILL.md` из каталога, в любой раскладке. Минус —
|
||
подхватывается всё содержимое разом, включая ненужное.
|
||
|
||
## Как добавить агента
|
||
|
||
Положить `.md` файл в `agents/` репозитория — и он сразу виден через `harness agents list`.
|
||
|
||
Формат — как у OpenCode:
|
||
|
||
```markdown
|
||
---
|
||
description: "Что делает агент и когда его звать"
|
||
mode: all # primary | subagent | all
|
||
temperature: 0.1
|
||
steps: 100
|
||
color: "#2563eb"
|
||
permission:
|
||
task: deny
|
||
bash: allow
|
||
edit: allow
|
||
---
|
||
|
||
# Имя агента
|
||
|
||
Тело промпта: роль, принципы, порядок работы, что НЕ делать, формат ответа.
|
||
```
|
||
|
||
- `mode: all` — можно и вызвать напрямую, и делегировать из `leader` (сабагент).
|
||
- `mode: primary` — только как основной агент (Tab в UI). Такой агент **не** появится
|
||
в `task`-инструменте лидера: OpenCode фильтрует список сабагентов по `mode !== "primary"`.
|
||
|
||
## Поддерживаемые форматы
|
||
|
||
- **Скиллы** — `SKILL.md` с YAML frontmatter (`name`, `description`); родной формат OpenCode и Hermes.
|
||
- **Агенты** — `<name>.md` с frontmatter (`description`, `mode`, ...); формат OpenCode.
|
||
|
||
## Совместимость
|
||
|
||
| Фича | Hermes | OpenCode |
|
||
|------|--------|----------|
|
||
| Skills (SKILL.md) | ✅ `~/.hermes/skills/` | ✅ `~/.claude/skills/`, `~/.config/opencode/skills/` |
|
||
| Agents | ❌ (только `delegate_task` в рантайме) | ✅ `~/.config/opencode/agents/`, `<project>/.opencode/agents/` |
|
||
| MCP-серверы | ✅ `config.yaml mcp_servers` | 🟡 через `opencode.json` |
|
||
| Plugins | ✅ `.hermes/plugins/` | ❌ (не поддерживает) |
|
||
| Systemd service | ✅ gateway + webui | ✅ opencode + openchamber |
|
||
| CLI install/update | `hermes update` | curl install script |
|