Перейти до змісту

Під свій проєкт

ЦільПідключити harness до свого репозиторію і налаштувати під свій стек.

Підключи свій репозиторій

harness projects add ~/code/my-app --name my-app
harness projects list

Add a project на сторінці Projects у дашборді робить те саме. projects add реєструє репозиторій у $HARNESS_HOME/projects.json, за замовчуванням ~/.harness/projects.json. У твоєму репозиторії з'являється:

ШляхЩо цеУ git
.harness/config.jsonналаштування проєктутак, версіонується
.harness/tasks/один Markdown-файл на задачуні
.harness/trace/докази, які лишає кожен юнітні
.harness/JOURNAL.mdнотатки, які агенти лишають наступному юнітуні

Ці шляхи, а також .harness/artifacts/ і .env, дописуються в .gitignore проєкту. Тека вважається проєктом harness, лише коли в ній є .harness/config.json. harness projects remove <id|name> знімає проєкт з реєстру і ніколи не видаляє файлів.

Далі створи першу задачу: harness new --title "…" --project my-app або New task у дашборді.

config.json

projects add пише лише ключі, які ти, найімовірніше, зміниш:

{
  "baseBranch": "main",
  "autonomy": {
    "mode": "gated"
  },
  "limits": {
    "bounces": 2,
    "prototypeRounds": 3,
    "unitTimeoutMinutes": 60
  },
  "gate": null,
  "probe": null,
  "deliver": {
    "pr": false,
    "remote": "origin"
  }
}

Решта ключів лишається стандартною в коді, тож змінене значення за замовчуванням доходить до кожного проєкту.

КлючЗа замовчуваннямЩо робитьДетальніше
baseBranchmainгілка, від якої стартує кожна гілка задачіЖиття задачі
autonomy.modegatedgated: план і прототип чекають на тебе; full: рухаються далі саміЖиття задачі
limits.bounces2скільки відмов паркує задачу для тебеКонтракти
limits.prototypeRounds3найбільша кількість раундів прототипу на задачуЖиття задачі
limits.unitTimeoutMinutes60юніт, що триває довше, — жорстка зупинкаКонтракти
gatenullкоманда перевірки проєкту; власний gate: задачі має пріоритетКонтракти
probenullкоманда, яка має завершитися з кодом 0 до старту юнітаКонтракти
deliver.pr, deliver.remotefalse, originпушити гілку і відкривати pull request для готової задачіЖиття задачі

Ключі, які можна додати, коли знадобляться:

КлючЗа замовчуваннямЩо робитьДетальніше
roles.modelsкоординатори sonnet, суддя opusмодель для кожної ролі; суддя має відрізнятися від implementer і testerРолі
roles.mergeQaJudgefalseодин юніт рев'ю на задачу замість двохРолі
notify.eventsусі сімякі події надсилати в TelegramКерування циклом
agent.commandnullкоманда, що підміняє claude, як AGENT_CMD
agent.permissionModedontAskclaude --permission-mode: відмовляти в недозволеному замість чекати
agent.allowedToolsсписокclaude --allowedTools; read-only grep, cat, head, tail і wc, а також sleep, там є; комітів і пушів немає навмисно
agent.settingSourcesproject,localclaude --setting-sources: твої особисті хуки не спрацьовують у циклі
supervisor.*у кодіінтервали опитування й очікування, а також barrenUnits: 3Керування циклом
appnullзапускати застосунок проєкту і браузер для юнітів qa і prototype, описано нижче

Твій застосунок для qa і prototype

Задай app, коли юніт має бачити твій проєкт запущеним. Застосунок запускає runner, а не агент:

"app": { "start": "pnpm exec next dev -p {port}" }
КлючЗа замовчуваннямЩо робить
app.startобов'язковийкоманда, що запускає застосунок; без {port} конфіг відхиляється (код 2)
app.ready"/"шлях, який runner опитує, доки застосунок не відповість
app.timeoutSeconds60скільки runner чекає на цю відповідь
app.host"localhost"хост в адресі, яку отримують юніти; dev-сервер Next 16 віддає свій сокет живого перезавантаження лише на localhost, тож сторінка на 127.0.0.1 ніколи не гідрується
app.stages["qa", "prototype"]етапи юнітів, які отримують застосунок і браузер
app.browser"@playwright/mcp@0.0.83"пакет Playwright MCP, через який браузер працює з npx, закріплена версія

Проєкт-приклад задає "app": { "start": "pnpm exec next dev -p {port}", "ready": "/" }, тож його юніти qa і prototype отримують застосунок на http://localhost:<port>.

Перед кожним юнітом цих етапів runner бере вільний порт, запускає команду в окремій групі процесів і чекає на застосунок. Юніт отримує адресу в HARNESS_APP_URL і рядком у ## This run, який також каже агенту не запускати й не зупиняти сервер. Після юніта, хоч би чим він закінчився, runner зупиняє саме цю групу процесів. Якщо застосунок не стартував, Log задачі пише чому, і юніт працює без нього. Запуск також зупиняє застосунок, чий runner помер, і пише про це в лог.

Runner запускає застосунок до того, як зафіксує дерево для контракту scope, тож файли, які сервер пише на старті, — не юнітові. Ще він прибирає з оточення застосунку маркери AI-агента: Next.js 16.4 пише AGENTS.md у проєкт, коли бачить агента, і такий зайвий файл запаркував би read-only юніт. Так само зникають NODE_ENV і внутрішні змінні Next (__NEXT_*, NEXT_PRIVATE_*, NEXT_RUNTIME, NEXT_DEPLOYMENT_ID, TURBOPACK*), тож застосунок, запущений supervisor-ом із дашборду, працює як звичайний next dev. Відстежуваний файл, який застосунок переписав за роботи, після зупинки повертається з git, і Log задачі його називає.

Браузер

Юніт етапу з app.stages отримує ще й браузер, але лише коли його застосунок стартував: нема застосунку — нема браузера. Жоден інший юніт не отримує MCP-сервера взагалі. Runner пише .harness/trace/unit-NNNN.mcp.json і передає його через --mcp-config … --strict-mcp-config, додає в allowlist mcp__playwright, що дозволяє всі інструменти цього одного сервера, і задає HARNESS_MCP_CONFIG. Сервер запускається як npx -y <app.browser> --headless --isolated --browser chrome, тож npx має бути в PATH: harness agents --check попереджає, коли його немає, а код виходу не змінюється. harness preview показує ці прапорці для етапу із застосунком.

Координатор етапу передає адресу застосунку своєму спеціалісту, бо спеціаліст бачить лише свій промпт виклику. Спеціаліст, який перелічує свої інструменти, отримує mcp__playwright у JSON --agents; суддя — ніколи.

Playwright MCP зберігає названий скриншот у корені проєкту, а не в теці артефактів. Після юніта з браузером runner переносить нові невідстежувані файли png, jpg і webp з кореня проєкту в .harness/artifacts/T-NNN/ і записує кожен у Log задачі. Юніт без браузера все одно паркується через такий файл як через stray file.

Свій спеціаліст

Спеціаліст — це один Markdown-файл. Поклади його в <project>/.claude/agents/. Harness зливає цю теку зі своїми базовими агентами, а файл з іменем базового агента підміняє його.

---
name: a11y-reviewer
description: Checks every changed screen for keyboard access and contrast, and reports what fails.
model: sonnet
tools: Read, Grep, Glob
stages: [qa]
when: in the qa stage of a `kind: ui` task
---

You review accessibility. You change nothing.
ПолеЩо означає
nameім'я агента; якщо його немає, береться ім'я файлу
descriptionобов'язкове: один рядок, за яким координатор вирішує, чи викликати агента
modelйого модель; roles.models.<name> її перевизначає
toolsінструменти, якими він може користуватися
stagesетапи, що його пропонують; без stages його пропонує кожен етап
whenпідказка координатору: в яких задачах його викликати

Потім додай у файл постійні правила і перевір реєстр:

harness agents --sync --project my-app
harness agents --check --project my-app

Координатор кожного етапу читає запропонованих спеціалістів і викликає тих, які потрібні задачі.

Змінні оточення

ЗміннаЩо змінює
HARNESS_HOMEде лежать реєстр проєктів і запасний .env; за замовчуванням ~/.harness
HARNESS_AGENTS_DIRтека базових агентів; за замовчуванням agents/ у harness-demo
AGENT_CMDкоманда, що підміняє claude для кожного юніта; нею користується fake agent
HARNESS_GHкоманда, що підміняє gh для доставки
TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_IDсповіщення в Telegram, описані в Керуванні циклом

Перед першим справжнім запуском

  1. Базова гілка чиста й актуальна. Supervisor відмовляється працювати на брудному дереві, яке забруднив не він.
  2. Гейт проходить, коли ти запускаєш його команду вручну.
  3. harness agents --check закінчується на ok.
  4. harness preview T-NNN показує той промпт, якого ти чекаєш.
  5. Перший запуск короткий: з --once-through або --max-units <n>, і з відкритим дашбордом.
ДаліУроки→
Гайд10 розділів · ~55 хвилин
  1. 1Поняття
  2. 2Ролі
  3. 3Координація
  4. 4Життя задачі
  5. 5Керування циклом
  6. 6Контракти
  7. 7Дашборд
  8. 8Швидкий старт
  9. 9Під свій проєктти тут
  10. 10Уроки
ОглядДемоПрикладGitHub