Files
claude-playground/CLAUDE.md
T
christianandClaude Opus 5.5 ed197eeeb1 Address review round 3: safe API snippets, PR opened once, pinned review
- Titles and bodies go through --rawfile files, never inline shell quotes
- pipefail + curl -f + jq -e so a failed call can't look successful
- Fix rounds merge latest main and skip re-opening the PR
- Check the branch isn't main before pushing; never bypass the hooks
- Review at a pinned level; only correctness findings checked against the
  code block approval

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:50:38 +02:00

4.3 KiB

claude-playground

A tiny zero-dependency Node.js todo CLI, used as a sandbox for trying Claude Code features.

Commands

  • npm test — run the test suite (built-in node:test, no install needed)
  • npm start -- add "something" / npm start -- ls — run the CLI (data in todos.json, override with TODO_FILE)

Conventions

  • ES modules, Node >= 20, no third-party dependencies.
  • src/todo.js holds pure functions; keep I/O in load/save and src/cli.js.
  • Every behavior change gets a test in test/.
  • Commit messages: short imperative subject line.

Workflow (required)

Never commit, merge, or push to main. Only a human (Christian) merges into main. This is enforced by the git hooks that npm install installs and by Gitea branch protection (see "Protecting main" in the README). Never get around them: no --no-verify, no changing core.hooksPath, no editing .git/.

  1. Branch. Run git fetch origin on its own, then git switch --no-track -c <type>/<short-name> origin/main (e.g. fix/duplicate-ids, docs/readme). --no-track stops the branch from tracking main.
  2. Commit and test. Commit on the branch; npm test must pass before every push.
  3. Push. Check that git branch --show-current isn't main, then run git push -u origin HEAD.
  4. Open the PR, once per branch (see "Gitea API" below).
  5. Review with /code-review <branch> medium. Name both the branch and the level, so every round diffs against main at the same depth.
  6. Comment on the PR with the verdict.
    • First line: Needs fixes if any correctness finding still holds after you check it against the code; otherwise Approved. Cleanup and judgement-call findings are listed but don't block.
    • Second line: _Automated self-review by Claude; not an independent review._
    • Then the findings, including any you checked and rejected, and why.
  7. Fix rounds. If it needs fixes, first bring in the latest main: run git fetch origin, then git merge --no-ff --no-commit origin/main, then git commit --no-edit, each as its own command. Don't rebase, because force pushes are denied. Fix the correctness findings, then repeat steps 2, 3, 5 and 6 (not step 4: the PR already exists). Do at most 2 fix rounds, then post what's left and hand off.
  8. Stop. Never merge, even if approved; tell the human it's ready.

Gitea API

No gh/tea: use curl with $GITEA_TOKEN.

One-time human setup in the git-ignored .claude/settings.local.json: set env.GITEA_TOKEN, and add code.westerkam.org to sandbox.network.allowedDomains. Settings load at session start, so restart the session after adding them (claude --continue). If the token is unset, stop and ask the human; don't work around it.

Rules for every API call:

  • Make each call one self-contained command, because shell state doesn't carry over between commands.
  • Write titles and bodies to files in $TMPDIR (never in the repo) and pass them with --rawfile. Never put them inline in double quotes, where backticks and $(…) would run.
  • pipefail, curl -f and jq -e make every failure exit non-zero.
# Open a PR for the current branch (once). Write $TMPDIR/pr-title.txt and $TMPDIR/pr-body.md first.
set -o pipefail; API=https://code.westerkam.org/api/v1/repos/christian/claude-playground
jq -n --arg head "$(git branch --show-current)" --rawfile title "$TMPDIR/pr-title.txt" --rawfile body "$TMPDIR/pr-body.md" \
  '{head:$head, base:"main", title:($title|rtrimstr("\n")), body:$body}' \
  | curl -fsS -X POST -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" -d @- "$API/pulls" \
  | jq -er '"#\(.number) \(.html_url)"'

# Comment on PR <number>. Write $TMPDIR/comment.md first.
set -o pipefail; API=https://code.westerkam.org/api/v1/repos/christian/claude-playground
jq -n --rawfile body "$TMPDIR/comment.md" '{body:$body}' \
  | curl -fsS -X POST -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" -d @- "$API/issues/<number>/comments" \
  | jq -er .html_url

Run git fetch, git commit and git push as standalone commands, with no cd … && before them and nothing chained after. Only then do they run outside the sandbox, which they need to reach the remote and to sign commits.

Remote

Gitea at code.westerkam.org — origin = git@code.westerkam.org:christian/claude-playground.git.