This skill should be used when the user asks to "set up code quality", "configure git hooks", "add pre-commit hooks", "set up lint-staged", "add pre-push checks", "initialize code quality", or when starting a new project that needs quality gates.
From code-qualitynpx claudepluginhub nthplusio/functional-claude --plugin code-qualityThis skill uses the workspace's default tool permissions.
Implements CQRS patterns with Python templates for command/query separation, event-sourcing, and scalable read/write models. Use for optimizing queries or independent scaling.
Implements Clean Architecture, Hexagonal Architecture (ports/adapters), and Domain-Driven Design for backend services. For microservice design, monolith refactoring to bounded contexts, and dependency debugging.
Provides REST and GraphQL API design principles including resource hierarchies, HTTP methods, versioning strategies, pagination, and filtering patterns for new APIs, reviews, or standards.
Guided workflow to detect your ecosystem, recommend a git hook framework, and configure deterministic quality infrastructure.
Scan the project for ecosystems, existing quality tools, hook infrastructure, and CI configs.
Detection matrix:
| Category | What to Find |
|---|---|
| Ecosystems | package.json, tsconfig.json, pyproject.toml, Cargo.toml, go.mod |
| Package managers | pnpm-lock.yaml, yarn.lock, bun.lockb, package-lock.json |
| Existing hooks | .husky/, lefthook.yml, .pre-commit-config.yaml, .git/hooks/pre-commit, .githooks/ |
| Linters | eslint.config.*, .eslintrc*, biome.json, ruff.toml, .golangci.yml, .golangci.yaml |
| Formatters | .prettierrc*, biome.json (dual-use), rustfmt.toml |
| Type checkers | tsconfig.json, mypy.ini, pyrightconfig.json |
| lint-staged | lint-staged key in package.json, .lintstagedrc* |
| CI | .github/workflows/, .gitlab-ci.yml |
Run detection:
# Ecosystems and package managers
ls package.json tsconfig.json pyproject.toml Cargo.toml go.mod pnpm-lock.yaml yarn.lock bun.lockb package-lock.json 2>/dev/null
# Existing hook infrastructure
ls -d .husky lefthook.yml lefthook.yaml .pre-commit-config.yaml .githooks 2>/dev/null
ls .git/hooks/pre-commit .git/hooks/pre-push 2>/dev/null
# Check if git hooks are executable (not just samples)
file .git/hooks/pre-commit 2>/dev/null
# Linters and formatters
ls eslint.config.* .eslintrc* biome.json ruff.toml .golangci.yml .golangci.yaml .prettierrc* rustfmt.toml 2>/dev/null
# Type checkers
ls tsconfig.json mypy.ini pyrightconfig.json 2>/dev/null
# lint-staged
grep -l "lint-staged" package.json 2>/dev/null
ls .lintstagedrc* 2>/dev/null
# CI
ls -d .github/workflows .gitlab-ci.yml 2>/dev/null
# Legacy config (migration detection)
ls .claude/pre-commit.json 2>/dev/null
If package.json exists, also check scripts and dependencies:
# Check for relevant scripts
node -e "const p=require('./package.json'); console.log(JSON.stringify({scripts:Object.keys(p.scripts||{}),devDeps:Object.keys(p.devDependencies||{}),deps:Object.keys(p.dependencies||{})}))"
Select a git hook framework using this opinionated decision tree:
Existing hook framework detected?
├── YES → Use existing (husky, lefthook, pre-commit, etc.)
│ Tell the user what was found, offer to add/modify hooks
└── NO →
├── JS/TS project (package.json)?
│ ├── YES → Monorepo (pnpm-workspace.yaml, nx.json, lerna.json)?
│ │ ├── YES → lefthook (better monorepo support, no npm lifecycle dep)
│ │ └── NO → husky (most popular JS ecosystem, simple setup)
│ └── NO →
│ ├── Python project (pyproject.toml)?
│ │ └── YES → pre-commit framework (best polyglot support)
│ └── Rust/Go/other?
│ └── YES → Simple shell scripts (.githooks/ + core.hooksPath)
└── No project files found → Ask user about their ecosystem
Present the recommendation to the user with AskUserQuestion:
Hook content strategy:
| Hook | What to Run | Why |
|---|---|---|
| Pre-commit | Formatters + linters on staged files only | Fast feedback, incremental via lint-staged |
| Pre-push | Type checking + build + tests | Comprehensive, slower, runs on full codebase |
lint-staged recommendations per ecosystem:
For JS/TS projects:
biome check --writeeslint --fix then prettier --writeeslint --fixFor Python projects:
ruff check --fix then ruff formatblack then flake8Install the chosen framework and create hook scripts.
# Detect package manager
PM="npm"
[ -f "pnpm-lock.yaml" ] && PM="pnpm"
[ -f "yarn.lock" ] && PM="yarn"
[ -f "bun.lockb" ] && PM="bun"
# Install husky
$PM add -D husky
# Initialize husky
npx husky init
Create .husky/pre-commit:
npx lint-staged
Create .husky/pre-push:
# Type checking
npm run typecheck 2>/dev/null || npx tsc --noEmit
# Build
npm run build
# Tests
npm test
Adapt the pre-push script based on what was detected in Step 1. Only include checks that have corresponding tools installed. Use the project's actual script names from package.json.
Install lint-staged:
$PM add -D lint-staged
Add lint-staged config to package.json or create .lintstagedrc.json:
{
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,yml,yaml}": ["prettier --write"]
}
Or with Biome:
{
"*.{js,jsx,ts,tsx,json}": ["biome check --write --no-errors-on-unmatched"]
}
Ensure prepare script exists in package.json:
{
"scripts": {
"prepare": "husky"
}
}
# Install lefthook
$PM add -D lefthook
# Initialize
npx lefthook install
Create lefthook.yml:
pre-commit:
parallel: true
commands:
lint:
glob: "*.{js,jsx,ts,tsx}"
run: npx eslint --fix {staged_files} && git add {staged_files}
format:
glob: "*.{js,jsx,ts,tsx,json,md,yml,yaml}"
run: npx prettier --write {staged_files} && git add {staged_files}
pre-push:
commands:
typecheck:
run: npm run typecheck
build:
run: npm run build
test:
run: npm test
pip install pre-commit
Create .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0 # Check for latest version
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0 # Check for latest version
hooks:
- id: mypy
additional_dependencies: []
pre-commit install
Create .githooks/pre-commit:
#!/bin/sh
set -e
# Rust
if [ -f "Cargo.toml" ]; then
cargo fmt -- --check
cargo clippy -- -D warnings
fi
# Go
if [ -f "go.mod" ]; then
gofmt -l . | grep -q . && echo "Files need formatting" && exit 1
golangci-lint run 2>/dev/null || true
fi
Create .githooks/pre-push:
#!/bin/sh
set -e
# Rust
if [ -f "Cargo.toml" ]; then
cargo check
cargo test
fi
# Go
if [ -f "go.mod" ]; then
go vet ./...
go test ./...
fi
chmod +x .githooks/pre-commit .githooks/pre-push
git config core.hooksPath .githooks
After setup completes, provide a summary:
## Code Quality Setup Complete
### Framework: [husky/lefthook/pre-commit/shell scripts]
### Pre-commit hooks (run on every commit)
- [formatter] on staged [file types]
- [linter] on staged [file types]
### Pre-push hooks (run on every push)
- [typecheck command]
- [build command]
- [test command]
### Files created/modified
- [list of files]
### Customizing
- Edit [hook config location] to modify checks
- Edit [lint-staged config location] to change staged file processing
- See `code-quality-hooks` skill for framework-specific deep dives
- See `code-quality-lint` skill for linter/formatter configuration
### Testing your hooks
```bash
# Test pre-commit hook
git add . && git commit --dry-run
# Test pre-push hook
git push --dry-run
## Migration from Legacy `.claude/pre-commit.json`
If a `.claude/pre-commit.json` file is detected:
1. **Read the existing config** to understand what checks are defined
2. **Map old checks to new hooks:**
- `typecheck` → pre-push hook
- `lint` → pre-commit hook (lint-staged for staged files) + pre-push hook (full check)
- `build` → pre-push hook
- `test` → pre-push hook
3. **Set up the real hooks** using the workflow above, with commands from the legacy config
4. **After confirming hooks work**, offer to remove `.claude/pre-commit.json`
5. **Explain the shift**: "Previously these checks only ran when Claude pushed. Now they run on every push by any developer."
## Multi-Ecosystem Projects
For projects with multiple ecosystems (e.g., JS frontend + Python backend):
1. Detect all ecosystems present
2. Use the **most capable framework** that spans them:
- If JS + Python → pre-commit framework (best polyglot) or lefthook (flexible globs)
- If JS + Rust/Go → lefthook (language-agnostic commands)
3. Configure separate commands per ecosystem in the hook config
4. Use glob patterns to route files to the right tools