harness-eval
A linter for AI code agent setups, not for code. It auto-detects which AI tools a project uses (Claude Code, Cursor, Windsurf, Cline, Copilot, Gemini CLI, OpenCode), builds a component graph across all of them, and runs 84 deterministic rules to catch issues that per-file linters miss: credential exfiltration chains, confused deputy attacks, skill/hook conflicts, and token budget blowouts.
Most tools test whether a skill produces correct output. This one checks the setup itself: CLAUDE.md, GEMINI.md, AGENTS.md, skills, commands, hooks, MCP configs, agents, .cursor/rules/*.mdc, .cursorrules, .github/prompts/, .opencode/.
Quick start
pip install harness-eval
harness-eval lint . # 84 deterministic rules, fully offline
harness-eval security . # security scan (18 rules)
See docs/INSTALL.md for all installation options and configuration.
How to use it
Available as a CLI tool, a GitHub Action, a Tekton Task (OpenShift Pipelines), a Claude Code plugin, and Cursor commands. Each is documented in docs/INSTALL.md.
| Command | What it does | LLM needed? |
|---|---|---|
lint |
84 deterministic rules + system analysis (token budget, trigger overlaps, dependencies). Fast, CI-suitable. Supports --format sarif. |
No |
review |
Per-component rubric review with scoring, 21 cross-type checks, KEEP/REVIEW/REMOVE verdicts. | CLI: [llm] extra. Plugin/Cursor: in-session. |
security |
All security rules + YARA + CVE lookups + optional semantic review. SAFE/CAUTION/UNSAFE. | Scan: no. --review: [llm] extra or in-session. |
skill |
Deep-evaluate one skill individually and in context of the full setup. | Lint: no. --rubric: [llm] extra or in-session. |
rules |
List all rules. Filter by --category or --target. |
No |
Cross-component analysis
This is the core differentiator. Most linters check files in isolation. harness-eval builds a component graph that traces data flows across skills, agents, hooks, and MCP servers, then runs cross-component rules against it. This catches classes of issues that per-file analysis cannot:
- A hook reads credentials from env, passes them to a skill, which forwards them to an MCP server with broad network access
- A command's
allowed_toolslist doesn't cover the tools its instructions actually use - Settings.json
permissions.denyblocks a tool that CLAUDE.md instructs the agent to use - Two assistants' instruction files (CLAUDE.md and GEMINI.md) have drifted apart
- A skill is defined but never referenced from any instruction file (orphan)
Multi-tool projects are fully supported. When a project uses both Claude Code and Cursor, all components are evaluated together.
Supported AI tools
| Assistant | What it discovers |
|---|---|
| Claude Code | CLAUDE.md, skills/, commands/, .claude/agents/, .claude/settings.json, .mcp.json |
| Cursor | .cursor/rules/*.mdc, .cursorrules, .cursor/commands/, .cursor/skills/, .cursor/hooks.json, .cursor/mcp.json |
| Windsurf | .windsurfrules, .windsurf/rules/*.md |
| Cline | .clinerules (file or directory of *.md) |
| Copilot | .github/copilot-instructions.md, .github/skills/, .github/prompts/, .github/agents/ |
| Gemini CLI | GEMINI.md, .gemini/commands/, .gemini/settings.json (MCP) |
| OpenCode | AGENTS.md, .opencode/commands/, .opencode/agents/, opencode.json (MCP) |
| Third-party modules | .lola/modules/ (skills, commands, agents installed via package managers) |
Inspection rules
84 deterministic rules across 11 categories: structural, frontmatter, content, quality, security, cross-component, commands, CLAUDE.md, MCP, hooks, and agents. Four presets: recommended (default), strict, security, pre-workflow.
For the complete rule list with examples, detection techniques, and framework mappings (OWASP, MITRE ATLAS), see docs/rules-reference.md.
Privacy
lint and security (without --review) are fully offline. LLM review is opt-in:
only review, security --review, and skill --rubric send snippets to a remote
provider (Gemini or Anthropic via CLI, or in-session as a plugin/command).
Before any remote LLM call, likely secrets (tokens, PEM keys, API_KEY= assignments,
known prefix patterns) are replaced with [REDACTED] (HE-2). Scans also skip .env,
credentials paths, and *.pem / *.key / id_rsa globs by default (HE-3); add
more with --exclude.
See docs/how-can-you-know-its-safe-to-use-this-tool.md for details.
Contributing
See CONTRIBUTING.md for adding rules and submitting PRs.
Changelog
See CHANGELOG.md for release history.
Roadmap
See open issues for planned improvements and feature requests.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file harness_eval-7.3.0.tar.gz.
File metadata
- Download URL: harness_eval-7.3.0.tar.gz
- Upload date:
- Size: 256.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
44ae273c6d7203641923a6e00926fef417af2c202d9881b3226eb5a0fc724b54
|
|
| MD5 |
0790cb34765c2925566a8f3b6b9d9140
|
|
| BLAKE2b-256 |
cfbbc77e6324800afe180f9f486dfbca6a38c3d0a3866fde96006401ab081497
|
Provenance
The following attestation bundles were made for harness_eval-7.3.0.tar.gz:
Publisher:
publish.yml on redhat-community-ai-tools/harness-eval
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
harness_eval-7.3.0.tar.gz -
Subject digest:
44ae273c6d7203641923a6e00926fef417af2c202d9881b3226eb5a0fc724b54 - Sigstore transparency entry: 2398398053
- Sigstore integration time:
-
Permalink:
redhat-community-ai-tools/harness-eval@da51091e1d4d348bed3da7e0e827ce5a691aceb1 -
Branch / Tag:
refs/tags/v7.3.0 - Owner: https://github.com/redhat-community-ai-tools
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@da51091e1d4d348bed3da7e0e827ce5a691aceb1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file harness_eval-7.3.0-py3-none-any.whl.
File metadata
- Download URL: harness_eval-7.3.0-py3-none-any.whl
- Upload date:
- Size: 213.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a34a0667bbf5eb7d5aa351a29f0e0e389e1be911395744c861d8af8389f58e6
|
|
| MD5 |
16c0be0aabff7f29293772c2bb1fea81
|
|
| BLAKE2b-256 |
ce2ec8ed3c48f0371c9a1f9760720ada16f7652d8ab82a1ec4d5c4c1c6d7ef2a
|
Provenance
The following attestation bundles were made for harness_eval-7.3.0-py3-none-any.whl:
Publisher:
publish.yml on redhat-community-ai-tools/harness-eval
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
harness_eval-7.3.0-py3-none-any.whl -
Subject digest:
4a34a0667bbf5eb7d5aa351a29f0e0e389e1be911395744c861d8af8389f58e6 - Sigstore transparency entry: 2398398807
- Sigstore integration time:
-
Permalink:
redhat-community-ai-tools/harness-eval@da51091e1d4d348bed3da7e0e827ce5a691aceb1 -
Branch / Tag:
refs/tags/v7.3.0 - Owner: https://github.com/redhat-community-ai-tools
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@da51091e1d4d348bed3da7e0e827ce5a691aceb1 -
Trigger Event:
push
-
Statement type: