pi-edit-hooks

Code quality hooks for the pi coding agent — runs syntax checks on edit and format/lint/typecheck at turn end

Package details

extension

Install pi-edit-hooks from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-edit-hooks
Package
pi-edit-hooks
Version
0.2.0
Published
Apr 30, 2026
Downloads
142/mo · 15/wk
Author
mackenney
License
MIT
Types
extension
Size
59.7 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-edit-hooks

Code quality hooks for the pi coding agent.

Runs syntax checks inline as the agent edits files (onEdit) and runs format/lint/typecheck at the end of each turn (onStop).

Install

pi install npm:pi-edit-hooks

Configuration

Create .pi/edit-hooks.json in your project, or globally at ~/.pi/agent/edit-hooks.json.

Hooks

Hook Trigger Behavior Variables
onEdit After each write/edit tool call Appends output to tool result (informational, never blocks). Shows resolved config file and command executed. {file}
onStop After agent turn ends Sends a follow-up message with each command and its output. Errors trigger a new agent turn; clean output is informational only. {files}, {file}

Variables

  • {file} — absolute path of the edited file
  • {files} — space-separated absolute paths of all files edited in the current turn, grouped by project (see below)
  • {projectRoot} — directory containing the .pi/ folder

Commands without a placeholder run as-is (useful for project-wide tools like npx tsc --noEmit).

Monorepo File Grouping

In monorepos, {files} is not a flat list of every edited file. Instead, pi-edit-hooks groups files by their nearest workspace manifest (pyproject.toml, package.json, go.mod, etc.) and runs the onStop command once per group, with {files} containing only the files that belong to that manifest's project and {projectRoot} pointing to its directory.

This means tools like ruff, tsc, and go vet are always invoked from the correct project root with the correct subset of files — no cross-project contamination and no need to wrangle paths manually.

Array Commands

A command value can be a string or an array of strings. When an array is given, each command runs in sequence — all steps always run regardless of exit codes:

"*.py": [
  "uv run ruff format {files}",
  "uv run ruff check --fix {files}",
  "uv run ty check {files}"
]

Path-Keyed Config

Apply different settings per subdirectory:

{
  ".": {
    "onEdit": { "*.py": "python3 -m ast {file}" },
    "onStop": { "*.py": "uv run ruff check {files}" }
  },
  "legacy/": false,
  "packages/frontend/": {
    "onStop": { "*.{ts,tsx}": "npx biome check {files}" }
  }
}

false disables all hooks for that subtree.

Claude Code CLI

The package also ships a pi-edit-hooks binary compatible with Claude Code's stop-hook protocol:

{
  "hooks": {
    "Stop": [{ "hooks": [{ "type": "command", "command": "pi-edit-hooks check" }] }],
    "PostToolUse": [{ "hooks": [{ "type": "command", "command": "pi-edit-hooks accumulate" }] }]
  }
}

Example Configurations

Minimal project setup:

{
  "onEdit": {
    "*.py": "python3 -c 'import ast,sys;ast.parse(open(sys.argv[1]).read())' {file}",
    "*.{js,mjs,cjs}": "node --check {file}",
    "*.{ts,tsx}": "esbuild {file} > /dev/null"
  },
  "onStop": {
    "*.py": [
      "uv run ruff format {files}",
      "uv run ruff check --fix {files}",
      "uv run ty check {files}"
    ],
    "*.{ts,tsx}": "npx tsc --noEmit"
  }
}

Monorepo with per-subtree overrides:

{
  ".": {
    "onEdit": { "*.py": "python3 -c 'import ast,sys;ast.parse(open(sys.argv[1]).read())' {file}" },
    "onStop": {
      "*.py": [
        "uv run ruff format {files}",
        "uv run ruff check --fix {files}",
        "uv run basedpyright {files}"
      ]
    }
  },
  "legacy/": false,
  "packages/frontend/": {
    "onStop": { "*.{ts,tsx}": "npx biome check {files}" }
  }
}