agentleFS
jars-demojars-demo/jars-skills/skills/code-hygiene/SKILL.md

code-hygiene

Skill0 starsChanged 32 days agoMITView on GitHub

Audit and clean up code quality issues that accumulate over time — not bugs, but rot. Use when the user asks to clean up code, fix naming conventions, remove unused imports, remove dead code, fix inconsistent variable names, eliminate AI-generated boilerplate, remove vendor-generated noise, standardize casing (camelCase, snake_case, PascalCase), remove stale comments, fix magic numbers, or sweep a file or module for code quality issues before a release or review.

  • Installs packages

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

28 rules. About 0 are common, 23 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈23

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Read the project conventions first: Check CONTRIBUTING.md, linter config (.eslintrc, ruff.toml, .pylintrc, biome.json), and the existing …

    line 14
  2. Distinctive:

    One concern per commit: Don't mix naming fixes, dead code removal, and comment cleanup into one commit.

    line 20
  3. Distinctive:

    Tests pass before and after: Run the suite before touching anything.

    line 22
  4. Distinctive:

    Never remove code you don't understand: If something looks unused but you can't trace every call site, flag it rather than delete it.

    line 24
  5. Distinctive:

    If the linter already catches it, let the linter fix it — don't do it manually:

    line 44
  6. Distinctive:

    Only proceed manually for issues the linter doesn't catch.

    line 52
  7. Very specific:

    Remove the import. If it was providing a side effect (e.g.

    line 118
  8. Distinctive:

    Search all call sites including tests, config files, and dynamic invocations.

    line 142
  9. Distinctive:

    Check if it's part of a public API or plugin interface — deletion is a breaking change.

    line 143
  10. Very specific:

    If unsure, add a # TODO: verify unused before removal comment and flag it in the PR rather than deleting blindly.

    line 144
  11. Distinctive:

    Remove the wrapper and call the underlying function directly.

    line 193
  12. Distinctive:

    Delete comments that restate the code.

    line 194
  13. Distinctive:

    Remove defensive guards that the type system already guarantees.

    line 195
  14. Very specific:

    Remove unused parameters — or add _ prefix if the signature is required by an interface.

    line 196
  15. Distinctive:

    Commented-out code: delete it. Git has the history.

    line 211
  16. Distinctive:

    Comments that restate the code: delete them.

    line 217
  17. Distinctive:

    When different parts of the codebase do the same thing differently, pick the pattern the majority uses and make it consistent.

    line 266
  18. Distinctive:

    Don't fix style inconsistencies by hand — configure the linter/formatter and let it run:

    line 281
  19. Distinctive:

    Run the linter on the file and auto-fix what it catches.

    line 295
  20. Distinctive:

    Read the file top to bottom.

    line 296
  21. Distinctive:

    Run tests after each category.

    line 298
  22. Distinctive:

    Run the linter across the scope.

    line 302
  23. Very specific:

    Use ts-prune / vulture to find dead exports and functions.

    line 303
  24. Distinctive:

    Search for magic numbers in business logic.

    line 312
  25. Distinctive:

    Search for TODO/FIXME — triage each one.

    line 313
  26. Distinctive:

    Search for the vague name patterns above — spot check the worst offenders.

    line 314
  27. Distinctive:

    Verify tests still pass.

    line 315
  28. Distinctive:

    Delete code it can't fully trace.

    line 350

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Code hygiene

Hunt and eliminate the rot that accumulates in real codebases: wrong casing, dead imports, stale comments, magic numbers, AI-generated filler, unused variables, inconsistent naming. None of this is a bug — but all of it slows down every developer who reads the code after you.

Ground rules

  • Read the project conventions first. Check CONTRIBUTING.md, linter config (.eslintrc, ruff.toml, .pylintrc, biome.json), and the existing codebase style. The project's rules override everything in this skill.
  • No behaviour changes. Renaming a variable, removing a dead import, and fixing a comment do not change what the code does. If you find a bug while cleaning, note it and fix it separately.
  • One concern per commit. Don't mix naming fixes, dead code removal, and comment cleanup into one commit. Each is its own change with its own message.
  • Tests pass before and after. Run the suite before touching anything. If tests are already failing, stop and report — don't clean a broken codebase.
  • Never remove code you don't understand. If something looks unused but you can't trace every call site, flag it rather than delete it.
  • Never push, publish, or deploy unless explicitly asked.

Step 0: Establish baseline

# Tests green before you start?
pytest                    # Python
npm test -- --run         # JS/TS
go test ./...             # Go

# What does the linter already catch?
ruff check .              # Python
npx eslint src/           # JS/TS
npx biome check src/      # JS/TS (Biome)

If the linter already catches it, let the linter fix it — don't do it manually:

ruff check . --fix        # Python: auto-fix safe issues
npx eslint src/ --fix     # JS/TS: auto-fix
npx biome check src/ --write  # Biome: auto-fix

Only proceed manually for issues the linter doesn't catch. Record baseline test result.


What to audit

1. Naming conventions

Consistent naming is the difference between code you can scan and code you have to decode.

LanguageVariables/functionsClassesConstantsFiles
JavaScript / TypeScriptcamelCasePascalCaseUPPER_SNAKE_CASEkebab-case or camelCase
Pythonsnake_casePascalCaseUPPER_SNAKE_CASEsnake_case
GocamelCasePascalCasePascalCase (exported)snake_case
Rustsnake_casePascalCaseUPPER_SNAKE_CASEsnake_case

Red flags to search for:

# Mixed casing in Python (camelCase variables in a snake_case codebase)
grep -rn "[a-z][A-Z]" src/ --include="*.py" | grep -v "def \|class \|#"

# Single-letter variables outside of loops and math
grep -rn "\b[a-df-z]\b\s*=" src/ --include="*.ts"

# Vague names that carry no meaning
grep -rn "\bdata\b\|\binfo\b\|\btemp\b\|\bobj\b\|\bval\b\|\bres\b\|\bret\b" src/ --include="*.ts"

Fix them with your editor's rename refactor — not find-and-replace, which breaks partial matches. In an agent context, use a semantic rename tool so all references update together.

Good names say what a thing is, not what it contains:

BadGoodWhy
datainvoicePayloadSays what the data represents
resuserResponseSays what the response is for
tempfilteredOrdersSays what it holds
flagisEmailVerifiedBooleans: is, has, can, should
cbonPaymentSuccessCallbacks named for their trigger
arrpendingInvoicesArrays named for their contents
ManagerSessionCacheClasses named for their role
utils.tsdateFormatters.tsFiles named for what they contain

2. Unused imports

Unused imports add noise to every file and slow down linters, bundlers, and readers.

# Python: ruff catches these
ruff check . --select F401

# TypeScript/JavaScript: ESLint with no-unused-vars / unused-imports plugin
npx eslint src/ --rule '{"no-unused-vars": "error"}'

# Go: the compiler enforces this — unused imports are a build error
go build ./...

# Find manually in TS/JS if no linter is set up
grep -rn "^import" src/ --include="*.ts" | grep -v "from"

Remove the import. If it was providing a side effect (e.g. import './polyfill'), add a comment explaining why the side-effect-only import exists.


3. Dead code

Code that is defined but never called. Every dead function is a maintenance trap — future developers read it, try to understand it, and wonder if removing it will break something.

# TypeScript: ts-prune finds unused exports
npx ts-prune

# Python: vulture finds dead code
pip install vulture
vulture src/

# Find functions defined but never called (rough grep — verify before deleting)
grep -rn "^def \|^function \|^const.*= (" src/ --include="*.py" -l | \
  xargs -I{} sh -c 'grep -oh "def \w\+" {} | awk "{print \$2}"'

Before deleting:

  • Search all call sites including tests, config files, and dynamic invocations.
  • Check if it's part of a public API or plugin interface — deletion is a breaking change.
  • If unsure, add a # TODO: verify unused before removal comment and flag it in the PR rather than deleting blindly.

4. AI-generated and vendor-generated slop

AI coding tools and code generators produce working code — but they also produce patterns that are wasteful, over-engineered, or stylistically inconsistent with the rest of the codebase. Common signs:

Unnecessary abstraction:

// AI slop: a wrapper that does nothing
function getUserById(id: string) {
  return fetchUser(id);   // just call fetchUser directly
}

Over-commented obvious code:

# Increment the counter by 1
counter += 1

# Return the result
return result

Defensive guards on values that are always defined:

if (user && user.id && user.id !== null && user.id !== undefined) {
  // user.id is typed as string — this is all noise
}

Unused parameters left in from a template:

def process(data, config=None, options=None, verbose=False):
    # config, options, verbose never used in the body
    return transform(data)

Generic error messages from scaffolding:

throw new Error("An error occurred");   // tells the caller nothing
throw new Error("Something went wrong");

What to do:

  • Remove the wrapper and call the underlying function directly.
  • Delete comments that restate the code. Keep comments that explain why.
  • Remove defensive guards that the type system already guarantees.
  • Remove unused parameters — or add _ prefix if the signature is required by an interface.
  • Replace generic error messages with specific ones that include the value and context.

5. Stale comments and commented-out code

# Find commented-out code blocks (Python)
grep -rn "^#\s*[a-zA-Z_]*(" src/ --include="*.py"

# Find TODO/FIXME with no owner or ticket
grep -rn "TODO\|FIXME\|HACK\|XXX" src/

Commented-out code: delete it. Git has the history. Commented-out code confuses every reader into wondering if it's intentional, in progress, or forgotten.

Stale TODOs: either fix the issue now, open a ticket and replace the comment with the ticket number (# TODO(PROJ-123): ...), or delete it if the concern is no longer valid.

Comments that restate the code: delete them.

Comments that explain why: keep and improve them.

# Bad — restates the code
# Get the user by id
user = db.get_user(user_id)

# Good — explains a non-obvious constraint
# Stripe requires idempotency keys scoped to a single payment attempt.
# Reusing a key from a failed attempt causes a 400.
key = f"{payment_id}-{attempt}"

6. Magic numbers and strings

A bare number or string in logic is a bug waiting to happen — no one knows what it means or whether it's safe to change.

# Bad
if retries > 3:
    ...
time.sleep(0.5)
if status == 2:
    ...

# Good
MAX_RETRIES = 3
RETRY_DELAY_SECONDS = 0.5
STATUS_ACTIVE = 2

if retries > MAX_RETRIES:
    ...
time.sleep(RETRY_DELAY_SECONDS)
if status == STATUS_ACTIVE:
    ...

Exception: 0, 1, -1 in obvious mathematical context, and HTTP status codes with a comment, are fine as-is. Don't over-extract.


7. Inconsistent code patterns

When different parts of the codebase do the same thing differently, pick the pattern the majority uses and make it consistent.

# Mixed quote styles in Python (single vs double)
grep -rn "'" src/ --include="*.py" | wc -l
grep -rn '"' src/ --include="*.py" | wc -l

# Inconsistent error handling patterns
grep -rn "try:\|except Exception\|except:" src/ --include="*.py" | head -20

# Mixed async patterns in JS (callbacks vs promises vs async/await)
grep -rn "\.then(\|new Promise\|callback" src/ --include="*.ts"

Don't fix style inconsistencies by hand — configure the linter/formatter and let it run:

black src/          # Python formatting
prettier --write .  # JS/TS formatting
gofmt -w .         # Go formatting

Workflow

For a single file

  1. Run the linter on the file and auto-fix what it catches.
  2. Read the file top to bottom. Note every violation by category.
  3. Fix in order: imports → dead code → naming → comments → magic numbers.
  4. Run tests after each category. Commit each category separately.

For a module or directory

  1. Run the linter across the scope. Auto-fix safe issues.
  2. Use ts-prune / vulture to find dead exports and functions.
  3. Fix the easiest category first (unused imports) — it reduces noise for the rest.
  4. Work file by file through naming, then dead code, then comments.
  5. One commit per category across the module.

For a pre-release sweep

  1. Linter + formatter on the whole codebase.
  2. ts-prune / vulture pass — flag, don't delete blindly.
  3. Search for magic numbers in business logic.
  4. Search for TODO/FIXME — triage each one.
  5. Search for the vague name patterns above — spot check the worst offenders.
  6. Verify tests still pass.
  7. Report a summary: files touched, violations fixed, issues flagged for follow-up.

Report format

## Hygiene sweep: <scope>  (<date>)

Auto-fixed by linter:
  - 14 unused imports (ruff F401)
  - 7 formatting issues (black)

Fixed manually:
  - 3 magic numbers extracted to constants (billing.py)
  - 5 vague variable names renamed (orders.py, users.py)
  - 11 stale comments removed across 4 files
  - 2 commented-out code blocks deleted

Flagged for follow-up (not deleted — need verification):
  - process_legacy_order() in orders.py — appears unused, but check background jobs
  - FEATURE_FLAG_V2 constant — no call sites found, may be read via getattr()

Tests: 94 passed, 0 failed. Exit 0.

What this skill does NOT do

  • Fix bugs or logic errors — that's debug-session.
  • Restructure modules or split large files — that's refactor.
  • Review a PR diff for correctness — that's code-review.
  • Change public API signatures without confirmation.
  • Delete code it can't fully trace.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.