Back to Our Work

April 2026

TIDY: A Claude Code Plugin for Repo Drift

A Claude Code plugin that finds stale docs, dead files, and convention drift, then cleans them up with snapshot commits, a read-only scanner, and per-category approval.

Developer Tools · Claude Code Plugin

Every working repo accumulates drift. The README still claims Python 3.9 when the project moved to 3.11 a year ago. A helpers.py sits at the repo root while every other utility lives in src/utils/. Half a refactor left behind dead files nobody is willing to delete because they are not sure what depends on them. There are TODOs from teammates who left two years ago.

None of this breaks anything, exactly. It just adds drag. Onboarding takes longer because the docs lie. Code review takes longer because conventions are inconsistent. Refactors take longer because nobody can tell which files are live. The cost is paid by every contributor, every time they open the project.

Tidy is a Claude Code plugin we built to find that drift and clean it up. It works on any stack, ships five focused skills, and is structured so that running it does not put your codebase at risk.

Tidy process flowchart. A pre-tidy snapshot commit feeds into a read-only scan, which presents a plan. The user approves or skips, approved findings land as focused commits, and a final test gate runs before the report.

What it does

The plugin ships five skills. tidy:clean does a comprehensive sweep across every category in one pass. The other four are scoped for when you want narrower work.

tidy:docs audits doc accuracy by cross-checking every claim against the actual code. If the README says "requires Python 3.9" and pyproject.toml pins 3.11, that is a finding.

tidy:dead-code finds unused files and imports and removes them. The scan checks both static references and the test suite's reach before anything is proposed for deletion.

tidy:conventions detects the patterns the project already uses and flags the outliers. No outside style guide is imposed. If three out of four route handlers return early on validation failure and one buries the check at the bottom, the outlier is the finding.

tidy:folders proposes git mv for stragglers and updates every import path that referenced the old location.

You do not have to remember the names. Asking Claude to "clean up this repo" auto-invokes tidy:clean, and asking specifically about docs or dead code routes to the narrower skill.

The architecture that makes it safe to run

Most "clean up your codebase" tools are unsafe in exactly the way that makes them useless. They run, they change a hundred files, and you spend the rest of the afternoon figuring out which of those changes you actually wanted. Tidy is structured so that running it is reversible at every step. Four design choices do most of the work.

1

Every cleanup starts with a snapshot commit

Before Tidy looks at a single file, it creates a pre-tidy snapshot commit on your current branch. The entire operation, however many findings it produces and however many commits it lands, can be undone with one git reset --hard pre-tidy.

This sounds small. In practice it is the thing that lets us be aggressive elsewhere in the design. We do not need to be conservative about what Tidy proposes, because the cost of disagreeing is one command. The snapshot is the safety net that makes the rest of the architecture practical.

2

Scanning happens in a read-only subagent

The scanning phase runs in a Claude Code subagent that has no write tools. Not "instructed not to write" but physically restricted by the tool list it was launched with. It can read files, walk directories, run static analysis, and inspect git state. It cannot edit, write, or run shell commands that mutate the working tree.

The reason is that scanning and editing are different jobs with different failure modes. A scanner that can also edit will sometimes confuse the two and start fixing things mid-scan. Separating the surfaces removes that class of mistake at the tool layer instead of at the prompt layer.

3

Findings are grouped, approved, and committed by category

When the scan completes, findings are grouped by category (docs, dead code, conventions, folders) and shown to you for approval. You can accept a category in full, accept individual findings within a category, or reject the lot. Nothing is changed until you approve.

Each approved category becomes its own focused commit. "Update docs to match current Python version", "Remove unused helpers", "Normalize early-return convention in route handlers" land as separate, reviewable diffs instead of one sprawling change. The full test suite has to pass before the final commit lands. If a test breaks mid-cleanup, the work stops and the failing change is rolled back without touching the categories that already passed.

4

Folder moves require per-file approval

Moving a file is the most destructive thing you can do to a codebase that other tools and people depend on. A wrong move breaks every import that referenced the old path, and the breakage is not always visible at compile time in dynamic languages.

Tidy treats tidy:folders as a separate trust level. The skill proposes a git mv for each straggler, shows the import paths that will be rewritten, and asks for approval one file at a time. Bulk-accept exists for users who want it. The default is per-file because the per-file question is the one you usually want to be asked.

What Tidy will not touch, and what it will work on

Vendored paths are off-limits by default: node_modules, .venv, vendor/, build artifacts, and anything in .gitignore. The scanner stays out of them and the cleanup phase will not propose changes inside them. These directories often contain large amounts of code that is not ours to clean.

Beyond those exclusions, Tidy is stack-agnostic on purpose. It detects what is in the repo (a pyproject.toml, a package.json, a go.mod, a Cargo.toml, a Gemfile) and uses that to drive analysis. Convention detection looks at what the project already does instead of importing an outside style guide. The same plugin works on a Python service, a Node monorepo, and a Go CLI without configuration.

Why we built it this way

The hard part of repo cleanup is not finding the drift. The hard part is being able to run cleanup without spending the next hour reviewing changes you did not ask for. Tidy is built around that constraint: a snapshot commit you can roll back to, a scanner that physically cannot write, approval per category, and per-file approval for the riskiest move. The findings are useful in proportion to how cheaply you can refuse them.

We use it on our own repos before review and before release. It is the version of "clean up this repo" we trust to actually run.