From harness-engineering
Deterministic architecture enforcement across languages: go-arch-lint YAML rules for Go, dependency-cruiser or @softarc/sheriff for TypeScript, depguard inside golangci-lint, Factory.ai's 4-category framework (grep-ability, glob-ability, architecture boundaries, security). Use when designing layering for a new service, enforcing Clean Architecture, blocking forbidden imports, or setting up custom analyzers. Do NOT use for runtime design patterns (use architecture-advisor for that).
npx claudepluginhub toru-oizumi/claude-harness-engineering --plugin harness-engineeringThis skill uses the workspace's default tool permissions.
Make architectural constraints mechanically checkable. If a human has to review every PR to catch layer violations, the rule isn't real.
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.
Make architectural constraints mechanically checkable. If a human has to review every PR to catch layer violations, the rule isn't real.
| Category | Example | Enforcement |
|---|---|---|
| Grep-ability | "All SQL queries go through db/queries/" | Custom grep analyzer in golangci-lint / ESLint no-restricted-imports |
| Glob-ability | "No test code outside *_test.go" | File pattern rules in dependency-cruiser / go-arch-lint |
| Architecture boundaries | "Domain doesn't import infrastructure" | go-arch-lint / dependency-cruiser / sheriff |
| Security | "No exec.Command outside cmd/" | gosec / ESLint security plugin / depguard |
A rule that fits in one of these four categories can be enforced. Rules that don't (e.g., "use idiomatic error handling") must be handled by human review or LLM review.
The canonical tool. Declarative YAML, component-based, allow/deny lists.
Full Clean Architecture example is at ${CLAUDE_PLUGIN_ROOT}/templates/.go-arch-lint.clean-arch.yml.
Key directives:
components — define named groups of packages via globdeps.<component>.allow — explicit allowlist of components this one may importdeps.<component>.mayDependOn — same, alternative nameexcludeFiles — files to skip (generated, mocks, tests)Running it: go-arch-lint check — exits non-zero on violations. The post-edit-lint.js hook runs this after every .go file edit.
For forbidden imports that aren't about layering:
linters-settings:
depguard:
rules:
main:
deny:
- pkg: "github.com/pkg/errors"
desc: "use standard errors + fmt.Errorf with %w instead"
- pkg: "io/ioutil"
desc: "deprecated; use os and io"
- pkg: "math/rand"
desc: "use crypto/rand for anything security-related"
Framework-agnostic. Regex path matching. Best for existing codebases with flexible layering.
// .dependency-cruiser.js
module.exports = {
forbidden: [
{
name: 'no-circular',
severity: 'error',
from: {},
to: { circular: true },
},
{
name: 'domain-pure',
severity: 'error',
from: { path: '^src/domain' },
to: { path: '^src/(infrastructure|interfaces|application)' },
},
{
name: 'no-deprecated',
severity: 'error',
from: {},
to: { dependencyTypes: ['deprecated'] },
},
],
};
Tag-based, ESLint plugin, enforces a module graph.
// sheriff.config.ts
export const config = {
tagging: {
'src/domain': ['domain'],
'src/application': ['application'],
'src/infrastructure': ['infrastructure'],
},
depRules: {
domain: [], // pure
application: ['domain'],
infrastructure: ['domain', 'application'],
},
};
Sheriff runs inside ESLint (so you need ESLint in the project). dependency-cruiser runs standalone (lighter).
For rules that don't fit the above tools, write a custom go/analysis analyzer or an ESLint rule. Keep them small — one rule per analyzer.
Example use cases:
ctx := r.Context() as the first line"cache.Key(...)"These live in a tools/lint/ directory in the target repo, not in this plugin.
The /harness:lint-all command runs all enforcement passes sequentially:
# Go
gofumpt -l .
golangci-lint run
go-arch-lint check
gosec ./...
# TypeScript
biome check .
oxlint
tsc --noEmit
depcruise src
knip
# Proto
buf format --diff
buf lint
buf breaking --against .git#branch=main
severity: warn for a week, then upgrade to error. You'll find false positives you didn't anticipate.allow-until annotation. Use them — don't block a merge over a preexisting issue..go-arch-lint.yml is the single source of truth for "how this codebase is supposed to be structured". Write it first, implement later.go-stack, ts-stack, proto-stack — language-specific harness detailconfig-protect — why you can't edit these configs as an agentpr-review-multi-model — the LLM-based review that catches non-deterministic issuesSee gotchas.md.