chore: add prettier auto-format hook for Claude Code#1037
chore: add prettier auto-format hook for Claude Code#1037dqnykamp wants to merge 1 commit intoDoenet:mainfrom
Conversation
Adds .claude/settings.json with a PostToolUse hook that runs prettier on files after Write/Edit/MultiEdit/NotebookEdit operations. Ensures code is formatted automatically rather than relying on the agent to follow the "format with prettier before committing" instruction in CLAUDE.md (which was missed in PR Doenet#1036). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
There was a problem hiding this comment.
Pull request overview
Adds a Claude Code hook configuration to automatically run Prettier after file write/edit operations, aiming to keep agent-driven edits consistently formatted in this repo.
Changes:
- Add
.claude/settings.jsondefining aPostToolUsehook forWrite|Edit|MultiEdit|NotebookEdit. - Hook runs
npx --no-install prettier --write --ignore-unknownon the edited file path (when it appears to be under$PWD).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| "hooks": { | ||
| "PostToolUse": [ |
There was a problem hiding this comment.
The PR description mentions relying on an instruction in CLAUDE.md, but there is no CLAUDE.md in this repository (the existing guidance appears to be in AGENTS.md). Please update the description to reference the correct file so future contributors can find the formatting requirement.
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; case \"$f\" in \"$PWD\"/*) npx --no-install prettier --write --ignore-unknown \"$f\" ;; esac; } 2>/dev/null || true", |
There was a problem hiding this comment.
The stderr redirection (2>/dev/null) is applied to the { ... } block but not to the jq command. If jq is missing or errors, it can still print noise to stderr even though the hook ultimately succeeds due to || true. Consider redirecting jq stderr as well (or checking for jq before running) so hook output stays clean.
| "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; case \"$f\" in \"$PWD\"/*) npx --no-install prettier --write --ignore-unknown \"$f\" ;; esac; } 2>/dev/null || true", | |
| "command": "jq -r '.tool_response.filePath // .tool_input.file_path' 2>/dev/null | { read -r f; case \"$f\" in \"$PWD\"/*) npx --no-install prettier --write --ignore-unknown \"$f\" ;; esac; } 2>/dev/null || true", |
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; case \"$f\" in \"$PWD\"/*) npx --no-install prettier --write --ignore-unknown \"$f\" ;; esac; } 2>/dev/null || true", |
There was a problem hiding this comment.
The "$PWD" prefix check can be bypassed by paths containing .. segments (e.g., "$PWD/../outside") which still match the case pattern but resolve outside the repo. To enforce “only format files inside the project directory”, normalize with realpath (or an equivalent) before comparing, and only run Prettier when the normalized path is within the normalized repo root.
| "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; case \"$f\" in \"$PWD\"/*) npx --no-install prettier --write --ignore-unknown \"$f\" ;; esac; } 2>/dev/null || true", | |
| "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; repo_root=$(realpath \"$PWD\") && target=$(realpath \"$f\") && case \"$target\" in \"$repo_root\"|\"$repo_root\"/*) npx --no-install prettier --write --ignore-unknown \"$target\" ;; esac; } 2>/dev/null || true", |
Summary
.claude/settings.jsonwith aPostToolUsehook that runsprettier --write --ignore-unknownon files afterWrite/Edit/MultiEdit/NotebookEditoperations..prettierignore(auto-discovered by prettier) and only formats files inside the project directory.Test plan
/hooksonce (or restart Claude Code) so the new settings take effect..ts/.jsfile with formatting violations and confirming it gets auto-formatted on save..mdand other ignored paths are skipped (already covered by.prettierignore).🤖 Generated with Claude Code