Table of Contents

Set up Post-Edit Lint Hooks

One of the most effective ways to reduce review cycles is to catch linting and type errors at the cheapest point: immediately after the AI agent makes a change.

Spec Kitty provides a universal wrapper command, spec-kitty lint, designed specifically for this purpose. When configured as a "post-edit hook," it feeds violations back to the agent in the same turn, allowing it to self-correct.

1. The Universal Wrapper

The spec-kitty lint <file_path> command:

  • Runs ruff check (linting).
  • Runs mypy --strict (type-checking).
  • Summarizes errors in an agent-friendly format.
  • Exits with 1 if errors are found, triggering the agent's auto-fix logic.

Two invocation forms. When you pass a path explicitly (spec-kitty lint path/to/file.py) it lints that file. When you omit the path (spec-kitty lint --json, the form wired into harness hooks below) it reads the edited file from the harness's JSON payload on stdin — Claude Code delivers tool_input.file_path, Cursor delivers file_path. A hook that fires without a Python file to lint (for example after a non-edit tool call) is a harmless no-op, never an error that blocks the agent.

Rather than hand-editing harness config, let Spec Kitty manage the hooks for the agents in your .kittify/config.yaml:

spec-kitty agent config set lint_on_edit true
spec-kitty agent config sync --sync-hooks

This writes the Claude Code (PostToolUse) and Cursor (afterFileEdit) hook entries below for every configured agent, idempotently and without disturbing your other hooks/settings. Set lint_on_edit false and re-sync to remove them. Only agents listed in config.yaml are touched.

3. Configuration by Harness (manual)

Claude Code

Claude Code supports PostToolUse hooks in .claude/settings.json.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "spec-kitty lint --json"
          }
        ]
      }
    ]
  }
}

Aider

Aider supports the --lint-cmd flag. You can set this in your .aider.conf.yml or pass it at startup.

aider --lint-cmd "spec-kitty lint"

Cursor

Cursor (v1.7+) supports hooks in .cursor/hooks.json.

{
  "version": 1,
  "hooks": {
    "afterFileEdit": [
      {
        "command": "spec-kitty lint --json"
      }
    ]
  }
}

Windsurf

Windsurf has no programmatic post-edit hook, so --sync-hooks does not manage it. Configure it manually by adding a natural-language rule to your .windsurfrules file:

# Linting Guardrail
After every file edit, you MUST run `spec-kitty lint <file_path>` and fix any reported errors immediately.

4. Advanced Usage

Auto-Fixing

You can instruct spec-kitty lint to attempt to fix errors automatically (via ruff --fix) by adding the --fix flag:

spec-kitty lint <file_path> --fix

JSON Output

For tools that can parse structured feedback, use the --json flag to get a machine-readable error report:

spec-kitty lint <file_path> --json

Why use hooks?

  1. Faster Merges: Code arrives at the review gate already clean and type-safe.
  2. Lower Costs: Fewer turns spent on trivial "unused import" or "missing type hint" fixes.
  3. Better Quality: Enforces project standards (like mypy --strict) automatically.