Cookbook · Sheet 07
Copy-paste setups for real stacks. In every case hyperfixer init gets you 90% of the way; these show the finished config with caching, autofix and the right parsers.
{
"failFast": true,
"outDir": ".hyperfixer",
"gates": [
{ "name": "lint", "cost": 5, "command": ["bunx", "biome", "check", "."],
"fixCommand": ["bunx", "biome", "check", "--write", "."],
"inputs": ["src/**", "test/**", "biome.json"] },
{ "name": "typecheck", "cost": 10,
"command": ["bunx", "tsc", "--noEmit", "--pretty", "false"], "parser": "tsc",
"inputs": ["src/**", "test/**", "tsconfig.json"] },
{ "name": "unit", "cost": 30, "command": ["bun", "test"], "parser": "bun-test",
"inputs": ["src/**", "test/**"] }
]
}
ESLint runs with --format json so every finding reaches the agent with file and line; fix clears the autofixable part first.
{
"gates": [
{ "name": "lint", "cost": 5,
"command": ["npx", "eslint", ".", "--format", "json"], "parser": "eslint-json",
"fixCommand": ["npx", "eslint", ".", "--fix"],
"inputs": ["src/**", "test/**", "eslint.config.js"] },
{ "name": "typecheck", "cost": 10,
"command": ["npx", "tsc", "--noEmit", "--pretty", "false"], "parser": "tsc",
"inputs": ["src/**", "test/**", "tsconfig.json"] },
{ "name": "unit", "cost": 30, "command": ["npx", "vitest", "run"],
"inputs": ["src/**", "test/**"] }
]
}
The generic protocol: a gate whose command prints a JSON array of findings integrates with full hints, whatever the toolchain. A pytest wrapper in ten lines:
# scripts/pytest-findings.py
import json, subprocess, sys
r = subprocess.run(["pytest", "--tb=line", "-q"], capture_output=True, text=True)
findings = []
for line in r.stdout.splitlines():
if ".py:" in line and (" error" in line.lower() or "assert" in line.lower()):
path, _, rest = line.partition(":")
num, _, msg = rest.partition(":")
findings.append({"file": path.strip(), "line": int(num) if num.strip().isdigit() else 0, "message": msg.strip()})
print(json.dumps(findings))
sys.exit(r.returncode)
{ "name": "pytest", "cost": 30,
"command": ["python3", "scripts/pytest-findings.py"], "parser": "findings-json",
"inputs": ["src/**", "tests/**"] }
The wrapper's exit code decides pass or fail, the JSON decides what the hint says. Same pattern works for cargo, go test, or any linter.
When you keep a naive reference implementation next to the optimized one, a parity gate with the fast-check parser finds divergences and puts the minimal counterexample plus the replay seed straight into the verdict:
{ "name": "parity", "cost": 50, "command": ["bun", "scripts/parity.ts"],
"parser": "fast-check", "inputs": ["src/**", "scripts/**"] }
Give expensive gates (mutation, e2e) a cost above 50: install-hooks wires pre-commit to --max-cost 50 (fast) and pre-push to the full pipeline. In CI, the GitHub Action runs everything:
- uses: actions/checkout@v4 - uses: egeominotti/hyperfixer@main
Scope your linter to source folders (Biome files.includes, ESLint ignores): otherwise it lints .hyperfixer/verdict.json and the pipeline argues with its own output.