TypeDialog/docs/pre-commit-setup.md
2025-12-24 03:11:32 +00:00

6.1 KiB

Pre-commit Hook Setup

Automated linting and validation before every commit.

Installation

1. Install pre-commit

macOS/Linux (via pip):

pip install pre-commit
# Or with pipx (recommended)
pipx install pre-commit

macOS (via Homebrew):

brew install pre-commit

Verify installation:

pre-commit --version

2. Install the hooks

From the project root:

pre-commit install

This creates .git/hooks/pre-commit that runs automatically on git commit.

What Gets Checked

The pre-commit hook runs these checks automatically before every commit:

General Checks

  • Trailing whitespace - Removes trailing spaces (except in .md files)
  • End-of-file fixer - Ensures files end with newline
  • YAML/TOML/JSON validation - Syntax checking
  • Large files - Prevents files >1MB
  • Merge conflicts - Detects conflict markers
  • Line endings - Normalizes to LF

Language-Specific Linting

Rust

  • cargo fmt - Code formatting check
  • cargo clippy - Linting with warnings as errors

Shell Scripts

  • shellcheck - Bash/shell script analysis

Markdown (docs/ only)

  • markdownlint-cli2 - Syntax validation (MD rules)
  • vale - Prose quality (weasel words, etc.)

Nickel

  • nickel typecheck - Type checking for .ncl files

Nushell

  • nu --check - Script validation for .nu files

Security

  • cargo audit - Dependency vulnerability scan (manual stage only)

Usage

Pre-commit runs automatically on git commit:

git add docs/README.md
git commit -m "Update README"
# Pre-commit hooks run automatically

Manual Run

Run all hooks on all files:

pre-commit run --all-files

Run specific hook:

pre-commit run cargo-fmt --all-files
pre-commit run markdownlint-cli2 --all-files
pre-commit run vale --all-files

Run hooks on staged files only:

pre-commit run

Skip Hooks (Emergency Only)

To bypass hooks (use sparingly):

git commit --no-verify -m "Emergency fix"

Note: CI will still run all checks, so bypassing locally doesn't skip validation.

Hook Behavior

Blocking vs Non-Blocking

Blocking (commit fails if check fails):

  • cargo fmt
  • cargo clippy
  • markdownlint-cli2
  • shellcheck
  • nickel typecheck
  • nushell check

Non-Blocking (warnings logged, commit succeeds):

  • vale (prose quality warnings don't block commits)

Vale Configuration

Vale is configured to be informative but not blocking:

  • 0 errors → Commit succeeds
  • Warnings → Logged but commit proceeds
  • Encourages better prose without being disruptive

To make Vale blocking, edit .pre-commit-config.yaml:

# Change this:
entry: bash -c 'vale docs/ || exit 0'
# To this:
entry: bash -c 'vale docs/'

Updating Hooks

Update to latest hook versions:

pre-commit autoupdate

This updates the rev: fields in .pre-commit-config.yaml.

Troubleshooting

Hook fails: "command not found"

Problem: Tool not installed (e.g., cargo, vale, nickel, nu)

Solution: Install the missing tool:

# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Vale
brew install vale  # macOS
# See https://vale.sh for other platforms

# Nickel
cargo install nickel-lang-cli

# Nushell
cargo install nu

Hooks are slow

Problem: cargo clippy takes 30+ seconds

Solution: Use --no-verify for quick commits, let CI handle full validation:

git commit --no-verify -m "WIP: quick fix"
# Later, when ready:
pre-commit run --all-files

Markdownlint fails on valid Markdown

Problem: False positive from markdownlint

Solution: Update .markdownlint-cli2.jsonc to disable the rule:

{
  "config": {
    "default": true,
    "MD013": false,  // Example: disable line length
    "MD033": false   // Example: allow HTML
  }
}

Vale warnings are too noisy

Problem: Too many prose quality warnings

Solution: Adjust .vale.ini to disable specific rules:

[*.md]
write-good.Weasel = NO  # Disable weasel word warnings

Or set higher alert level:

MinAlertLevel = error  # Only show errors, not warnings

Best Practices

1. Run Before First Commit

After installing hooks, test them:

pre-commit run --all-files

Fix any issues before committing.

2. Keep Commits Small

Smaller commits = faster hook execution.

3. Stage Incrementally

Stage related changes together:

git add docs/README.md docs/build.md
git commit -m "Update build docs"
# Only checks staged files

4. Use --no-verify Sparingly

Reserve --no-verify for emergencies:

  • Hotfixes
  • Reverts
  • Time-critical patches

CI will catch issues anyway.

5. Update Hooks Regularly

Monthly:

pre-commit autoupdate
pre-commit run --all-files

Integration with CI

Pre-commit hooks mirror CI checks:

Local (pre-commit):

  • Fast feedback before commit
  • Catches obvious issues early
  • Optional (can bypass with --no-verify)

CI (GitHub Actions):

  • Comprehensive validation
  • Required for PRs
  • Cannot be bypassed

Both run the same checks, so passing locally = passing CI.

Disabling Hooks Temporarily

Disable all hooks:

pre-commit uninstall

Re-enable:

pre-commit install

Disable specific hook (edit .pre-commit-config.yaml):

- id: cargo-clippy
  # Add this to disable:
  stages: [manual]

Then run manually with:

pre-commit run cargo-clippy --all-files --hook-stage manual

Summary

Pre-commit hooks provide:

  • Automated quality checks before every commit
  • Fast feedback (catch issues in seconds, not minutes)
  • Consistent standards across all contributors
  • Optional but recommended (can bypass if needed)

Install once, benefit forever:

pip install pre-commit
pre-commit install

See also: