A Claude Code PostToolUse hook that automatically runs PHPCS after Claude edits
a PHP/Drupal file inside a DDEV project — feeding violations back to Claude so it
can self-correct without any human intervention.
- Fires after every
EditorWritetool use - Checks only PHP-family files:
.php,.module,.install,.inc,.theme - Scopes to your custom code only (configurable via the path regex in the script)
- Runs
ddev phpcs <file>with a relative path (required — DDEV maps the project root to/var/www/html, so absolute host paths don't exist in the container) - Exit
0→ silent (file is clean or out of scope) - Exit
1→ Claude Code feeds the PHPCS output back to Claude, which reports and fixes the violations automatically
| Problem | Cause | Fix |
|---|---|---|
Hook not matching .module files |
Script only checked *.php |
Added all Drupal PHP extensions to the case statement |
"file does not exist" inside DDEV |
Passed absolute host path to ddev phpcs |
Derive relative path using git rev-parse --show-toplevel |
| Script not found | Used relative path in settings.json command |
Read stdin into $input, extract file path, derive root, call script via $root/.claude/scripts/... |
| Hook output not reaching Claude | Used ` | tee` (exit code became 0) |
| Output flashing then disappearing | Wrote to /dev/tty, but Claude Code TUI redraws screen |
Let stdout flow naturally so Claude Code captures it |
When the hook exits non-zero (PHPCS found violations):
- Claude Code shows
PostToolUse:Edit hook errorin the UI - The PHPCS output is fed to Claude as context
- Claude reports the violations and can fix them in the next step
When the hook exits zero (file is clean):
- Completely silent — no banner, no noise
This hook is a convenience safety net, not a replacement for CI.
Costs:
- ~1-2s DDEV overhead on every file edit
- Extra tokens when violations are found (PHPCS output added to context)
If you have CI enforcing PHPCS (e.g. GitHub Actions), this hook is redundant but adds instant feedback during development. Whether it's worth the overhead depends on your workflow.
- Copy
post-edit-phpcs.shto.claude/scripts/post-edit-phpcs.shin your project - Make it executable:
chmod +x .claude/scripts/post-edit-phpcs.sh - Add the hook snippet from
settings.jsonto your.claude/settings.json - Adjust the path regex in step 4 of the script to match your project structure
- Claude Code
- DDEV with
ddev phpcsconfigured jqinstalled on the host