Claude-skill-registry Lint Cleanup

FIX ESLint errors safely without breaking code. Prefix unused variables with `_`, fix no-case-declarations, add default props, and verify builds after each batch. Use when lint cleanup is needed for easier refactoring & faster Claude Code editing.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-lint-cleanup" ~/.claude/skills/majiayu000-claude-skill-registry-lint-cleanup && rm -rf "$T"
manifest: skills/data/dev-lint-cleanup/SKILL.md
source content

Safe Lint Cleanup

Instructions

This skill provides safe patterns for fixing ESLint errors without breaking code.

Pre-Flight Checklist

BEFORE starting any lint cleanup:

# 1. Get baseline count
npm run lint 2>&1 | tail -5

# 2. Save full output for reference
npm run lint 2>&1 > /tmp/lint-output.txt

# 3. Verify build works
npm run build

# 4. Check git status (ensure clean state)
git status

Error Categories & Fixes

1. Unused Variables (
@typescript-eslint/no-unused-vars
)

Pattern 1: Prefix Unused Variables with
_

This is the SAFEST fix - silences the error without changing logic:

// BEFORE (error)
const unusedVar = someValue

// AFTER (no error)
const _unusedVar = someValue

Pattern 2: Prefix Unused Function Parameters

// BEFORE
const handleClick = (event: MouseEvent) => {
  // doesn't use event
}

// AFTER
const handleClick = (_event: MouseEvent) => {
  // doesn't use event
}

Pattern 3: Destructuring with Rename

// BEFORE
const { unusedProp, usedProp } = options

// AFTER
const { unusedProp: _unusedProp, usedProp } = options

Pattern 4: Unused Type Imports

// BEFORE
import { SomeType, UsedType } from '@/types'

// AFTER
import type { SomeType as _SomeType, UsedType } from '@/types'

Pattern 5: Remove Completely Unused Imports

// BEFORE
import { ref, watch, computed } from 'vue'  // watch never used

// AFTER
import { ref, computed } from 'vue'

2. Case Declarations (
no-case-declarations
)

Error:

Unexpected lexical declaration in case block

Cause: Using

const
,
let
, or
class
directly in a
case
block without braces.

Fix: Wrap case block contents in

{}
to create block scope.

// BEFORE (error)
switch (type) {
  case 'foo':
    const value = computeValue()  // ERROR!
    doSomething(value)
    break
  case 'bar':
    const other = computeOther()  // ERROR!
    doOther(other)
    break
}

// AFTER (fixed)
switch (type) {
  case 'foo': {
    const value = computeValue()
    doSomething(value)
    break
  }
  case 'bar': {
    const other = computeOther()
    doOther(other)
    break
  }
}

Quick find pattern:

# Find files with case declarations errors
npm run lint 2>&1 | grep "no-case-declarations" -B1 | grep -E "^/" | sort -u

3. Vue Default Props (
vue/require-default-prop
)

Error:

Prop 'X' requires default value to be set

Cause: Optional props without default values in Vue 3

<script setup>
.

Fix: Use

withDefaults()
to provide default values.

<!-- BEFORE (error) -->
<script setup lang="ts">
interface Props {
  title?: string
  count?: number
  items?: string[]
}
const props = defineProps<Props>()
</script>

<!-- AFTER (fixed) -->
<script setup lang="ts">
interface Props {
  title?: string
  count?: number
  items?: string[]
}
const props = withDefaults(defineProps<Props>(), {
  title: '',
  count: 0,
  items: () => []  // Use factory for arrays/objects
})
</script>

Default value rules:

  • Primitives: Use direct value (
    ''
    ,
    0
    ,
    false
    ,
    null
    )
  • Arrays: Use factory function
    () => []
  • Objects: Use factory function
    () => ({})

4. Boolean Shorthand (
vue/prefer-true-attribute-shorthand
)

Error:

Boolean attribute should be written in shorthand form

Cause: Using

:prop="true"
instead of just
prop
.

<!-- BEFORE (error) -->
<MyComponent :is-active="true" :show-header="true" />

