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>
38 lines
2.3 KiB
Markdown
38 lines
2.3 KiB
Markdown
# claude-playground
|
|
|
|
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, and after changing .githooks/: installs the git hooks
|
|
npm test
|
|
npm start -- add "try Claude Code"
|
|
npm start -- done 1
|
|
npm start -- ls
|
|
```
|
|
|
|
## What's set up
|
|
|
|
| File | Claude Code feature |
|
|
| --- | --- |
|
|
| `CLAUDE.md` | Project memory, loaded into every session |
|
|
| `.claude/settings.json` | Shared permissions + a hook that syntax-checks `.js` files after every edit |
|
|
| `.claude/skills/changelog/` | A custom skill — run `/changelog` |
|
|
| `.claude/agents/test-writer.md` | A custom subagent — "use the test-writer agent to…" |
|
|
|
|
### 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** 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."*
|
|
- *"Use the test-writer agent to cover `src/todo.js`."*
|
|
- *"Add a `--json` flag to `ls`."* then `/code-review`
|
|
- `/changelog` after a few commits
|
|
- Press `shift+tab` to cycle permission modes (e.g. plan mode before a bigger change)
|
|
- `/memory` to edit CLAUDE.md, `/agents` and `/hooks` to inspect the setup
|