ai 🧪 (beta)

This is a beta feature and still in development.

Declare LLM agent hooks directly in lefthook.yml. During lefthook install, lefthook generates the provider-specific settings file so that the agent calls lefthook run <hook> when the event fires.

Each sub-key is a provider name. Its value is a map from the provider’s event name to a lefthook hook name defined elsewhere in the same config.

Supported providers

Provider Generated file Docs
claude .claude/settings.json Claude Code hooks
codex .codex/hooks.json Codex CLI hooks
cursor .cursor/hooks.json Cursor hooks
copilot .github/hooks/lefthook.json GitHub Copilot hooks

Keys under each provider must be that provider’s hook event names. See the provider’s hooks documentation for the supported events and their behaviour.

Install and uninstall behaviour

Claude, Codex, and Cursor preserve user-authored entries in their settings files. On lefthook install, old lefthook-managed entries are replaced with fresh ones derived from the current config. On lefthook uninstall, lefthook-managed entries are stripped while user-authored entries stay intact.

Copilot is handled differently: lefthook install rewrites .github/hooks/lefthook.json from scratch, and lefthook uninstall removes that file entirely.

Generated hook commands use the lefthook config value when set, otherwise the absolute path of the lefthook binary that ran install (via os.Executable()), so AI tools do not depend on lefthook being on PATH.

Example

# lefthook.yml

ai:
  claude:
    Stop: validate
    PreToolUse: security-check
  codex:
    Stop: validate
  cursor:
    stop: validate
    preToolUse: security-check
  copilot:
    postToolUse: validate

validate:
  jobs:
    - run: go test ./...

security-check:
  jobs:
    - run: ./scripts/security.sh

Running lefthook install creates (or updates) .claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "lefthook run validate" }
        ]
      }
    ],
    "PreToolUse": [
      {
        "hooks": [
          { "type": "command", "command": "lefthook run security-check" }
        ]
      }
    ]
  }
}

And .codex/hooks.json:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "lefthook run validate" }
        ]
      }
    ]
  }
}

And .cursor/hooks.json:

{
  "version": 1,
  "hooks": {
    "stop": [
      { "command": "lefthook run validate" }
    ],
    "preToolUse": [
      { "command": "lefthook run security-check" }
    ]
  }
}

And .github/hooks/lefthook.json:

{
  "version": 1,
  "hooks": {
    "postToolUse": [
      { "command": "lefthook run validate" }
    ]
  }
}