home / skills / levnikolaevich / claude-code-skills / ln-742-precommit-setup

ln-742-precommit-setup skill

/ln-742-precommit-setup

This skill configures Git hooks and pre-commit checks to enforce code quality before commits, adapting to Node.js, Python, or mixed stacks.

npx playbooks add skill levnikolaevich/claude-code-skills --skill ln-742-precommit-setup

Review the files below or copy the command above to add this skill to your agents.

Files (8)
SKILL.md
6.1 KB
---
name: ln-742-precommit-setup
description: Configures Husky, lint-staged, commitlint, and Python pre-commit
---

> **Paths:** File paths (`shared/`, `references/`, `../ln-*`) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root.

# ln-742-precommit-setup

**Type:** L3 Worker
**Category:** 7XX Project Bootstrap
**Parent:** ln-740-quality-setup

Sets up Git hooks for automated code quality enforcement before commits.

---

## Purpose & Scope

**Does:**
- Installs hook management tools (Husky or pre-commit)
- Configures staged file linting (lint-staged or pre-commit hooks)
- Sets up commit message validation (commitlint)
- Verifies hooks trigger correctly

**Does NOT:**
- Configure linters themselves (ln-741 does this)
- Set up test infrastructure (ln-743 does this)
- Modify source code

---

## Supported Stacks

| Technology | Hook Manager | Staged Linting | Commit Validation |
|------------|--------------|----------------|-------------------|
| Node.js | Husky | lint-staged | commitlint |
| Python | pre-commit | pre-commit hooks | pre-commit hook |
| Mixed | Both (if needed) | Stack-specific | commitlint |

---

## Phase 1: Check Existing Hooks

Before installing, check for existing hook configurations.

**Files to Check:**

| Tool | Indicators |
|------|------------|
| Husky | `.husky/` directory, `husky` in package.json |
| pre-commit | `.pre-commit-config.yaml` |
| lint-staged | `lint-staged` in package.json or `.lintstagedrc*` |
| commitlint | `commitlint.config.*`, `.commitlintrc*` |

**Decision Logic:**
1. If hooks exist and working: **SKIP** (inform user)
2. If partial setup: **ASK** user to complete or replace
3. If no hooks: **CREATE** from templates

---

## Phase 2: Install Hook Manager

### Node.js Projects (Husky)

```bash
npm install -D husky
npx husky init
```

This creates:
- `.husky/` directory
- `.husky/pre-commit` hook file
- Adds `prepare` script to package.json

### Python Projects (pre-commit)

```bash
pip install pre-commit
# OR with uv:
uv add --dev pre-commit

pre-commit install
```

This creates:
- `.git/hooks/pre-commit` (managed by pre-commit)
- Requires `.pre-commit-config.yaml` for configuration

---

## Phase 3: Configure Staged Linting

### Node.js (lint-staged)

```bash
npm install -D lint-staged
```

Create configuration (`.lintstagedrc.mjs` or in package.json):

**Key Rules:**
- TypeScript files: ESLint + Prettier
- JSON/MD/CSS: Prettier only
- C# files: dotnet format (if mixed project)

> **CRITICAL FIX:** For .NET files, use correct syntax:
> `"*.cs": "dotnet format --include"` is WRONG
> Use: `"*.cs": "dotnet format whitespace --include"` or run dotnet format separately

### Python (pre-commit hooks)

Configuration in `.pre-commit-config.yaml`:

```yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.8.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format
```

---

## Phase 4: Configure Commit Message Validation

### Node.js (commitlint)

```bash
npm install -D @commitlint/cli @commitlint/config-conventional
```

Create `commitlint.config.mjs` with:
- Conventional Commits format
- Allowed types: feat, fix, docs, style, refactor, test, chore, ci
- Max header length: 100 characters

### Update Husky hook

Add commit-msg hook:
```bash
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
```

### Python (pre-commit hook for commit message)

Add to `.pre-commit-config.yaml`:
```yaml
  - repo: https://github.com/compilerla/conventional-pre-commit
    rev: v3.4.0
    hooks:
      - id: conventional-pre-commit
        stages: [commit-msg]
```

---

## Phase 5: Test Hooks

Verify hooks work correctly.

**Test 1: Lint-staged triggers**
```bash
# Create a file with lint issues
echo "const x=1" > test-file.ts
git add test-file.ts
git commit -m "test: verify hooks"
# Expected: lint-staged runs, either fixes or blocks
```

**Test 2: Commit message validation**
```bash
git commit --allow-empty -m "bad message"
# Expected: commitlint rejects

git commit --allow-empty -m "test: valid message format"
# Expected: commit succeeds
```

