From harness-engineering
Explains the config protection policy enforced by the pre-config-protect hook. Covers which files are write-protected, why, and what to do when the agent (or you) hits a blocked edit. Use when the user asks 'why can't Claude edit biome.json?', 'how do I disable the config guard?', or when a PreToolUse block message appears. Do NOT use for adding new protected patterns — that's a hook-utils.js code change.
npx claudepluginhub toru-oizumi/claude-harness-engineering --plugin harness-engineeringThis skill uses the workspace's default tool permissions.
The harness blocks Write/Edit/MultiEdit on linter and architecture config files. This is intentional and non-negotiable.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
The harness blocks Write/Edit/MultiEdit on linter and architecture config files. This is intentional and non-negotiable.
When an agent hits a lint violation, its instinct is often to "fix" the lint by editing the linter config — disabling the rule, adding a file to the ignore list, downgrading severity. This is not a fix. It hides the problem and erodes the harness.
The only correct responses to a lint violation are:
Config protection makes option 1 the only option available to the agent. Option 2 requires going through a human, which is exactly what we want.
See hooks/hook-utils.js → PROTECTED_CONFIG_BASENAMES for the canonical list. Summary:
| Stack | Files |
|---|---|
| TypeScript | biome.json, biome.jsonc, .oxlintrc.json, tsconfig*.json, .eslintrc*, eslint.config.*, .prettierrc*, prettier.config.*, .dependency-cruiser.* |
| Go | .golangci.yml, .golangci.yaml, .go-arch-lint.yml, gosec.yaml |
| Proto | buf.yaml, buf.gen.yaml, .protolint.yaml |
| Cross-cutting | lefthook.yml, .pre-commit-config.yaml |
| Claude Code | .claude/settings.json, .claude/settings.local.json, .claude/review-profile.yaml |
The hook exits with code 2 and writes a clear message to stderr. Claude Code displays this to the agent as a blocked tool call. The agent sees:
harness-engineering: BLOCKED edit on protected config file: biome.json
This file is part of the project's harness (linter / architecture / CI config).
Agents cannot modify it, because silencing a linter is NOT the fix — fixing
the code is.
If the linter rule itself is genuinely wrong, ask the human to edit the config manually.
If you hit a lint violation, fix the code to satisfy the existing rule.
You (the human) can edit any of these files directly — the hook only blocks Claude's tool calls, not your hands on the keyboard. Open the file in your editor, make the change, save. Done.
If you want to temporarily disable the entire hook:
# Stop Claude Code, then:
mv ~/.claude/plugins/harness-engineering/hooks/pre-config-protect.js \
~/.claude/plugins/harness-engineering/hooks/pre-config-protect.js.disabled
# Restart Claude Code
Re-enable by moving it back.
Edit hooks/hook-utils.js → PROTECTED_CONFIG_BASENAMES set. Add the basename. Reinstall/reload the plugin. (Yes, this file itself is editable — meta-protection would be too much.)
edit-lint-feedback-loop — the other half of the harness (feedback instead of blocking)harness-setup — initial installationSee gotchas.md.