Skip to main content

fatcheck

Agent instruction files (CLAUDE.md, AGENTS.md, and the rest) only grow. Adding a rule is cheap. Deleting one without knowing why it was there feels unsafe. fatcheck is a weigh-in: count the rules, record the why in a sidecar the agent never loads, and prune only after you pick the cuts.

uvx --from git+https://github.com/shunvel/fatcheck fatcheck scan

Demo (messy-repo)

Before, on the bundled fixture:

              fatcheck scan
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━┓
┃ file                           ┃ kind   ┃ instr ┃ lines ┃ bytes ┃ ~tok ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━┩
│ .cursor/rules/ts.mdc           │ cursor │     1 │     7 │   121 │   30 │
│ .github/copilot-instructions.md│ copilot│     1 │     1 │    47 │   11 │
│ AGENTS.md                      │ codex  │     4 │     6 │   168 │   42 │
│ CLAUDE.md                      │ claude │     2 │    15 │   171 │   42 │
│ frontend/AGENTS.md             │ codex  │     1 │     1 │    38 │    9 │
│ shim/CLAUDE.md [shim]          │ claude │     0 │     1 │    11 │    2 │
└────────────────────────────────┴────────┴───────┴───────┴───────┴──────┘
total instructions: 9
~136 tokens (bytes/4, estimate)

lint flags uncommented rules and a TypeScript line copied into both CLAUDE.md and AGENTS.md. After notes plus prune --apply, the extra copy and the falsified on-call rule are gone:

--- AGENTS.md
+++ AGENTS.md
@@ -1,6 +1,5 @@
 # Agents
 
 - Use TypeScript for all new application code.
 - Run tests before every pull request.
 - Prefer small pull requests.
-- Always ping the on-call before merging.

--- CLAUDE.md
+++ CLAUDE.md
@@ -1,5 +1,4 @@
 # Team
 
-Use TypeScript for all new application code.
 Never commit API keys or secrets.

TypeScript stays in AGENTS.md (default canonical). Notes live in .fatcheck.yml, not in the prompt.

Install

Python 3.11+. Until the package is on PyPI:

uvx --from git+https://github.com/shunvel/fatcheck fatcheck scan
# or
pipx install git+https://github.com/shunvel/fatcheck

From a clone:

pip install -e ".[dev]"

Day-one flow

First lint is a wall of missing. Freeze that, then CI only fails on new uncommented rules.

fatcheck scan
fatcheck init --baseline
fatcheck lint              # new missing / copies (size is a scan warning)
fatcheck lint --strict     # all missing, ignore baseline
fatcheck lint --off missing
fatcheck annotate          # numbered why (writes .fatcheck.yml only)
fatcheck prune             # numbered diffs, nothing written
fatcheck prune --apply     # pick 1,3 or all, then y/N (writes *.bak)
fatcheck prune --apply --only all --yes   # scripts; --yes alone will not apply everything

--json and --path work on scan, lint, and prune. lint --sarif fatcheck.sarif writes SARIF 2.1 for GitHub code scanning. Exit 0 when clean, 1 when there are findings. lint never writes .fatcheck.yml (hash rematch is applied by init / annotate).

Hooks (write-time, fail open)

Copy-paste, not a plugin per vendor. If an agent instruction file changed, remind the maintainer to record why.

Agent Drop-in
Cursor examples/cursor/hooks.json + after-agent-file.sh / after-agent-file.py.cursor/hooks.json and .cursor/hooks/
Claude Code examples/claude/settings.hooks.json + post-tool-use.py.claude/settings.json hooks + .claude/hooks/
Codex / Copilot / Gemini examples/AGENTS.fragment.md

Other repos can pin this project as a pre-commit hook:

- repo: https://github.com/shunvel/fatcheck
  rev: v0.2.0
  hooks:
    - id: fatcheck       # copies / noise; does not fail on uncommented rules
    - id: fatcheck-new   # new missing vs .fatcheck-baseline.yml (run init --baseline first)

Optional .fatcheck.toml in the repo root:

canonical = "agents"    # agents | claude | longest
ignore_local = true     # skip CLAUDE.local.md

How to read the output

  • ~tokbytes/4, a rough prompt-size estimate, not a tokenizer.
  • missing — no note in .fatcheck.yml (grandfathered per file if listed in .fatcheck-baseline.yml).
  • noise — a note that is too vague.
  • copied_file — two whole files look like copies. Keep the canonical one (agents by default).
  • duplicate — the same rule in two files that are otherwise different.
  • size_claude / size_codex — over the published soft limits (200 lines / 32 KB). Shown by scan, not a lint failure.

prune proposes prune_falsified (your note says the rule did not help; if recurrence >= 1, it says “failed N times”) and prune_duplicate. Safety-marked rules are left alone. Deletes match the current instruction text, so a moved line still gets found.

Files it finds

No config required. Among others: CLAUDE.md, AGENTS.md, .github/copilot-instructions.md, .cursor/rules/, GEMINI.md. It skips README.md, .git, node_modules, vendor, site-packages, .venv, generated, third_party, and paths deeper than 8 directories. CLAUDE.local.md is skipped unless ignore_local = false.

GitHub listing (set on the repo)

Description: Weigh-in for CLAUDE.md and AGENTS.md. Topics: claude-code, agents-md, cursor, prompt-engineering.

Consumer SARIF workflow (copy into your repo): examples/github/sarif.yml. Publishing to PyPI is tag v* via .github/workflows/publish.yml (trusted publishing; not uploaded from a local session).

Where this idea comes from

Kushal Chakrabarti, Why Does CLAUDE.md Keep Growing? Catastrophic Remembering in Agentic Coding (arXiv:2608.11095). Public GitHub agent files more than tripled over their life; net adds piled up; old rules almost never came out except in a wipe. The paper’s advice is to write what failed, what you tried, and whether it helped. fatcheck is an independent tool. It is not affiliated with the paper’s author.

Today’s coding tools put the whole instruction file into the prompt. fatcheck keeps notes in .fatcheck.yml so the agent never sees them.

Honest limits

fatcheck cannot recover why a two-year-old rule exists. It does not invent a why. It only deletes lines after prune --apply and a pick you confirm. Leave prune off CI.

Tests

pytest
ruff check src tests

Checklist: tests/TEST_MATRIX.md. Fixture: fixtures/messy-repo.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fatcheck-0.2.0.tar.gz (26.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fatcheck-0.2.0-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file fatcheck-0.2.0.tar.gz.

File metadata

  • Download URL: fatcheck-0.2.0.tar.gz
  • Upload date:
  • Size: 26.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fatcheck-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ba580d4aa360387912df9fd3d0517f10be9501f8fa834a4289a561ef8d0e3db3
MD5 f4352ac777ac8fadd45f3a01d5d9a78e
BLAKE2b-256 e9fd0dbc91262a01df4c4e90557c86a5220be868d93295da4274f028634c3a39

See more details on using hashes here.

Provenance

The following attestation bundles were made for fatcheck-0.2.0.tar.gz:

Publisher: publish.yml on shunvel/fatcheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fatcheck-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fatcheck-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fatcheck-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 31ac7ee9c9846342bedffa0022b7267a345cf27bca098bfeaf91d4030f483c02
MD5 7f5d805dfe2782d2654d5c8511ab72b9
BLAKE2b-256 4748eae42e650a0f615a729fcaeb82a5d55b64eef0e85330976d6455e1305393

See more details on using hashes here.

Provenance

The following attestation bundles were made for fatcheck-0.2.0-py3-none-any.whl:

Publisher: publish.yml on shunvel/fatcheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page