**Cleanup:**
```bash
rm test-file.ts
git reset HEAD~1  # If test commit was made
```

---

## Critical Rules

> **RULE 1:** Husky requires Git repository (`git init` first).

> **RULE 2:** lint-staged MUST have linters configured first (run ln-741 before ln-742).

> **RULE 3:** Document `--no-verify` escape hatch for emergency commits.

> **RULE 4:** pre-commit hooks should auto-fix when possible (`--fix` flag).

---

## Definition of Done

- [ ] Hook manager installed (Husky or pre-commit)
- [ ] Staged linting configured and working
- [ ] Commit message validation configured
- [ ] Test commit triggers hooks correctly
- [ ] User informed of:
  - How hooks work
  - How to skip hooks in emergency (`git commit --no-verify`)
  - Commit message format required

---

## Reference Files

| File | Purpose |
|------|---------|
| [husky_precommit_template.sh](references/husky_precommit_template.sh) | Husky pre-commit hook |
| [husky_commitmsg_template.sh](references/husky_commitmsg_template.sh) | Husky commit-msg hook |
| [lintstaged_template.mjs](references/lintstaged_template.mjs) | lint-staged configuration |
| [commitlint_template.mjs](references/commitlint_template.mjs) | commitlint configuration |
| [precommit_config_template.yaml](references/precommit_config_template.yaml) | Python pre-commit config |
| [hooks_guide.md](references/hooks_guide.md) | Detailed hooks guide |

---

## Error Handling

| Error | Cause | Resolution |
|-------|-------|------------|
| Husky not running | Missing prepare script | Run `npx husky init` again |
| lint-staged fails | Missing linter | Run ln-741 first |
| pre-commit not found | Not in PATH | `pip install pre-commit` |
| Hooks not triggering | Git hooks disabled | Check `.git/hooks/` permissions |
| Windows path issues | Shell script format | Use cross-platform syntax |

---

## Emergency Bypass

Document for users:

```bash
# Skip all hooks (use sparingly!)
git commit --no-verify -m "emergency: bypass hooks"

# Skip only pre-commit (keeps commit-msg)
HUSKY=0 git commit -m "fix: urgent hotfix"
```

---

**Version:** 2.0.0
**Last Updated:** 2026-01-10

Overview

This skill configures Git pre-commit and commit-msg hooks to enforce code quality before commits. It installs and wires Husky, lint-staged, commitlint for Node.js projects and pre-commit for Python, ensuring staged files are linted and commit messages follow Conventional Commits. The setup verifies hooks trigger and provides a safe bypass for emergencies.

How this skill works

The skill first scans the repository for existing hook configurations and decides whether to skip, augment, or replace them. For Node.js it installs Husky and lint-staged, adds a prepare script, and creates .husky hooks. For Python it installs pre-commit and writes a .pre-commit-config.yaml with auto-fix hooks. Commit message validation is added via commitlint (Node) or a commit-msg pre-commit hook (Python). Finally, the skill runs test commits to confirm hooks execute correctly.

When to use it

  • Bootstrapping a new repository to enforce consistent pre-commit checks
  • Adding automated staged-file linting to an existing Node.js or Python project
  • Enforcing Conventional Commit messages across a team
  • Onboarding CI/quality gates that rely on local pre-commit checks
  • When you need a documented, testable hook setup with an emergency bypass

Best practices

  • Check for existing .husky/, .pre-commit-config.yaml, and package.json entries before installing
  • Run project lint configuration task (ln-741) before enabling lint-staged
  • Prefer auto-fixable hooks (e.g., ruff --fix, prettier) so commits succeed after fixes
  • Document the emergency bypass (git commit --no-verify) and when to use it
  • Ensure repository is initialized with Git (git init) before installing Husky

Example use cases

  • Node.js app: add Husky + lint-staged to run ESLint and Prettier on staged TS/JS files and enforce commitlint
  • Python service: install pre-commit with ruff and format hooks, plus a commit-msg hook for Conventional Commits
  • Mixed mono-repo: enable both Husky and pre-commit where each stack runs its native hooks
  • QA checklist: run a test commit to validate that linting blocks or fixes issues as expected

FAQ

What if hooks already exist?

The skill detects existing hook configs and offers to skip, complete, or replace them; it will not blindly overwrite without confirmation.

How can I bypass hooks for an emergency commit?

Use git commit --no-verify to skip all hooks, or HUSKY=0 git commit to disable Husky while keeping other hooks.