<!-- AFTER (fixed) -->
<MyComponent is-active show-header />

5. Empty Object Types (
@typescript-eslint/no-empty-object-type
)

Error:

The {} type is not recommended

Cause: Using

{}
as a type in TypeScript (especially in
.d.ts
files).

Fix: Use

object
or
Record<string, never>
instead, OR exclude
.d.ts
files:

// In eslint.config.js ignores:
ignores: ['**/*.d.ts']

6. ESLint Config Alignment

Problem: Files excluded from

tsconfig.json
but not from ESLint cause parsing errors.

Fix: Keep ESLint ignores aligned with tsconfig excludes:

// eslint.config.js
{
  ignores: [
    'node_modules/**',
    'dist/**',
    '**/*.d.ts',
    // Match tsconfig.json exclude patterns:
    'src/stories/**',
    'src/composables/adapters/**',
    'src/sync/**',
    'src/utils/emojiDetection.ts',
    'src/utils/logger.ts',
    // etc.
  ]
}

ESLint Config for Underscore Pattern

CRITICAL: The underscore pattern must be configured for BOTH

.ts
AND
.vue
files:

// eslint.config.js

// For TypeScript files
{
  files: ['**/*.ts', '**/*.tsx'],
  rules: {
    '@typescript-eslint/no-unused-vars': ['error', {
      argsIgnorePattern: '^_',
      varsIgnorePattern: '^_',
      caughtErrorsIgnorePattern: '^_'
    }]
  }
}

// For Vue files - MUST BE SEPARATE!
{
  files: ['**/*.vue'],
  rules: {
    '@typescript-eslint/no-unused-vars': ['error', {
      argsIgnorePattern: '^_',
      varsIgnorePattern: '^_',
      caughtErrorsIgnorePattern: '^_'
    }]
  }
}

Verification Process

After every batch of fixes:

# 1. Run build
npm run build 2>&1 | tail -10

# 2. Check new lint count
npm run lint 2>&1 | tail -5

# 3. Calculate progress
# (baseline - current) / baseline * 100 = % fixed

Files to Be Careful With

File TypeReason
Vue components with templatesVariables might be used in template
Store filesExported functions might appear unused
ComposablesReturned values might appear unused
Test filesMay have intentional unused vars
.d.ts
files
Type declarations may use special patterns

Error Priority Order

Fix errors in this order (highest impact first):

  1. Parsing errors - ESLint ignores alignment with tsconfig
  2. no-case-declarations - Structural fixes, wrap in
    {}
  3. require-default-prop - Add
    withDefaults()
  4. no-unused-vars - Prefix with
    _
    or remove
  5. prefer-true-attribute-shorthand - Simple template fixes
  6. no-explicit-any - Requires proper typing (lower priority)

Quick Reference Commands

# Get current lint count
npm run lint 2>&1 | tail -5

# Save full output
npm run lint 2>&1 > /tmp/lint-output.txt

# Find files with specific error
npm run lint 2>&1 | grep "ERROR_NAME" -B1 | grep -E "^/" | sort -u

# Count specific error type
grep "ERROR_NAME" /tmp/lint-output.txt | wc -l

# Check specific file errors
cat /tmp/lint-output.txt | grep -A20 "YourFile.vue$" | head -25

# Run --fix for auto-fixable errors (safe)
npm run lint -- --fix

# Find case declarations by file
awk '/^\/home.*\.(vue|ts)$/ { file=$0 } /no-case-declarations/ { print file }' /tmp/lint-output.txt | sort -u

Common Gotchas

  1. Multiple Matches: Add more surrounding context to make match unique
  2. Variable Used in Template: Check
    <template>
    section before prefixing
  3. Exported but Appears Unused: Don't prefix exports - used externally
  4. Store/Composable Return Values: Check if values are returned for consumers
  5. Case Block Fallthrough: Ensure
    break
    is inside the
    {}
    braces
  6. Factory Functions for Props: Arrays/objects need
    () => []
    not
    []

See

lint-cleanup-guide.md
for complete documentation.