> ## Documentation Index
> Fetch the complete documentation index at: https://tashfiq.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Charter in a Pre-Commit Hook

> Run charter doctor automatically before every commit to catch issues before they reach CI.

Running Charter in a pre-commit hook catches score regressions before they reach CI and before other team members have to deal with them. With `--quiet`, the hook is completely silent on a passing commit and only interrupts when there's something to fix.

## Exit code behavior

| Exit code | Meaning                          | Hook result                     |
| --------- | -------------------------------- | ------------------------------- |
| `0`       | Score meets or exceeds threshold | Commit proceeds silently        |
| `1`       | Score below threshold            | Commit blocked, summary printed |

All hook runners respect non-zero exit codes to block commits. No additional configuration is needed.

<Note>
  `--quiet` mode is essential for hooks. On pass: completely silent. On fail: one summary line with the failing findings. Without `--quiet`, every commit prints the full scan output — which gets noisy fast.
</Note>

## Setup

<Tabs>
  <Tab title="hk (recommended)">
    [hk](https://github.com/jdx/hk) is a Git hook manager configured in `hk.pkl` and committed to the repo, so every contributor gets the same hooks automatically.

    Add a Charter hook to `hk.pkl`:

    ```pkl theme={null}
    hooks {
      new Hook {
        name = "charter"
        run = "charter doctor --quiet --threshold 80"
      }
    }
    ```

    Then install:

    ```bash theme={null}
    hk install
    ```

    Run `hk install` again after any changes to `hk.pkl` to update the installed hooks.
  </Tab>

  <Tab title="husky">
    If your repo uses [husky](https://typicode.github.io/husky/), create or edit `.husky/pre-commit`:

    ```bash theme={null}
    #!/bin/sh
    charter doctor --quiet --threshold 80
    ```

    Make it executable:

    ```bash theme={null}
    chmod +x .husky/pre-commit
    ```

    Commit `.husky/pre-commit` to version control so all contributors share the same hook.
  </Tab>

  <Tab title="Plain shell">
    No hook manager required. Create `.git/hooks/pre-commit` directly:

    ```bash theme={null}
    #!/bin/sh
    charter doctor --quiet --threshold 80
    ```

    Make it executable:

    ```bash theme={null}
    chmod +x .git/hooks/pre-commit
    ```

    <Warning>
      `.git/hooks/` is not committed to version control. Plain shell hooks are local to your machine only. For team-wide enforcement, use hk or husky — both commit their configuration files to the repo.
    </Warning>
  </Tab>
</Tabs>

## Threshold guidance

<Tip>
  Use the same threshold in your pre-commit hook as in CI. If they diverge, local commits can succeed but CI will fail — which creates friction and erodes trust in the hook.
</Tip>

Set an explicit threshold to match your CI gate:

```bash theme={null}
# Matches a charter.yaml policy.threshold: 85
charter doctor --quiet --threshold 85
```

Or defer to whatever `charter.yaml` says, so hook and CI always agree automatically:

```bash theme={null}
# Defers to policy.threshold or policy.profile in charter.yaml
charter doctor --quiet
```

If `charter.yaml` has no policy section, Charter uses the built-in default of 80.

## Next steps

<CardGroup cols={2}>
  <Card title="Run Charter in GitHub Actions" icon="git-branch" href="/docs/how-to/run-in-github-actions">
    Enforce the same gate on every pull request.
  </Card>

  <Card title="Policy Profiles" icon="adjustments-horizontal" href="/docs/config/policy-profiles">
    Set one threshold for hook and CI so they always agree.
  </Card>

  <Card title="charter.yaml Reference" icon="settings" href="/docs/config/charter-yaml">
    Configure policy at the repo root.
  </Card>

  <Card title="charter doctor" icon="stethoscope" href="/cli/doctor">
    The scan command the hook runs.
  </Card>
</CardGroup>
