Skip to content
config-hygiene logo

Configuration Hygiene Fixes

config-hygiene

Fixes configuration hygiene issues including gitignore patterns, ESLint config duplication, and hook scripts. Use when encountering backup files in repo, missing gitignore patterns, or config maintenance issues.

SKILL.md

Full skill instructions

Configuration Hygiene Fixes

Fixes for project configuration issues. Clean configs prevent noise, ensure consistency, and improve developer experience.

Quick Start

  1. Identify the config issue (gitignore, ESLint, husky)
  2. Apply the recommended fix
  3. Verify no unintended side effects
  4. Commit config changes

Priority Matrix

IssuePriorityImpact
Backup files in repoP2Noise, confusion
Missing gitignore patternsP2Unwanted files tracked
Husky silent failureP2Hidden hook failures
ESLint config duplicationP3Maintenance burden
Permissive lint thresholdP2Quality regression

Workflows

Backup/​Artifact Files in Repository (#35 - 12 occurrences)

Detection: Files matching *.bak, *.orig, *~ patterns.

Pattern: Editor/​merge artifacts committed to repo.

Fix Strategy: Remove from git, add to gitignore.

# Remove from git (keep locally)
git rm --cached "*.bak"
git rm --cached "*.orig"
git rm --cached "*~"

# Add to .gitignore
echo "*.bak" >> .gitignore
echo "*.orig" >> .gitignore
echo "*~" >> .gitignore

# Commit
git add .gitignore
git commit -m "chore: ignore backup/​artifact files"

Missing .gitignore Patterns (#36 - 8 occurrences)

Detection: Common patterns not in .gitignore.

Fix Strategy: Add comprehensive patterns.

# Editor artifacts
*.swp
*.swo
*~
*.bak
*.orig

# OS files
.DS_Store
Thumbs.db

# IDE
.idea/
.vscode/
*.sublime-*

# Build outputs
dist/
build/
*.tsbuildinfo

# Dependencies
node_modules/

# Environment
.env
.env.*
!.env.example

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Test coverage
coverage/
.nyc_output/

# Cache
.cache/
.eslintcache
.parcel-cache/

Template: See templates/​gitignore-node.txt for complete Node.js template.


Husky Prepare Script Silent Failure (#37 - 1 occurrence)

Detection: prepare script uses || true fallback.

Pattern: Hook installation fails silently.

// PROBLEM - hides failures
{
  "scripts": {
    "prepare": "husky install || true"
  }
}

Fix Strategy 1: Conditional execution based on CI.

// SOLUTION - check CI environment
{
  "scripts": {
    "prepare": "node -e \"if (process.env.CI !== 'true') require('husky').install()\""
  }
}

Fix Strategy 2: Use is-ci package.

npm install --save-dev is-ci
{
  "scripts": {
    "prepare": "is-ci || husky install"
  }
}

Fix Strategy 3: Husky v9+ auto-setup.

// Husky v9 uses .husky/​_/​husky.sh automatically
{
  "scripts": {
    "prepare": "husky"
  }
}

Permissive lint:strict Threshold (#38 - 1 occurrence)

Detection: High --max-warnings value in lint script.

Pattern: Too many warnings allowed.

// PROBLEM - too permissive
{
  "scripts": {
    "lint:strict": "eslint . --max-warnings 500"
  }
}

Fix Strategy: Progressive reduction.

// Week 1: Lower to current count + small buffer
{
  "scripts": {
    "lint:strict": "eslint . --max-warnings 350"
  }
}

// Week 2: Lower further
{
  "scripts": {
    "lint:strict": "eslint . --max-warnings 200"
  }
}

// Target: Zero tolerance
{
  "scripts": {
    "lint:strict": "eslint . --max-warnings 0"
  }
}

Tracking Progress:

# Get current warning count
npx eslint . 2>&1 | tail -1
# Output: "X warnings" or "X problems (Y errors, Z warnings)"

ESLint Config Duplication (#39, #40)

Issue #39: Repeated plugin/​globals definitions.

// PROBLEM - repeated in multiple blocks
export default [
  {
    files: ['**/​*.ts'],
    plugins: { '@typescript-eslint': tsPlugin },
  },
  {
    files: ['**/​*.tsx'],
    plugins: { '@typescript-eslint': tsPlugin },  // Duplicated
  },
];

Fix Strategy: Extract shared config.

// SOLUTION - shared base config
const baseTypescriptConfig = {
  plugins: {
    '@typescript-eslint': tsPlugin,
  },
  languageOptions: {
    parser: tsParser,
    parserOptions: {
      project: './​tsconfig.json',
    },
  },
};

export default [
  {
    files: ['**/​*.ts'],
    ...baseTypescriptConfig,
    rules: { /​* ts-specific rules */ },
  },
  {
    files: ['**/​*.tsx'],
    ...baseTypescriptConfig,
    rules: { /​* tsx-specific rules */ },
  },
];

Issue #40: Disabled rules duplicated across blocks.

// PROBLEM - duplicated disabled rules
{
  rules: {
    '@typescript-eslint/​no-explicit-any': 'off',
    '@typescript-eslint/​no-unsafe-assignment': 'off',
  },
},

Fix Strategy: Extract to named constant with documentation.

// SOLUTION - extracted with docs
/​**
 * Rules disabled during migration to strict TypeScript.
 * TODO: Re-enable progressively - see issue #456
 */
const migrationDisabledRules = {
  '@typescript-eslint/​no-explicit-any': 'off',
  '@typescript-eslint/​no-unsafe-assignment': 'off',
  '@typescript-eslint/​no-unsafe-member-access': 'off',
} as const;

export default [
  {
    files: ['**/​*.ts'],
    rules: {
      ...migrationDisabledRules,
      // ts-specific rules
    },
  },
];

Recursive Directory Walking Without Limits (#23 - 1 occurrence)

Pattern: Unbounded recursion in file walking.

// PROBLEM - no limits
async function walkDir(dir: string): Promise<string[]> {
  const entries = await fs.readdir(dir, { withFileTypes: true });
  const files: string[] = [];
  for (const entry of entries) {
    if (entry.isDirectory()) {
      files.push(...await walkDir(path.join(dir, entry.name))); // No limit!
    }
  }
  return files;
}

Fix Strategy: Add depth limit and visited tracking.

// SOLUTION - with limits
interface WalkOptions {
  maxDepth?: number;
  maxFiles?: number;
}

async function walkDir(
  dir: string,
  options: WalkOptions = {},
  depth = 0,
  visited = new Set<string>()
): Promise<string[]> {
  const { maxDepth = 10, maxFiles = 10000 } = options;

  if (depth > maxDepth) {
    return [];
  }

  const realPath = await fs.realpath(dir);
  if (visited.has(realPath)) {
    return []; // Circular symlink
  }
  visited.add(realPath);

  const entries = await fs.readdir(dir, { withFileTypes: true });
  const files: string[] = [];

  for (const entry of entries) {
    if (files.length >= maxFiles) break;

    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      files.push(...await walkDir(fullPath, options, depth + 1, visited));
    } else {
      files.push(fullPath);
    }
  }

  return files;
}

Regex Created Per-Match (#24 - 1 occurrence)

Pattern: Regex compiled on every function call.

// PROBLEM - regex created every call
function containsKeyword(text: string, keyword: string): boolean {
  const regex = new RegExp(`\\b${keyword}\\b`, 'i');
  return regex.test(text);
}

Fix Strategy: Pre-compile and cache.

// SOLUTION - cached regex
const keywordRegexCache = new Map<string, RegExp>();

function getKeywordRegex(keyword: string): RegExp {
  let regex = keywordRegexCache.get(keyword);
  if (!regex) {
    regex = new RegExp(`\\b${escapeRegex(keyword)}\\b`, 'i');
    keywordRegexCache.set(keyword, regex);
  }
  return regex;
}

function escapeRegex(str: string): string {
  return str.replace(/[.*+?^${}()|[\]\\]/​g, '\\$&');
}

function containsKeyword(text: string, keyword: string): boolean {
  return getKeywordRegex(keyword).test(text);
}

Scripts

Check Config Hygiene

node scripts/​check-config.js

Fix Gitignore

node scripts/​fix-gitignore.js

Templates

Node.js .gitignore

See templates/​gitignore-node.txt

ESLint Base Config

See templates/​eslint-base.js


CI/​CD Considerations

Ensuring Hooks Run

# GitHub Actions
- name: Install dependencies
  run: npm ci

# This runs "prepare" script which installs husky
# Make sure CI=true is set to skip if needed

Lint in CI

- name: Lint
  run: npm run lint:strict
  # Fails if warnings exceed threshold

Progressive Strictness

# Allow gradual improvement
- name: Check lint progress
  run: |
    WARNINGS=$(npx eslint . 2>&1 | grep -oP '\d+ warning' | grep -oP '\d+' || echo "0")
    THRESHOLD=200
    if [ "$WARNINGS" -gt "$THRESHOLD" ]; then
      echo "Too many warnings: $WARNINGS (max: $THRESHOLD)"
      exit 1
    fi

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View