docs: hooks-guide auto-format example breaks on paths with spaces and exits 2 on unsupported files — contradicts the bundled update-config skill
Summary
The "Auto-format code after edits" example in hooks-guide has two defects. It appears twice on the page and is the first hook pattern most people copy.
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
Both failures are silent or noisy in ways that surface long after the user has stopped watching the hook.
Defect 1 — xargs word-splits paths containing spaces
xargs splits on whitespace, so one file becomes several nonexistent paths.
$ echo '{"tool_input":{"file_path":"/tmp/carpeta con espacios/a.ts"}}' \
| jq -r '.tool_input.file_path' | xargs printf '[%s]\n'
[/tmp/carpeta]
[con]
[espacios/a.ts]
$ echo '{"tool_input":{"file_path":"/tmp/carpeta con espacios/a.ts"}}' \
| jq -r '.tool_input.file_path' | xargs ls
ls: /tmp/carpeta: No such file or directory
ls: con: No such file or directory
ls: espacios/a.ts: No such file or directory
Control: with a path that has no spaces, xargs works correctly. The bug is therefore intermittent by nature — the hook appears to work for months until someone edits a file under My Project/.
The page contains no warning about spaces or word-splitting. Searched the full 71 KB of the rendered page: zero occurrences of read -r, and nothing about quoting near the example. The only related note is 900 lines away under troubleshooting ("command not found"), suggesting "args": [] for exec form.
Defect 2 — no --ignore-unknown, so unsupported files exit 2
exit 2 is the _blocking error_ code for hooks: stderr is fed back to Claude.
$ prettier --write s.py ; echo "exit=$?"
[error] No parser could be inferred for file ".../s.py".
exit=2
$ prettier --write --ignore-unknown s.py ; echo "exit=$?"
exit=0
The documented command has neither --ignore-unknown nor || true. In any polyglot repository, every edit to a .py, .sh, .toml, or any file Prettier has no parser for makes the hook return a blocking error on an operation that succeeded.
Defect 3 (minor) — npx can hit the network
npx prettier with no local copy resolves by downloading from the registry. On a machine whose global Prettier lives inside an nvm release, a Node version bump removes it from PATH and this hook silently starts fetching Prettier on every edit.
This contradicts a bundled first-party source
The update-config skill that ships with Claude Code prescribes the opposite, explicitly:
usejq -rinto a quoted variable or{ read -r f; ... "$f"; }, NOT unquoted| xargs(splits on spaces)
Two official sources of the same product disagree, and the more visible one is the incorrect one.
Suggested fix
"command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; npx prettier --write --ignore-unknown \"$f\"; } || true"
read -rinto a quoted variable — no word-splitting--ignore-unknown— unsupported files are skipped silently instead of exiting 2 (also honours.prettierignore)|| true— a formatter should not turn a successful edit into a hook error.tool_response.filePathfirst, matching the fallback theupdate-configskill uses
A one-line note that paths may contain spaces would also help readers who adapt the pattern to other formatters.
Environment
- Claude Code 2.1.237
- macOS (arm64), APFS
- Prettier 3.9.6
jqvia Homebrew
Also worth checking
The page states "When the hook succeeds, Claude Code shows nothing in the conversation." In practice a PostToolUse hook that rewrites the edited file surfaces a PostToolUse hook modified <file> after your edit (likely a formatter) notice. I have not isolated the exact conditions, so this is an observation rather than a confirmed claim — but the sentence may be worth revisiting, since that notice is genuinely useful and users are being told it does not exist.