Your AI coding agent is only as reliable as the harness around it.
Measure that harness in seconds. Know exactly what to fix. Watch the number go up.
An AI coding agent is a model plus a harness β the context files, rules, skills, hooks, sensors, and guardrails wrapped around it. The model you rent; the harness you own. Two repositories can use the exact same model and get wildly different results, because one has a harness that catches mistakes before they ship and the other has none.
Harness Score measures that harness β across any tool. Point it at any repository using Cursor, Claude Code, Windsurf, Cline, Continue, or any other AI coding tool, and get a maturity level (L0βL4), a 108-point breakdown across six dimensions, and the precise, ranked list of what to fix next β with zero LLM calls, zero network access, and the same result every time you run it.
npx harness-score harness-score v1.0.0 ~/my-app
Maturity: L2 Β· Guided Score: 70/108 (65%)
Detected: Cursor, Claude Code
Context & Guides ββββββββββββββββββββ 80% 16/20 pts
Skills & Commands ββββββββββββββββββββ 65% 11/17 pts
Hooks & Guardrails ββββββββββββββββββββ 0% 0/14 pts
Sensors & Feedback ββββββββββββββββββββ 80% 16/20 pts
CI Feedback ββββββββββββββββββββ 71% 10/14 pts
Hygiene & Safety ββββββββββββββββββββ 74% 17/23 pts
To reach L3: sensors β₯ 60%; ci β₯ 50%
Not just a score β a diagnosis. Every failed check names the file, explains what's missing, and links to the exact recipe to fix it. Every check is a filesystem fact β a file exists, parses, matches a pattern β never a judgment call and never a network request. Same repository, same commit, same score, on your laptop or in CI, forever. That's what lets you gate a pipeline on it.
Vibe-coding without a harness works, right up until it doesn't: an agent that
rediscovers your conventions every session, rm -rfs something it shouldn't,
or ships code nobody reviewed because nothing was there to catch it. The
fix isn't "prompt better" β it's building the same kind of control system
around an AI agent that you'd build around any other autonomous system:
guides to steer it, sensors to check its work, and guardrails to
stop it before damage happens.
Most repositories have none of this and don't know it. Harness Score tells you exactly where you stand, in a language a CI pipeline (and a competitive teammate) understands: a number, a level, a badge.
Levels don't just add up points β they gate on the shape of your harness. 80 points of beautifully written docs with zero tests is not maturity; it's L1. Climbing the ladder means covering a new dimension at each step.
| Level | What it means | Priority to climb | |
|---|---|---|---|
| π± | L0 Β· Unharnessed | Agents rediscover the project every session. Mistakes ship unless a human happens to catch them. Most repositories start β and stay β here. | Write an AGENTS.md |
| π | L1 Β· Documented | A substantive AGENTS.md orients every session: what the project is, how to build and test it, what not to touch. The single highest-leverage step from zero. |
Add scoped rules + a skill |
| π§ | L2 Β· Guided | Guidance has real structure: scoped .cursor/rules/, at least one skill or command, basic hygiene (env files ignored, no leaked secrets). The harness ships with the code and is reviewed like code. |
Add a test runner, linter, types, CI |
| π¬ | L3 Β· Sensing | The feedback loop exists. Tests, a linter, type checking, and a CI pipeline re-verify every push. The agent can check its own work with deterministic tools β this is where AI-assisted development stops feeling risky. | Add gate + feedback hooks, pre-commit |
| π‘οΈ | L4 Β· Self-correcting | The loop closes at runtime. Gate hooks make destructive actions impossible, not just discouraged; feedback hooks lint and format inline. A mistake has to get past rules, hooks, tests, types, CI, and the gates β mostly without a human in the loop. | Keep it there β gate CI on --min-level 4 |
The scanner always tells you exactly which requirement blocks the next
level (To reach L3: sensors β₯ 60%; ci β₯ 50%) β the path up is never a
guess. Full maturity model, thresholds, and rationale:
the Maturity Model.
108 points, six dimensions, 36 checks β each one naming a concrete artifact, never "write better rules."
| Dimension | Points | What it measures |
|---|---|---|
| π Context & Guides | 20 | AGENTS.md substance, .cursor/rules/ scoping and frontmatter |
| π§© Skills & Commands | 17 | Packaged procedures β skills, slash commands, subagents, trigger-worthy descriptions |
| πͺ Hooks & Guardrails | 14 | Gate hooks (block risky actions) and feedback hooks (lint/format on edit) |
| β Sensors & Feedback | 20 | Test runner, linter, type checker, formatter, actual test files |
| βοΈ CI Feedback | 14 | Pipeline runs tests/lint/types on every push, pre-commit installed |
| π Hygiene & Safety | 23 | .gitignore, no leaked .env/secrets, license, lockfile, safe MCP config |
Full check catalog, with every remediation recipe: Measure & Improve.
Honesty about the limits of a deterministic scanner:
- Whether your tests are good β only that they exist, run, and gate.
- Whether your rules are true β a stale rule scores like a fresh one.
- Functional correctness β no static scan can verify behavior.
- Team practice β branch protection and review culture live outside the tree.
A high score means the infrastructure for reliable agent work exists. It's necessary, not sufficient β and that's the honest ceiling of what any deterministic scanner can claim.
As of v1.0.0, Harness Score follows semantic versioning with a concrete definition of what counts as public API:
- Check IDs (
CTX-01β¦HYG-08) are stable identifiers. A check's ID never changes meaning; removing or repurposing one is a major change. - The
ReportJSON shape β everything--jsonemits and the typed programmatic API exports β only gains fields in minor versions; removing or renaming a field is major. - CLI flags and exit codes (
0pass,1gate failure,2usage error) are stable; removals are major. - Maturity model evolution (new checks, point totals, level thresholds)
ships in minor versions β it changes what a repository scores, not
how you consume the tool.
--diffflags it explicitly viamaturityModelChanged, so baselines are never silently misread. - The determinism invariants β zero LLM calls, zero network access, zero runtime dependencies, same input β same output β are permanent commitments, not version-scoped promises.
| Piece | What | Where |
|---|---|---|
| π The Guide | Harness engineering for AI coding agents: guides (feedforward), sensors (feedback), guardrails, and the 5-level maturity model. Consolidates Martin Fowler's harness engineering articles, LangChain's harness lessons, and Cursor's own docs. | paladini.github.io/harness-score |
| π The CLI | npx harness-score β 36 checks across 6 dimensions, maturity level L0βL4, JSON/markdown/badge output, --diff mode, --min-level CI gate. Scores harnesses for Cursor, Claude Code, Windsurf, Cline, Continue, Codex, and other tools via OR semantics. Zero runtime dependencies, fully-typed programmatic API. |
packages/cli |
| π§© Editor/agent plugins | /harness-audit command + harness-engineering skill: audit the open workspace and let the agent fix the gaps following the guide's recipes. Cursor is the flagship; Claude Code and Windsurf support in progress (see PLUGINS-ROADMAP.md for the rest). |
plugins |
| βοΈ The GitHub Action | Run the scan on every push, gate on a minimum level, emit the badge. Multi-harness aware. | action |
Harness Score ships two branded SVG formats β free, self-contained, no shields.io subscription:
| Format | Shows | Best for |
|---|---|---|
Badge (harness-badge.svg or badge-l0βl4) |
harness Β· L4 |
README row (112Γ20) |
Share card (card-l0βl4) |
Full banner with level name | Social posts, repo hero |
The pill looks the same whether CI regenerates it or you pin a static file.
Auto-updating badge (recommended) β CI writes harness-badge.svg on every run:
# .github/workflows/harness.yml
- uses: paladini/harness-score@v1
with: { badge: 'harness-badge.svg' }
# publish harness-badge.svg to a badges branch or GitHub Pages, then:<img alt="Harness Score" src="https://raw.githubusercontent.com/<you>/<repo>/badges/harness-badge.svg" height="20">Pinned badge β same pill, static badge-lN.svg:
<img alt="Harness Score L3" src="https://paladini.github.io/harness-score/maturity/badge-l3.svg" height="20">All five badge levels:
Shareable banner cards for posts and docs (card-l0βcard-l4):
Full gallery, CI recipes, and copy-paste embeds (Markdown, HTML, iframe, JSX): Show your maturity β Β· Embed snippets β
No install needed β just run it:
npx harness-scoreOr install it, for repeated / offline / CI use:
npm install -g harness-score # global binary
npm install --save-dev harness-score # pinned in a repo's devDependenciesMirrored on other registries, in case npm is unreachable or you prefer a different ecosystem:
| Registry | Package | Install |
|---|---|---|
| npm | harness-score |
npm install -g harness-score |
| GitHub Packages | @paladini/harness-score |
npm install -g @paladini/harness-score --registry=https://npm.pkg.github.com |
| JSR (Deno/Bun) | @paladini/harness-score |
deno run npm:harness-score or npx jsr add @paladini/harness-score |
# score a repository
harness-score # or: npx harness-score
# machine-readable / markdown / badge
harness-score --json
harness-score --md report.md
harness-score --badge harness-badge.svg
# gate CI: fail below L3
harness-score --min-level 3Or in CI:
- uses: paladini/harness-score@v1
with:
min-level: '3'Some checks don't apply to every team for structural reasons β a policy
that forbids local hook scripts, for instance. .harness-score.json
(optional, at the repo root) supports two ESLint-style keys so a team can
say so without forking the model:
{
"extends": ["no-hooks"],
"rules": { "HYG-05": "off" }
}Excluded checks are removed from both sides of the score's fraction β never penalized, never silently hidden. Every exclusion shows up in the terminal, Markdown, and JSON output, and three checks that detect actively leaked credentials can never be excluded, from either a rule or a preset. Full story: Metrics & Codes β Team customization.
Starting from a typical L0 product repo, one focused session per level:
- β L1 (an afternoon). Write
AGENTS.md: what the project is, how to build/test it, what conventions hold. Include commands even if your sensors are weak β the agent will use them. - β L2 (a day). Three scoped
.cursor/rules/*.mdc+ one skill for your most repeated procedure. Fix hygiene: gitignore, env files, license. - β L3 (the real work, if sensors are missing). Test runner + linter + strict types + a CI workflow that runs all three. If you already have them, this level is free.
- β L4 (a morning). One gate hook + one feedback hook, committed with
their scripts, plus pre-commit β then
--min-level 4in CI so it never regresses.
Full recipes for every step: the guide.
The repository you are reading maintains L4 Β· Self-correcting on its own
scanner (npm run scan), and CI fails if it ever regresses. Its AGENTS.md,
.cursor/rules/, skills, commands, and hooks are live examples of everything
the guide teaches.
npm install
npm test # build + vitest (fixtures pin each maturity level)
npm run lint # biome
npm run scan # self-audit β must print L4
npm run docs:dev # guide dev server
npm run bench -w harness-score # scan-time benchmark against a synthetic large repoMonorepo layout, conventions, and the maturity-sync rule live in AGENTS.md β written for agents, useful for humans.
Issues and pull requests are welcome β new checks, new language/tool recognition (a linter or test runner the scanner doesn't know about yet), docs fixes, bug reports against real-world repositories. Proposing a new check or a check change? Use the Check change issue template β it's the highest-value contribution and the one most likely to need agreement up front, since it changes what every existing repository scores. See CONTRIBUTING.md for the full workflow and CODE_OF_CONDUCT.md for how we expect people to treat each other. Security issues: see SECURITY.md instead of filing a public issue.
What's next lives in ROADMAP.md: a harness-score init
scaffold command that turns the diagnostic into a fixer, SARIF output for
GitHub code-scanning integration, larger real-world corpus analyses to keep
calibrating the maturity model, and first-class plugins for more tools
beyond Cursor and Claude Code (PLUGINS-ROADMAP.md).
MIT Β© 2026 Fernando Paladini