Install hooks by copying into .git/hooks instead of core.hooksPath
Linking core.hooksPath to the tracked, sandbox-writable .githooks/ let a sandboxed command rewrite a hook that git commit/push then run unsandboxed. Copies in .git/hooks can't be changed from the sandbox. This also keeps existing .git/hooks scripts working and lets npm install succeed outside a git checkout. pre-merge-commit now names itself in errors; hook tests clean up, ignore GIT_* env and cover the installer; docs state what each layer does and doesn't stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8b08c7b27a
commit
24541f0602
7 files changed
+72
-20
No files matched your search
@@ -3,7 +3,7 @@
|
||||
A tiny todo CLI that exists to try out [Claude Code](https://docs.claude.com/en/docs/claude-code) features.
|
||||
|
||||
```sh
|
||||
npm install # once per clone: turns on the git hooks in .githooks/
|
||||
npm install # once per clone, and after changing .githooks/: installs the git hooks
|
||||
npm test
|
||||
npm start -- add "try Claude Code"
|
||||
npm start -- done 1
|
||||
@@ -22,9 +22,11 @@ npm start -- ls
|
||||
### Protecting `main`
|
||||
Changes reach `main` only through a PR that a human merges. Three layers, strongest first:
|
||||
1. **Gitea branch protection** on `main` (set in the repo settings on code.westerkam.org): the only layer that can't be bypassed from a clone.
|
||||
2. **Git hooks** in `.githooks/` (enabled by `npm install`): `pre-push` rejects any push that would update `main`, however it's spelled; `pre-commit` / `pre-merge-commit` refuse commits while `main` is checked out. `--no-verify` skips them.
|
||||
2. **Git hooks** from `.githooks/`, copied into `.git/hooks` by `npm install` (`scripts/install-hooks.sh`). `pre-push` rejects any push that would update `main`, however it's spelled. `pre-commit` / `pre-merge-commit` refuse ordinary and merge commits while `main` is checked out; cherry-pick, revert and fast-forwards skip them, but pre-push still stops the result leaving the machine. The hooks are copied, not linked with `core.hooksPath`, because Claude Code's sandbox can't write inside `.git/`: a sandboxed command can't rewrite the installed hooks, which matters because `git commit` / `git push` run outside the sandbox. Anyone can still skip them with `--no-verify`.
|
||||
3. **Claude Code deny rules** in `.claude/settings.json` for `git push … main`: a quick early stop, but they match command text, so they're easy to get around.
|
||||
|
||||
Layers 2 and 3 live on your machine and can be bypassed by whoever runs the commands; only layer 1 can't.
|
||||
|
||||
## Things to try
|
||||
|
||||
- *"There's a bug in how ids are assigned after removing a todo — find it and fix it with a test."*
|
||||
|
||||
Reference in new issue
Block a user