DBDelve
Dive deep into your data. A fast, native, multi-engine database client written in Rust. Free and open source, no telemetry.
翻訳待ち
Deterministic, diff-aware guardrails for AI coding agents: weakened tests, type suppressions, config tampering, stubs and phantom imports, blocked before the agent finishes.
翻訳待ち
開発ツールTypeScriptGitHub @aguschirico接続状況の再確認が必要です所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
Catch the shortcuts AI coding agents take: weakened tests, type suppressions, config tampering. Diff-aware, deterministic, built for agent hooks.
翻訳待ち
Loading the full README.
Read the full README ↗Your coding agent says the tests pass. cheatguard checks how.
cheatguard reads the diff an AI coding agent produced and stops the shortcuts agents take when a task gets hard: deleted assertions, skipped tests, silenced type errors, relaxed configs, placeholder code and imports of packages that do not exist. It also runs the linters you already have on just the changed files and shows only the problems the change introduced.
It is deterministic, runs locally in milliseconds, and never sends your code anywhere.
npm i -D cheatguard
npx cheatguard init claude-code # adds the hooks to .claude/settings.json
Restart Claude Code (or run /hooks). From then on:
npx cheatguard accept.Prefer not to add a dependency? The Claude Code plugin installs the same hooks for every project:
claude plugin marketplace add aguschirico/claude-plugins
claude plugin install cheatguard@aguschirico
It comes from my marketplace, next to my other plugins. This repository is still a marketplace of its own (aguschirico/cheatguard, then cheatguard@cheatguard), so installs made that way keep working.
| Rule | Reports | Effect |
|---|---|---|
test-weakened | Tests or test files deleted or moved where the runner skips them; assertions removed, made unreachable or replaced by literals; tests skipped, focused, made conditional (skipIf/runIf), inverted (.fails) or run over an empty table; expected values edited or matchers weakened to match the code | Blocks |
type-suppression | New any, as any, as never, double casts through unknown, Function, untyped declare module, @ts-ignore, @ts-expect-error, eslint-disable, oxlint-disable, biome-ignore, coverage-ignore comments | Blocks |
config-tampering | Strict flags turned off (also in extended tsconfigs), lint rules weakened, files or tests dropped from tsc, ESLint, Biome, oxlint or the test run, coverage lowered, test scripts neutralized, CI checks disabled, workspace packages removed, the agent's own cheatguard hooks removed, config files deleted or renamed | Blocks |
stub-left | Not-implemented or TBD throws, TODO-implement comments, function bodies gutted to return a constant | Blocks |
phantom-import | Imports of packages that are not declared or not installed, and relative files that do not exist | Blocks |
swallowed-error | New catch blocks that are empty, comment-only or only log, and .catch(() => undefined) | Warns |
duplicate-export | A new exported function that copies an existing one (formatDate2 next to formatDate) | Warns |
scope-creep | Files changed outside the paths you allowed | Warns |
Every rule looks only at what the change introduced. Details and examples: docs/rules.md.
npx cheatguard check # working tree vs HEAD, plus new lint/type errors
npx cheatguard check --base origin/main --format json # in CI
npx cheatguard check --staged # in a pre-commit hook
npx cheatguard lint # only the lint/type diagnostics you introduced
npx cheatguard rules # list the rules
npx cheatguard accept # (you, in a terminal) drop issues a released session left open
Exit codes: 0 clean, 1 blocking issues, 3 the tool itself failed or a linter could not run. In CI, a linter that crashes, or one listed in lint.tools that is not installed, is an error; with lint.tools: "auto", a configured linter that is not installed is a warning. Inside agent hooks, an internal error never blocks the agent (it is logged and, at the end of a session, shown to you).
Everything is optional. Put a cheatguard.config.json at the repository root:
{
"rules": { "swallowed-error": "block", "duplicate-export": "off" },
"scope": { "allow": ["src/**", "test/**"] },
"ignore": ["src/legacy/**"],
"lint": { "tools": ["eslint", "tsc"], "maxDiagnostics": 20 }
}
The configuration is always read from the base of the change (the committed version, or the session's starting point), so a change can never relax the rules it is judged by. Any edit to the file is itself reported, and the CLI tells you when your working-tree config is uncommitted or invalid. Full reference: docs/configuration.md.
Does it flag the right things? (benchmark A, hand-labeled)
| Corpus | Cases | Changed lines | Precision | Recall | Precision of blocking flags | Wrong blocks per 1,000 lines |
|---|---|---|---|---|---|---|
| Synthetic cases (written with the rules; in-distribution) | 347 | 1,526 | 100% | 100% | 100% | 0.00 |
| Merged pull requests written by coding agents | 154 | 20,313 | 72% | 100% | 59% | 0.44 |
| Merged pull requests written by people (before 2022) | 122 | 8,700 | 75% | 100% | 87% | 0.57 |
This is the beginning of the README. Read the rest at the original. Read the full README ↗