Gotchas around hooks
You may have noticed there are two settings files in .claude after you run npm run setup: settings.example.json and settings.local.json. That is not a mistake — it is a deliberate pattern that solves a real team-workflow problem with hooks, and you will want to copy it in your own projects.
The security recommendation
The Claude Code documentation recommends using absolute paths for hook script commands rather than relative ones. The reason is straightforward: absolute paths help mitigate path interception and binary planting attacks, where an attacker puts a malicious script with the same name earlier in your PATH and your hook ends up running that instead of your real script.
So a safe hook command looks like:
"command": "node /Users/alice/projects/uigen/hooks/read_hook.js"
Not:
"command": "node ./hooks/read_hook.js"
The portability problem
As soon as you try to commit that absolute path to source control, the problem is obvious. Your teammate clones the repo into /home/bob/code/uigen/ and your settings.json points at /Users/alice/... — broken on every machine but yours.
You cannot share absolute paths directly, and you should not downgrade to relative paths for security reasons. That is the gotcha.
The settings.example.json pattern
The project solves this with a two-file setup plus a setup script.
settings.example.json — the committed template. Wherever a hook command needs an absolute path, the file uses a $PWD placeholder instead:
"command": "node $PWD/hooks/read_hook.js"
This file goes in source control. Everyone on the team gets the same template.
init-claude.js — a setup script in the scripts directory that resolves $PWD to the real absolute path on the current machine, writes the result out as settings.local.json, and leaves that copy gitignored.
npm run setup — runs init-claude.js as part of its normal setup flow. First time a teammate clones the project, they run npm run setup and end up with a working settings.local.json pointing at their own machine's paths.
The net effect: you get the security benefit of absolute paths, the portability of relative paths, and a one-command onboarding flow for new teammates. The cost is one small script you write once and forget about.
When to copy the pattern
Any project where hooks are committed to source control should use this pattern. If hooks are purely personal and live in settings.local.json from day one, you can skip it — but as soon as you want the team to share a hook, reach for settings.example.json plus a setup script.
Key Takeaways
- 1Claude Code recommends absolute paths for hook commands to mitigate path interception and binary planting attacks.
- 2Absolute paths are not portable across machines — every teammate's project lives at a different location — so committing them directly breaks the shared settings file.
- 3The fix is a `settings.example.json` template that uses `$PWD` placeholders, plus a setup script (`init-claude.js`) that resolves them into a real `settings.local.json` on the current machine.
- 4Wire the setup script into `npm run setup` so new teammates get a working configuration with one command.