| name | linter-driven-development |
| description | META ORCHESTRATOR for complete implementation workflow - design, test, lint, refactor, review, commit. Use for any code change that should result in a commit (features, bug fixes, refactors). Ensures clean code with tests, linting passes, and design validation. |
Linter-Driven Development Workflow (TypeScript + React)
DEFAULT ENTRY POINT: This skill should be automatically invoked for ALL code changes when the plugin is enabled.
META ORCHESTRATOR for implementation workflow: design → test → lint → refactor → review → commit.
Use for any commit: features, bug fixes, refactors.
Auto-Invocation
When this plugin is enabled in a project, this skill is the default workflow for:
- New feature implementation
- Bug fixes
- Refactoring
- Any code change that should result in a commit
The CLAUDE.md file at the plugin root enforces this automatic invocation.
Core Principles
CRITICAL - Read Before Starting:
-
Never Disable Rules by Default
- DO NOT add
eslint-disable, @ts-ignore, @ts-expect-error, or similar comments without explicit user approval
- ALWAYS strive to fix the underlying issue through refactoring, not by suppressing warnings
- ONLY disable rules as an absolute last resort when no other solution exists, and always ask user first
- When approved: Add a comment explaining WHY the rule is disabled
-
Fix, Don't Suppress
- Linter warnings exist for good reasons - they indicate real issues
- Use @refactoring patterns to address complexity and code quality issues
- If a rule seems wrong for the project, discuss with user rather than silently disabling
-
Clean Code at Every Step
- All checks must pass without suppressions before commit
- Tests pass, linter passes, types pass - no exceptions
Prerequisites
IMPORTANT: Before using this skill, the project MUST have linter configurations:
Required Configurations
-
TypeScript (tsconfig.json)
- Type checking configured for your project
-
ESLint (eslint.config.mjs or .eslintrc.js)
- Must include
eslint-plugin-sonarjs for complexity metrics
- Recommended: TypeScript ESLint, React plugins
- Complexity thresholds: cognitive, cyclomatic, expression
-
Prettier (.prettierrc.json or prettier.config.js or .prettierrc)
- Consistent formatting rules defined
- Integration with ESLint recommended
-
Stylelint (stylelint.config.js) - if using CSS/SCSS
- CSS/SCSS linting rules configured
Required npm Scripts
Project must have scripts for running quality checks. Script names vary by project - detect them from package.json.
Common patterns to look for:
- Testing:
test, test:unit, vitest, jest
- Type checking:
typecheck, type-check, tsc, check-types
- Linting (check):
lint, lint:check, eslint, lintcheck
- Linting (fix):
lint:fix, eslint:fix, lint --fix
- Formatting (check):
format, format:check, prettier:check, formatcheck
- Formatting (fix):
format:fix, prettier:write, prettier --write
- Styling (check):
stylelint, style:check, stylecheck
- Styling (fix):
stylelint:fix, style:fix
- Combined check:
check, checkall, validate, verify
- Combined fix:
fix, fixall, format:all
Detection strategy: Read package.json scripts and identify which commands serve each purpose.
Step 0: Detect Project Setup
FIRST STEP - Do this before starting any workflow:
-
Detect Package Manager
- Check for lock files in project root:
yarn.lock → Use yarn commands
package-lock.json or npm-shrinkwrap.json → Use npm commands
pnpm-lock.yaml → Use pnpm commands
- No lock file → Ask user which package manager to use
-
Detect Available Scripts
- Read
package.json scripts section
- Identify which scripts exist for each purpose:
- Type checking (e.g.,
typecheck, type-check, tsc)
- Linting check (e.g.,
lint, eslint, lint:check)
- Linting fix (e.g.,
lint:fix, eslint:fix)
- Formatting check (e.g.,
format:check, prettier:check)
- Formatting fix (e.g.,
format:fix, prettier:write)
- Testing (e.g.,
test, vitest, jest)
- Combined checks (e.g.,
check, checkall, validate)
- Combined fixes (e.g.,
fix, fixall)
-
Build Command Map
- Store detected commands for use throughout workflow
- Example:
{ typecheck: 'typecheck', lint: 'lint', lintFix: 'lint:fix', test: 'test' }
Remember: Use detected package manager + detected script names consistently throughout ALL workflow phases.
Verification
Before starting, verify setup by running detected commands:
If scripts are missing:
- Check if functionality exists but with different script name
- Look for combined commands (e.g.,
check that runs multiple tools)
- If truly missing, ask user:
- "What command should I run to check/fix linting?"
- "Where is this documented?" (suggest adding to README.md or CLAUDE.md)
- If no script exists, run tool directly (e.g.,
eslint .) or skip that phase
Command detection examples:
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"check": "tsc && eslint .",
"test": "vitest"
}
typecheck: (not found, will run 'tsc' directly)
lint: 'lint'
lintFix: 'lint:fix'
test: 'test'
combined: 'check'
When to Use
- Implementing any code change that should result in a commit
- Need automatic workflow management with quality gates
- Want to ensure: clean code + tests + linting + design validation + accessibility
Workflow Phases
IMPORTANT: Start every workflow by detecting the package manager (Step 0 in Prerequisites).
Phase 1: Design (if needed)
- If new components/types/major changes needed → invoke @component-designing skill
- Output: Component design plan with types, hooks, and structure
Phase 2: Implementation
- Follow @testing skill principles (React Testing Library with Jest/Vitest)
- Write tests + implementation in parallel (not necessarily test-first)
- Follow project's Prettier/ESLint formatting rules
- Use project's test runner (Jest, Vitest, or other)
- Aim for 100% coverage on new leaf components/hooks (pure logic with no external dependencies)
- Leaf types: Pure logic (can compose other leaf types), no API/DB/file system access
- Orchestrating types: Coordinate leaf types and external systems, need integration tests
- Test from user perspective (public API only)
Phase 3: Linter Loop
Use detected package manager and script names from Step 0 for all commands below.
Run quality checks in this order (using detected script names from package.json):
- Type Check: Run detected typecheck script (look for:
typecheck, type-check, tsc)
- Lint Check: Run detected lint check script (look for:
lint, lint:check, eslint)
- Format Check: Run detected format check script (look for:
format:check, prettier:check)
- Style Check: Run detected style check script (look for:
stylelint, style:check) - if CSS/SCSS in project
Handling missing scripts:
- If type check script not found → Run
tsc --noEmit directly
- If lint check script not found → Run
eslint . directly
- If format check script not found → Run
prettier --check . directly
- If style check script not found and CSS/SCSS exists → Skip if Stylelint not installed
If any failures detected:
- Run auto-fixes using detected fix scripts:
- Lint fix: Run detected lint fix script (look for:
lint:fix, eslint:fix)
- Format fix: Run detected format fix script (look for:
format:fix, prettier:write)
- Style fix: Run detected style fix script (look for:
stylelint:fix, style:fix)
- Re-run quality checks
- If still failing (complexity, design issues):
- NEVER disable linter rules by default: Do NOT add
eslint-disable, @ts-ignore, @ts-expect-error, or similar comments unless explicitly approved by the user
- Always fix, not disable: Strive to fix the underlying issue through refactoring, not by suppressing warnings
- Only disable as last resort: If absolutely necessary and no other solution exists, ask user for explicit approval before disabling any rule
- When approved: Add a comment explaining WHY the rule is disabled
- Interpret failures (cognitive complexity, cyclomatic complexity, etc.)
- Invoke @refactoring skill to fix (use storifying, extract functions/hooks, early returns)
- Check for existing utilities: Before creating new helpers, check if type guards, utilities, or constants already exist in the codebase
- Avoid repeated
typeof checks: Use or create type guard utilities (e.g., isString, isNumber) instead of repeating typeof value === 'string'
- Re-run checks
- Repeat until all checks pass clean
Alternative: If project has combined commands (detected in Step 0):
- Check: Use detected combined check script
- Fix: Use detected combined fix script
Example workflow:
# Step 0: Detect commands from package.json
# Found: { packageManager: 'npm', typecheck: 'typecheck', lint: 'lint', lintFix: 'lint:fix', ... }
# Run checks using detected script names
[package-manager] run [detected-typecheck-script]
[package-manager] run [detected-lint-script]
[package-manager] run [detected-format-check-script]
# If failures, run fixes using detected fix scripts
[package-manager] run [detected-lint-fix-script]
[package-manager] run [detected-format-fix-script]
# Re-run checks to verify
[package-manager] run [detected-typecheck-script]
[package-manager] run [detected-lint-script]
[package-manager] run [detected-format-check-script]
Phase 4: Pre-Commit Design Review (ADVISORY)
- Invoke @pre-commit-review skill
- Review validates design principles (not code correctness)
- Includes accessibility checks (ARIA, semantic HTML, keyboard nav)
- Categorized findings: Design Debt / Readability Debt / Polish Opportunities
- If issues found in broader file context, flag for potential refactor
- User decides: commit as-is, apply fixes, or expand scope
Phase 5: Commit Ready
- Type checking passes ✅
- ESLint passes ✅
- Prettier passes ✅
- Stylelint passes ✅
- Tests pass with target coverage ✅
- Design review complete (advisory) ✅
- Present summary + commit message suggestion
Output Format
📋 COMMIT READINESS SUMMARY
✅ Type Check: Passed (0 errors)
✅ ESLint: Passed (0 issues)
✅ Prettier: Passed (all files formatted)
✅ Stylelint: Passed (0 style issues)
✅ Tests: 92% coverage (3 leaf hooks at 100%, 1 orchestrating component, 18 test cases)
⚠️ Design Review: 3 findings (see below)
🎯 COMMIT SCOPE
Modified:
- src/components/LoginForm.tsx (+65, -20 lines)
- src/hooks/useAuth.ts (+30, -5 lines)
Added:
- src/types/auth.ts (new: UserId, Email types)
- src/contexts/AuthContext.tsx (new context provider)
Tests:
- src/components/LoginForm.test.tsx (+95 lines)
- src/hooks/useAuth.test.ts (new)
- src/types/auth.test.ts (new)
⚠️ DESIGN REVIEW FINDINGS
🔴 DESIGN DEBT (Recommended to fix):
- src/components/LoginForm.tsx:45 - Primitive obsession detected
Current: function validateEmail(email: string): boolean
Better: Use Zod schema or branded Email type with validation
Why: Type safety, validation guarantee, prevents invalid emails
Fix: Use @component-designing to create self-validating Email type
- src/hooks/useAuth.ts:78 - Prop drilling detected
Auth state passed through 3+ component levels
Why: Tight coupling, hard to maintain
Fix: Extract AuthContext or use composition pattern
🟡 READABILITY DEBT (Consider fixing):
- src/components/LoginForm.tsx:120 - Mixed abstraction levels
Component mixes validation logic with UI rendering
Why: Harder to understand and test independently
Fix: Use @refactoring to extract custom hooks (useValidation)
- src/components/LoginForm.tsx:88 - Cognitive complexity: 18 (max: 15)
Nested conditionals for form validation
Why: Hard to understand logic flow
Fix: Use @refactoring to extract validation functions or use Zod
🟢 POLISH OPPORTUNITIES:
- src/types/auth.ts:12 - Missing JSDoc comments
Public types should have documentation
- src/components/LoginForm.tsx:45 - Consider semantic HTML
Use <form> with proper ARIA labels for better accessibility
- src/hooks/useAuth.ts:34 - Missing error boundaries
Consider wrapping async operations with error handling
📝 BROADER CONTEXT:
While reviewing LoginForm.tsx, noticed similar validation patterns in
RegisterForm.tsx and ProfileForm.tsx (src/components/). Consider
extracting a shared validation hook or creating branded types for common
fields (Email, Username, Password) used across the application.
💡 SUGGESTED COMMIT MESSAGE
Add self-validating Email and UserId types to auth feature
- Introduce Email type with RFC 5322 validation using Zod
- Introduce UserId branded type for type safety
- Refactor LoginForm to use validated types
- Extract useAuth hook for auth state management
- Add AuthContext to eliminate prop drilling
- Achieve 92% test coverage with React Testing Library
Follows component composition principles and reduces primitive obsession.
────────────────────────────────────────
Would you like to:
1. Commit as-is (ignore design findings)
2. Fix design debt only (🔴), then commit
3. Fix design + readability debt (🔴 + 🟡), then commit
4. Fix all findings (🔴 🟡 🟢), then commit
5. Refactor broader scope (address validation patterns across features), then commit
Complexity Thresholds (SonarJS)
These metrics trigger @refactoring when exceeded:
- Cognitive Complexity: max 15 (how hard to understand)
- Cyclomatic Complexity: max 10 (number of paths through code)
- Expression Complexity: max 5 (operators in single expression)
- Function Length: max 200 lines
- File Length: max 600 lines
- Nesting Level: max 4 (depth of nested control structures)
- Max Union Size: max 4 types (union types with too many options)
Priority Levels
🔴 High Priority: Type Safety Issues
Rules that can cause runtime errors:
@typescript-eslint/no-unsafe-member-access (416 violations)
@typescript-eslint/no-unsafe-assignment (267 violations)
@typescript-eslint/no-explicit-any (194 violations)
@typescript-eslint/no-unsafe-argument (101 violations)
@typescript-eslint/no-unsafe-call (72 violations)
@typescript-eslint/no-unsafe-return (50 violations)
Fix Strategy: Use proper types, type guards, Zod schemas, or branded types
🟡 Medium Priority: Code Quality & Maintainability
Rules that affect readability and maintenance:
no-magic-numbers (243 violations) - Extract to named constants
react/forbid-dom-props (94 violations) - No inline styles, use CSS modules
sonarjs/cyclomatic-complexity (34 violations) - Reduce branches, early returns
sonarjs/prefer-read-only-props (25 violations) - Props should be immutable
react-hooks/exhaustive-deps (41 violations) - Fix dependencies or simplify
Fix Strategy: Apply @refactoring patterns (storifying, early returns, extract functions)
🟢 Low Priority: Style & Convention
Rules that improve consistency:
no-console (28 violations) - Use proper logging
- Import/export conventions
- Styling conventions (camelCase, keyframes naming)
Fix Strategy: Auto-fix or manual cleanup
Workflow Control
Sequential Phases: Each phase depends on previous phase completion
- Design must complete before implementation
- Implementation must complete before linting
- Linting must pass before review
- Review must complete before commit
Iterative Linting: Phase 3 loops until clean
Advisory Review: Phase 4 never blocks, always asks user
Integration with Other Skills
This orchestrator invokes other skills automatically:
- @component-designing (Phase 1, if needed)
- @testing (Phase 2, principles applied)
- @refactoring (Phase 3, when linter fails on complexity)
- @pre-commit-review (Phase 4, always)
After committing, consider:
- If feature complete → invoke @documentation skill
- If more work needed → run this workflow again for next commit
Common Linter Failures and Resolutions
TypeScript Errors (detected typecheck script)
- Type mismatches → Fix types or add proper type guards
- Missing types → Add explicit types or interfaces
- Cannot fix automatically → Manual intervention required
ESLint Failures (detected lint check script)
Auto-fixable:
- Import sorting (simple-import-sort)
- Unused imports (unused-imports)
- Formatting issues covered by Prettier
- Simple style violations
Requires refactoring (invoke @refactoring):
- Cognitive/cyclomatic complexity
- Max lines per function
- Expression complexity
- Nested control flow
- React hooks violations
- Component design issues
Prettier Failures (detected format check script)
- Always auto-fixable with detected format fix script or
prettier --write .
- No manual intervention needed
Stylelint Failures (detected style check script)
- Most auto-fixable with detected style fix script or
stylelint "**/*.{css,scss}" --fix
- Class naming violations may require manual fixes
Best Practices
- Run checks frequently during development
- Fix one complexity issue at a time (don't batch refactoring)
- Trust the advisory review (design debt causes future pain)
- Test after each refactoring (ensure behavior unchanged)
- Commit frequently (small, focused commits)
Implementation Phases
Phase 1: Type Safety Foundation (🔴 High Priority)
Phase 2: Code Quality (🟡 Medium Priority)
Phase 3: Polish (🟢 Low Priority)
Acceptance Criteria
CRITICAL: All criteria must be met before completing this skill.
Mandatory Requirements (Must Pass)
-
No Linter Rule Disabling in Changed Files
-
All Quality Checks Pass Clean
-
All Tests Pass
-
Iterative Verification
Verification Workflow
IMPORTANT: Detect available scripts from the project's package.json before running checks.
# Iteration 1: Initial check
Run all quality check commands detected from package.json:
- TypeScript check (e.g., typecheck, type-check, tsc)
- Linting check (e.g., lint, lint:check, eslint)
- Format check (e.g., format:check, prettier:check)
- Tests (e.g., test, test:unit, vitest)
# If failures: fix issues, then...
# Iteration 2: Verify fixes didn't introduce new issues
Run the same quality check commands again
# If still clean: proceed to commit
# If new failures: fix and repeat until two consecutive clean runs
Pre-Commit Checklist
Before marking workflow complete:
✅ ACCEPTANCE CRITERIA CHECKLIST
Linter Compliance:
[ ] No eslint-disable comments added to changed files
[ ] No @ts-ignore/@ts-expect-error added to changed files
[ ] All linter issues fixed through proper refactoring
[ ] If any disabling approved: comment explains WHY
Quality Gates:
[ ] TypeScript: 0 errors
[ ] ESLint: 0 errors/warnings in changed files
[ ] Prettier: All files formatted
[ ] Tests: All passing
Iteration Verification:
[ ] Ran checks twice consecutively
[ ] Both runs passed clean
[ ] No oscillating fixes (fix A breaks B, fix B breaks A)
Ready to commit: All boxes checked ✅
What Blocks Completion
The following will BLOCK skill completion:
- Any new linter disabling comment in changed files (without explicit user approval)
- Any failing quality check (typecheck, lint, format, test)
- Single-run verification (must run checks twice)
- Unresolved complexity issues (must refactor, not disable)
Acceptable Exceptions (Require User Approval)
Only with explicit user consent:
- Disabling a rule for a specific line with documented justification
- Skipping a quality check due to known project issues
- Accepting technical debt with plan to address later
When disabling a rule with approval, add a comment explaining WHY:
const data: any = response.body
const data: any = response.body
Document any exceptions in commit message.
Additional Resources
- Common Linter Failures section above for resolution strategies
- @refactoring skill - For complexity issues (cognitive, cyclomatic, expression)
- @component-designing skill - For type safety and architecture issues
- @pre-commit-review skill - For design validation (runs automatically in Phase 4)