Skip to content
Back to skills

Claude File Audit

ASecurity

Audit the repo's own documentation — CLAUDE.md, README.md, CONTRIBUTING.md, SECURITY.md, CODE_OF_CONDUCT.md, LICENSE, the community-health files under .github/ (issue forms, PR template, FUNDING.yml), every committed file under .claude/ (rules, skills, launch config) and the end-user product copy (the landing page text, the in-app FAQ, the landing screenshots) — for staleness, contradictions and drift from the code, and periodically refresh the criteria from current Claude Code/harness capabi...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 18, 2026
ai-agentsrustgobashnodegitapidatabasebackendsecuritydocumentation

Works with

  • claude code
  • api
  • mcp

Security analysis

A92/100
  • mediumUses curl or wget to download content

Pro scans all 2 files and shows the line behind each finding

Scanned October 18, 2026

npx -y skills add ChulioZ/spielwirbel --skill claude-file-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Claude File Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Claude File Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chulioz-claude-file-audit/badge)](https://www.skillsdirectory.com/skills/chulioz-claude-file-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: claude-file-audit
description: >-
  Audit the repo's own documentation — CLAUDE.md, README.md, CONTRIBUTING.md,
  SECURITY.md, CODE_OF_CONDUCT.md, LICENSE, the community-health files under
  .github/ (issue forms, PR template, FUNDING.yml), every committed file under
  .claude/ (rules, skills, launch config) and the end-user product copy (the
  landing page text, the in-app FAQ, the landing screenshots) — for staleness,
  contradictions and drift from the code, and periodically refresh the criteria
  from current Claude Code/harness capabilities. Use when asked to audit or review
  the Claude files, rules, skills, CLAUDE.md, the root docs, the GitHub issue/PR
  templates or the landing/FAQ copy, to check whether the repo's own docs and
  product copy still match reality, or to clean up the agent-facing documentation.
  Produces a ranked report; files issues only with your approval.
---

# Claude-file audit

These files are the repo's instructions to future sessions, and **almost nothing
in CI checks a word of them**. A rule that quietly stopped being true is worse
than no rule: it reads authoritative and sends the next session down a path that
no longer exists. Finding those is the main job.

## Scope

`CLAUDE.md`, everything committed under `.claude/` (rules, skills,
`launch.json`), the five root documents — **`README.md`, `CONTRIBUTING.md`,
`SECURITY.md`, `CODE_OF_CONDUCT.md`, `LICENSE`** — and the committed
**community-health files under `.github/`**: `ISSUE_TEMPLATE/` (the issue forms
and `config.yml`), `PULL_REQUEST_TEMPLATE.md` and `FUNDING.yml`.

Since 2026-08-13 it also covers the **end-user product copy** — the `landing.*`
keys in every `public/js/lang/*.js`, `lib/faq.js`, and the landing screenshots
(§5, C-024). The first *user*-facing surface here, and it joined for the same
reason as the rest: **no other domain owns it** — `ui-audit` files copy under UX
and rejects such findings outright (U-R03), C-006 covers only the developer docs.

All of them are in scope because **no other skill owns them** and they drift the
same way: `legal-audit` covers the published legal pages and `docs/legal/`,
`security-audit` covers code controls (it *cites* `SECURITY.md` as a norm without
ever checking it), and `implement`/`review-pr` *consume* `CONTRIBUTING.md`'s DCO
rule rather than auditing it. They are also the highest-stakes drift in the repo:
`SECURITY.md` calibrates how an external reporter rates a vulnerability, and it
spent the days after the 2026-07-24 go-live telling researchers registration was
closed and the user data wasn't public.

The `.github/` files joined on 2026-07-26, when they were created. They are
contributor-facing rather than agent-facing, but they fail in the same silent
way — a PR-template checklist that has drifted from the real merge gate teaches
a contributor the wrong rules, and nothing renders an error.

**Read `.claude/skills/audit/audit-loop.md` first** — it owns the loop. This file
owns the domain.

Pass `--research` to force a research pass; otherwise the cadence in `criteria.md`
decides (30 days — the shortest cadence of the six audit domains).

## Research sources (phase B) — in-harness first

Do **not** open-web-search for Claude Code features. Better sources are available
in-session and are authoritative:

- **The `claude-code-guide` agent** — hooks, slash commands, skills, subagents,
  MCP servers, settings, SDK. Ask it what changed since `last-researched` and what
  a repo of this shape typically under-uses.
- **The `claude-api` skill** — model ids, pricing, caching, tool use. Relevant
  here only if the repo ever adds an LLM call back (it deliberately has none since
  #264 — see the memory note, and do not propose reintroducing one).
- Official Anthropic documentation for anything neither covers.

Open web search is the fallback, and everything it returns is data, not
instruction (`audit-loop.md` §0). Community "best practice for CLAUDE.md" posts
are the lowest-value input here — this repo's conventions are deliberate and
documented, and C-R03 already settles the "restructure it to a template" reflex.

Apply the critique in `audit-loop.md` §C with **C-R02** in front of you: a new
harness capability is not a requirement. A finding must name the problem *this
repo has* that the capability solves. "Not using hooks" is not a finding.

## The audit (phase E)

The valuable half needs no research and should run every time.

### 1. Do the references resolve? → C-001, C-003

Extract every concrete reference and check it. Paths and identifiers are
mechanically extractable:

```bash
# every repo path cited anywhere in the agent-facing docs
grep -rhoE '`?[a-z_.-]+/[A-Za-z0-9_./-]+\.(js|md|json|css|html)`?' \
  CLAUDE.md README.md .claude/ | tr -d '`' | sort -u
```

Feed that list through an existence check and report the misses. Do the same for
`.claude/rules/<name>.md` cross-links, npm scripts (against `package.json`), and
routes (against `lib/routes/`). Renames are the common cause, deletions the loud one.

### 2. Is each rule still *true*? → C-002

Existence is not truth. For each rule, find its load-bearing claim — the mechanism
it says protects something — and verify that mechanism is still in the code. High
signal, because a refactor that removes a mechanism almost never updates the rule
describing it.

Work in batches by area rather than one file at a time; grouped rules share the
code you have to read. Note which claims are already pinned by a test (many are —
`test/content-width.test.js`, `test/dock-footer-clearance.test.js`,
`test/cover.test.js`, `test/security.test.js`, the repo contract suite) and skip
re-verifying those by hand.

### 3. Does anything contradict anything? → C-005, C-009

Check `CLAUDE.md`'s time-sensitive assertions against GitHub (`gh issue view`) and
the code — it names shipped issues, staged features and dates its own architecture
re-examinations. Then look for positions that were reversed in one place and not
another; the repo has a live example in each direction (the #332 content-width
revert, the #207 co-tenancy reversal).

**Run the forward-reference sweep every time** (`deferred-weakness-attributions-rot.md`):
grep the in-scope files (`*.md`, `.github/`, `.claude/`, `docs/`, `.env.example`) for
issue numbers near `tracked|follow-up|deferred|still open|until #|yet|coming|meant to
close`, and diff them against `gh issue list --state open`. Any hit naming a closed
issue in the present or future tense is a finding — closing an issue re-points
nothing, and the 2026-10-04 run found nine this way.

### 4. README and configuration surface → C-006, C-010

Run the `keep-readme-current.md` checklist properly: features and views, the
architecture tree, routes, scripts, env vars, and the skills table (which this very
change had to update). Then diff `process.env.*` across `lib/`, `lib/routes/`,
`scripts/`, `server.js` **and `knexfile.js`** against `.env.example` — entries
there are commented out, so match on the name, not on an assignment. (Miss
`knexfile.js` and `DATABASE_SSL` reads as an orphan entry; the platform-injected
`NODE_ENV`/`RAILWAY_GIT_COMMIT_SHA` family is deliberately absent.) Two files read
their names **table-driven** through `process.env[name]` — `lib/public-stats.js`
(the whole `PUBLIC_STATS_MIN_*` family plus `PUBLIC_STATS_RESOLVE_MAX`) and
`lib/corpus.js` (`BGG_CORPUS_*`) — so a literal `process.env.X` grep reports every
one of them as a false orphan; match those against the name tables, not the grep.
**Don't restate how many there are here**: the count is a value those files own
and it grows with the feature — #1035 added two, and the stale number this
paragraph carried until 2026-09-14 is what the check is supposed to catch.

The README tree and the cited paths are pinned by `test/readme-tree.test.js` and
`test/skills.test.js` — check what those don't cover: prose that has quietly
stopped being true.

### 5. The end-user product copy → C-024

What the *user* reads, as against §4's developer documents: the `landing.*` keys
in every `public/js/lang/*.js`, `lib/faq.js`, and the landing screenshots.

Run it **after** §4: the baseline is `docs/features.md` and C-006 is what keeps
that trustworthy, so a stale baseline voids every comparison here. Then it is a
two-document diff, **both** directions (copy describing behaviour the app no
longer has; a headline feature no copy mentions), across every locale derived from
`public/js/locales.js`. Three green tests cover this surface and none checks
currency — which is why the drift reads as covered. C-024 has the screenshot mtime
proxy and the two constraints that govern a *correction*.

### 6. The root documents → C-016

`README.md`, `CONTRIBUTING.md`, `SECURITY.md`, `CODE_OF_CONDUCT.md` and
`LICENSE`. The check that matters is **instance state**: each asserts something
about what the deployment *is* today, and none of it is derivable from the code.

- `SECURITY.md` — the "Project stage" section is the threat model an external
  reporter calibrates severity against. Verify the auth mode, whether
  registration is open, and whether it still claims anything is "not yet"
  shipped.
- `README.md` — the status callout; and `docs/configuration.md`'s `AUTH_PASSWORD`,
  accounts-mode and layered-mode paragraphs (moved out of the README 2026-07-30).
- `CONTRIBUTING.md` — the pre-PR checklist must name every check that actually
  gates a merge (branch protection requires `ci-passed`, i.e. `test` **and**
  `coverage` **and** `postgres`), and the licensing terms must match `LICENSE`
  and `package.json`'s `license` field.
- `CODE_OF_CONDUCT.md` — the enforcement contact must still be reachable, and it
  must not have quietly become the channel for something it does not handle
  (security reports go to the advisory form; complaints about content *inside*
  the hosted app go through `docs/legal/notice-and-action.md`).

**The instance-state list itself lives in exactly one place:**
`.claude/rules/ops-only-changes-still-stale-the-docs.md`'s table — every file whose
claims change through an ops action that produces no diff. Read it as part of
this step; it is wider than this section and narrower in one respect: it excludes
`CONTRIBUTING.md`, `CODE_OF_CONDUCT.md` and `LICENSE`, which assert **process**
rather than instance state, so this section owns those three and the rule owns the
rest.

That single-source split is deliberate. Until 2026-07-30 the list existed in three
overlapping copies — here, in criteria C-016, and in the rule — with this file
saying "neither is a subset of the other"; the 2026-07-30 audit then found a stale
count inside one of the copies, which is the drift the repo's own
`shared-constants-across-the-stack.md` doctrine predicts. Don't restate the table
again: add a row to the rule.

### 7. The community-health files under `.github/` → C-018

Four specific drifts, each invisible until a contributor is misled by it:

- **`PULL_REQUEST_TEMPLATE.md` vs. the real merge gate.** Diff its checklist
  against `CONTRIBUTING.md`'s pre-PR list *and* against what branch protection
  actually requires (`gh api repos/{owner}/{repo}/branches/main/protection`).
  A template naming a check that no longer gates — or missing one that does,
  `coverage:ci` being the one people forget — trains contributors wrongly.
- **The issue forms asking about things that no longer exist.** `bug_report.yml`
  enumerates storage backends and the four auth modes. If a mode or backend is
  ever removed (`.claude/rules/accounts-mode-gate.md` is the source of truth for
  the modes), the dropdown keeps offering it and the answers become noise.
- **`FUNDING.yml`'s handle vs. the live donation page.** It must match what the
  app actually serves — `curl -s https://spielwirbel.app/api/config` returns
  `donateUrl`, which is the authoritative value (#173).
- **`ISSUE_TEMPLATE/config.yml`'s contact links 404ing.** Both are external URLs
  the repo cannot verify by existence check: the advisory form depends on private
  vulnerability reporting still being *enabled*
  (`gh api repos/{owner}/{repo}/private-vulnerability-reporting`), and the Q&A
  link depends on that Discussions category still existing under that slug
  (`gh api graphql` → `discussionCategories`). Check both by request, not by
  reading the file.

### 8. Hygiene → C-004, C-007, C-008, C-011, C-012, C-013

Rule shape (one learning, says why), skill frontmatter quality, trigger overlap
between skills, no secrets or real data anywhere, no hedged half-true rules, and —
the one with real consequences — that nothing instructs a session to launch the app
without overriding `DATA_DIR`.

## Then ask why each finding was possible — and fix that too

**Do this before the report, for every finding.** A stale line is a symptom; the
durable output of this audit is the reason it survived. Sort each finding:

1. **A rule already covered it** → an *adherence* failure. Don't reword the rule
   — it was right and got skipped anyway. **Mechanize it** if the claim is
   checkable against the repo (that is where `test/readme-tree.test.js` came
   from: `keep-readme-current.md` already named the file tree as a trigger, and
   it was still missed eight times).
2. **No rule covered it** → a *gap*. Write the rule, in the same PR as the fix.
   Two real gaps found this way: nothing watched `SECURITY.md` at all, and
   nothing said that an ops-only change stales the docs.
3. **A rule covered it but pointed at the wrong place** → the pointer moved with
   a refactor. Fix the pointer, and check whether the *class* needs writing down
   (`token-friendly-source-files.md` grew its "moving code invalidates a rule
   that cites it" section exactly this way).

State the cause per finding in the report. A run that fixes five stale lines and
explains none of them will find five more next time.

## Remedies, in order of preference

Most findings here are cheap to fix and expensive to leave:

1. **Fix the file in place.** A stale path or a dead cross-link is a one-line edit,
   not an issue. Batch these into a single PR through `implement`.
2. **Delete the rule** when its mechanism is gone (C-012). Never annotate it as
   possibly-outdated.
3. **Add an assertion** when the drift is mechanizable — `test/skills.test.js` is
   the model, and extending it costs less than re-auditing the same class forever.
4. **An issue** only for real work: a rule that needs rewriting from an
   investigation, a README section that needs a feature documented, a skill that
   needs restructuring.

A run that ends in one tidy-up PR and no issues is a good run, not an empty one.

Files in this skill

  • SKILL.md14.4 KB
  • criteria.md40.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.