3.5 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-innode:test, no install needed)npm start -- add "something"/npm start -- ls— run the CLI (data intodos.json, override withTODO_FILE)
Conventions
- ES modules, Node >= 20, no third-party dependencies.
src/todo.jsholds pure functions; keep I/O inload/saveandsrc/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.
These rules are instructions, not a lock. Gitea branch protection on main is the real guard; the git push … main deny rules in .claude/settings.json only catch the obvious spellings.
- Start every change from a fresh
main. Rungit fetch originas its own command, thengit switch --no-track -c <type>/<short-name> origin/main(e.g.fix/duplicate-ids,docs/readme).--no-trackkeeps the branch from trackingmain. - Commit on that branch; run
npm testbefore every push. - Push with
git push -u origin HEAD, then open a PR againstmain(see "Gitea API" below). - Review it with
/code-review <branch>. Always name the branch, so the review diffs it againstmainwhatever its upstream is. - Post the result as a PR comment. The first line is the verdict: Needs fixes if there is any correctness finding, otherwise Approved (cleanup-only findings are listed but don't block). The second line is
_Automated self-review by Claude; not an independent review._, followed by the findings. - If it needs fixes, fix the correctness findings on the same branch and repeat steps 2–5. At most 2 fix rounds: after that, post what's left and hand off to the human.
- Stop there. Do not merge the PR, 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 after adding them the session must be restarted (claude --continue). If the token is unset, stop and ask the human; don't work around it.
Shell state doesn't persist between commands, so set every variable in the same command as the call. Write comment bodies to $TMPDIR, never into the repo. -fsS makes HTTP errors fail loudly; check that the PR response has a .number.
API=https://code.westerkam.org/api/v1/repos/christian/claude-playground
# Open a PR
BRANCH=fix/x TITLE="Fix x" BODY="…"
jq -n --arg head "$BRANCH" --arg title "$TITLE" --arg body "$BODY" '{head:$head, base:"main", title:$title, body:$body}' \
| curl -fsS -X POST -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" -d @- "$API/pulls" | jq -e .number
# Comment on PR number $N
N=1
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/$N/comments" | jq -r .html_url
Run git fetch, git commit and git push as standalone commands (no cd … && prefix, nothing chained after them): only then do they run outside the sandbox, which reaching the remote and commit signing need.
Remote
Gitea at code.westerkam.org — origin = git@code.westerkam.org:christian/claude-playground.git.