Skip to content

Pre-Commit Hooks

Run CodeCharter locally before committing.

We recommend CodeCharter in CI as the enforcing gate, with the pre-commit hook as a fast local pre-check. Running the hook locally is optional — but it saves iteration time because you don't have to wait for the CI build to find out whether a convention was violated.

Prerequisites: the codecharter CLI must be installed and on your PATH, and a valid license must be available — without one, every CLI command exits with code 6, so the hook would block every commit. See Installation for download and setup instructions.

Using Git hooks directly

.git/hooks/pre-commit:

#!/bin/sh

# Analyze the staged changes; only errors block the commit.
# --diff - scopes both the findings and the --fail-on gate to changed lines.
git diff --cached --unified=0 | codecharter analyze MySolution.sln --diff - --fail-on error || {
    echo ""
    echo "❌ CodeCharter found blocking issues."
    echo "Run 'codecharter analyze MySolution.sln' for details, or commit with --no-verify if you really want."
    exit 1
}

The report still lists findings of every severity in the changed lines; --fail-on error only decides which of them block the commit. Note that without --fail-on, analyze exits 1 on any finding, including info — so always set --fail-on explicitly in hooks that rely on the exit code.

On an existing codebase, record the current findings once with codecharter analyze MySolution.sln --write-baseline codecharter.baseline.json and add --baseline codecharter.baseline.json to the hook — then only new findings block commits.

chmod +x .git/hooks/pre-commit.

Windows note: chmod is a no-op on NTFS. The hook file is created but may not be marked executable in the Git index. For a hook that is tracked in the repository (e.g. in a hooks/ directory committed to the repo), run git update-index --chmod=+x hooks/pre-commit to set the executable bit in Git's object store. For an untracked .git/hooks/pre-commit, Git for Windows (Git Bash) will usually execute it regardless of the NTFS permission.

Using pre-commit (the Python tool)

If you already use pre-commit, add this to .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: codecharter-analyze
        name: CodeCharter analyze
        entry: codecharter analyze MySolution.sln --fail-on error
        language: system
        pass_filenames: false
        types: ['c#']

Note on types: ['c#']: the type tag for C# files is c# (it comes from the identify library that pre-commit uses), and it needs quotes because of the #. If you prefer not to depend on type tags, use files: '\.cs$' instead.

Using Husky (Node.js)

For JS/TS repos that also happen to have C#, or mixed teams:

.husky/pre-commit:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

codecharter analyze MySolution.sln --fail-on error

Run the hook only on C# changes

A full analysis before every commit can take longer on large solutions. Skip the run if the commit doesn't touch any .cs files:

#!/bin/sh
CHANGED=$(git diff --cached --name-only --diff-filter=ACMR -- '*.cs')
if [ -z "$CHANGED" ]; then
    exit 0
fi
codecharter analyze MySolution.sln --fail-on error
Step Hook
pre-commit diff-scoped: git diff --cached --unified=0 \| codecharter analyze MySolution.sln --diff - --fail-on error
pre-push codecharter analyze MySolution.sln --fail-on error (duration depends on solution size)
CI codecharter analyze MySolution.sln --fail-on error (always)

This keeps the hook in the hot path scoped to what the commit actually changes and catches obvious mistakes without making every commit wait for a full analysis.