install — scaffold harness governance into the current project
Installing the plugin from the marketplace enforces nothing by itself. This skill makes
governance ambient and deterministic by writing project-owned files (option A: the
project owns and edits its copies; the plugin never manages them afterward).
Process
The SKILL owns judgment and dialogue; the deterministic file work — gate write, hook copy +
.claude/settings.json merge, standalone embedding, .gitignore — is delegated to
install.mjs so the fiddly, error-prone parts run identically every time. Everything is
idempotent and non-destructive: existing files are never overwritten.
Gather confirmed inputs first (judgment — before running anything).
- Gate patterns: inspect the project (languages, source roots) and propose patterns
(Kotlin
"src/.*\\.kt$", TS "src/.*\\.tsx?$", …); confirm with the user. If
.claude/harness-gate.json already exists, install.mjs keeps it — just report its
patterns.
- Standalone embedding — ASK: "플러그인 없이도 하네스가 돌게 임베드할까요? (에어갭/CI용,
용량↑·drift 관리 필요)". Default No.
- The hook is self-contained, but the engine, Codex CLI adapter/runner, and the skills it invokes live in the
plugin. Without embedding, a plugin-less project's gate blocks with no local way to
satisfy it — say so.
- If Yes: locate the source dirs of the skills the engine statically mounts —
agents:agent-task-decomposer (Planner), think:devils-advocate (critic + judges),
and completion:verification-before-completion (tester) — and pass them as {name, src}.
Offer to add a broader skill set the project expects to use.
- Hard caveat, say it out loud: subgoal
skills[] are chosen dynamically by
SetGoal from the whole catalogue and can't be pre-enumerated; embedding guarantees
only what you pass. MCP tools (sequential-thinking, think-tool, mcp-reasoner) can't be
embedded at all.
Run install.mjs with the confirmed values (gate + hook + embedding + gitignore — all
deterministic, idempotent, non-destructive):
node "<plugin>/skills/install/install.mjs" '{
"projectDir": "<abs project root>",
"gate": { "patterns": ["src/.*\\.kt$"], "window_hours": 2 },
"embed": { "runtime": true, "skills": [
{ "name": "agent-task-decomposer", "src": "<abs>/agents/skills/agent-task-decomposer" },
{ "name": "devils-advocate", "src": "<abs>/think/skills/devils-advocate" },
{ "name": "verification-before-completion", "src": "<abs>/completion/skills/verification-before-completion" } ] }
}'
Omit gate to skip the gate write; omit embed to skip embedding. It always installs
the hook (.claude/hooks/goal-gate.mjs + a merged .claude/settings.json PreToolUse entry
— never clobbering existing hooks; an unparseable settings.json is left untouched) and the
.gitignore line. Read the JSON report it prints (per-action created/kept/already
/parse-error) — that is the source of truth for step 5.
Conventions — .claude/conventions/ (judgment, agent-run):
- Copy each
templates/conventions/{coding,verification,boundaries}.md only if missing
(do not dedupe topics the user already covers under other names).
- Optional rulesets (
templates/conventions/optional/): copy only when the project
matches the trigger at the top of each — security.md, data.md, operations.md. Ask
when unsure; skip silently when irrelevant.
- Fill the
<!-- fill --> placeholders you can derive; name the ones left for the user.
CLAUDE.md — ambient instruction (judgment, agent-run):
- Block in
templates/claude-md-section.md, fenced by <!-- harness:begin --> /
<!-- harness:end -->. Missing file → create with just the block. Markers present →
leave untouched, never duplicate. Exists without markers → append; if existing content
contradicts it (e.g. "never use hooks/subagents"), do NOT append — surface the conflict.
- If you embedded (step 1), rewrite the Workflow
scriptPath in the block to
.claude/harness/engine/pipeline.js and codex_adapter_path to
.claude/harness/engine/codex-exec-adapter.mjs (the gate's engagement regex still
matches the harness/engine/pipeline.js substring).
Report — from install.mjs's JSON plus the convention/CLAUDE.md steps: list created /
kept / needs-user-input. Remind: the gate only blocks Write|Edit|MultiEdit|NotebookEdit
on the listed patterns and is fail-open. If embedding was declined and the plugin is
absent, flag the engine gap; if accepted, list what was embedded and the dynamic-skills[]
boundary.
Updating after a plugin version bump
install.mjs is non-destructive by default — a plain re-run reports every existing file
as kept and changes nothing, so it will NOT pull a newer engine/hook on its own. The files
split into two classes:
- plugin-owned copies (verbatim of a plugin file):
.claude/hooks/goal-gate.mjs and, if
embedded, .claude/harness/** (engine, Codex adapter/runner, meta-skeleton, goal-spec, static skills). These
drift from the plugin on a version bump.
- user-owned (the project evolves them):
harness-gate.json, conventions/**, the
CLAUDE.md block, settings.json.
To update: bump the plugin (marketplace), then re-run install.mjs with "refresh": true
and the same embed config. It re-copies only the plugin-owned files (reported refreshed
or unchanged) and never touches user-owned files even with refresh on. Then git diff the
plugin-owned copies and commit. In plugin mode (no embedding) the only drift-prone file is
goal-gate.mjs; in embedded mode it also refreshes .claude/harness/**.
What Claude does
- Proposes gate patterns, asks about embedding + resolves skill sources, runs
install.mjs
for every deterministic file op, then does conventions + the CLAUDE.md block (judgment), and
reports honestly from the script's JSON (incl. the plugin-engine gap / dynamic-skill boundary).
What you do
- Confirm the gate patterns and the embedding choice. Commit
.claude/settings.json,
.claude/hooks/goal-gate.mjs, any .claude/harness/ copies, and the conventions so the
gate applies team-wide. Fill remaining placeholders. Own the copies afterward — after a
plugin version bump, re-run with "refresh": true to pull the newer plugin-owned files
(see "Updating after a plugin version bump"); your gate/conventions/CLAUDE.md stay put.
Related
install.mjs — deterministic file ops (gate/hook/embed/gitignore) this skill invokes
harness skill — running the six-stage engine
remove skill — uninstalling project-local harness governance
patch skill — preparing a synchronized source patch release
hooks/README.md — gate semantics and accepted holes
1---2name: install-33description: Use when installing the harness into a project. Triggers on: "하네스 설치해줘", "이 프로젝트에 하네스 적용해줘", "harness install", "set up the harness here", "게이트 켜줘", "convention 스캐폴딩해줘". Not for running the engine (use the harness skill).4---56# install — scaffold harness governance into the current project78Installing the plugin from the marketplace enforces nothing by itself. This skill makes9governance **ambient and deterministic** by writing project-owned files (option A: the10project owns and edits its copies; the plugin never manages them afterward).1112## Process1314The SKILL owns judgment and dialogue; the deterministic file work — gate write, hook copy +15`.claude/settings.json` merge, standalone embedding, `.gitignore` — is delegated to16`install.mjs` so the fiddly, error-prone parts run identically every time. Everything is17idempotent and non-destructive: existing files are never overwritten.18191. **Gather confirmed inputs first (judgment — before running anything).**20 - **Gate patterns:** inspect the project (languages, source roots) and propose patterns21 (Kotlin `"src/.*\\.kt$"`, TS `"src/.*\\.tsx?$"`, …); confirm with the user. If22 `.claude/harness-gate.json` already exists, `install.mjs` keeps it — just report its23 patterns.24 - **Standalone embedding — ASK:** "플러그인 없이도 하네스가 돌게 임베드할까요? (에어갭/CI용,25 용량↑·drift 관리 필요)". Default **No**.26 - The hook is self-contained, but the **engine, Codex CLI adapter/runner, and the skills it invokes live in the27 plugin**. Without embedding, a plugin-less project's gate blocks with no local way to28 satisfy it — say so.29 - If **Yes**: locate the source dirs of the skills the engine **statically** mounts —30 `agents:agent-task-decomposer` (Planner), `think:devils-advocate` (critic + judges),31 and `completion:verification-before-completion` (tester) — and pass them as `{name, src}`.32 Offer to add a broader skill set the project expects to use.33 - **Hard caveat, say it out loud:** subgoal `skills[]` are chosen **dynamically by34 SetGoal from the whole catalogue** and can't be pre-enumerated; embedding guarantees35 only what you pass. MCP tools (sequential-thinking, think-tool, mcp-reasoner) can't be36 embedded at all.37382. **Run `install.mjs` with the confirmed values** (gate + hook + embedding + gitignore — all39 deterministic, idempotent, non-destructive):40 ```41 node "<plugin>/skills/install/install.mjs" '{42 "projectDir": "<abs project root>",43 "gate": { "patterns": ["src/.*\\.kt$"], "window_hours": 2 },44 "embed": { "runtime": true, "skills": [45 { "name": "agent-task-decomposer", "src": "<abs>/agents/skills/agent-task-decomposer" },46 { "name": "devils-advocate", "src": "<abs>/think/skills/devils-advocate" },47 { "name": "verification-before-completion", "src": "<abs>/completion/skills/verification-before-completion" } ] }48 }'49 ```50 Omit `gate` to skip the gate write; omit `embed` to skip embedding. It **always** installs51 the hook (`.claude/hooks/goal-gate.mjs` + a merged `.claude/settings.json` PreToolUse entry52 — never clobbering existing hooks; an unparseable settings.json is left untouched) and the53 `.gitignore` line. **Read the JSON report it prints** (per-action `created`/`kept`/`already`54 /`parse-error`) — that is the source of truth for step 5.55563. **Conventions — `.claude/conventions/`** (judgment, agent-run):57 - Copy each `templates/conventions/{coding,verification,boundaries}.md` **only if missing**58 (do not dedupe topics the user already covers under other names).59 - **Optional rulesets** (`templates/conventions/optional/`): copy only when the project60 matches the trigger at the top of each — `security.md`, `data.md`, `operations.md`. Ask61 when unsure; skip silently when irrelevant.62 - Fill the `<!-- fill -->` placeholders you can derive; name the ones left for the user.63644. **CLAUDE.md — ambient instruction** (judgment, agent-run):65 - Block in `templates/claude-md-section.md`, fenced by `<!-- harness:begin -->` /66 `<!-- harness:end -->`. Missing file → create with just the block. Markers present →67 leave untouched, never duplicate. Exists without markers → append; if existing content68 contradicts it (e.g. "never use hooks/subagents"), do NOT append — surface the conflict.69 - **If you embedded** (step 1), rewrite the Workflow `scriptPath` in the block to70 `.claude/harness/engine/pipeline.js` and `codex_adapter_path` to71 `.claude/harness/engine/codex-exec-adapter.mjs` (the gate's engagement regex still72 matches the `harness/engine/pipeline.js` substring).73745. **Report** — from `install.mjs`'s JSON plus the convention/CLAUDE.md steps: list created /75 kept / needs-user-input. Remind: the gate only blocks `Write|Edit|MultiEdit|NotebookEdit`76 on the listed patterns and is fail-open. If embedding was declined and the plugin is77 absent, flag the engine gap; if accepted, list what was embedded and the dynamic-`skills[]`78 boundary.7980## Updating after a plugin version bump8182`install.mjs` is **non-destructive by default** — a plain re-run reports every existing file83as `kept` and changes nothing, so it will NOT pull a newer engine/hook on its own. The files84split into two classes:85- **plugin-owned copies** (verbatim of a plugin file): `.claude/hooks/goal-gate.mjs` and, if86 embedded, `.claude/harness/**` (engine, Codex adapter/runner, meta-skeleton, goal-spec, static skills). These87 drift from the plugin on a version bump.88- **user-owned** (the project evolves them): `harness-gate.json`, `conventions/**`, the89 CLAUDE.md block, `settings.json`.9091To update: bump the plugin (marketplace), then re-run `install.mjs` with **`"refresh": true`**92and the same `embed` config. It re-copies only the plugin-owned files (reported `refreshed`93or `unchanged`) and never touches user-owned files even with refresh on. Then `git diff` the94plugin-owned copies and commit. In **plugin mode** (no embedding) the only drift-prone file is95`goal-gate.mjs`; in **embedded mode** it also refreshes `.claude/harness/**`.9697## What Claude does98- Proposes gate patterns, asks about embedding + resolves skill sources, runs `install.mjs`99 for every deterministic file op, then does conventions + the CLAUDE.md block (judgment), and100 reports honestly from the script's JSON (incl. the plugin-engine gap / dynamic-skill boundary).101102## What you do103- Confirm the gate patterns and the embedding choice. Commit `.claude/settings.json`,104 `.claude/hooks/goal-gate.mjs`, any `.claude/harness/` copies, and the conventions so the105 gate applies team-wide. Fill remaining placeholders. Own the copies afterward — after a106 plugin version bump, re-run with `"refresh": true` to pull the newer plugin-owned files107 (see "Updating after a plugin version bump"); your gate/conventions/CLAUDE.md stay put.108109## Related110- `install.mjs` — deterministic file ops (gate/hook/embed/gitignore) this skill invokes111- `harness` skill — running the six-stage engine112- `remove` skill — uninstalling project-local harness governance113- `patch` skill — preparing a synchronized source patch release114- `hooks/README.md` — gate semantics and accepted holes