Skip to content

Latest commit

 

History

History
104 lines (66 loc) · 6.49 KB

File metadata and controls

104 lines (66 loc) · 6.49 KB

CLAUDE.md

Guidance for Claude Code when working in this repository.

Evidence-based claims

When asserting something about this codebase, cite the file and line you read it from. If you have not verified something, say so rather than inferring it.

Project layout

  • packages/web/ — React + TypeScript frontend. Conventions in .claude/rules/frontend.md. That rule loads automatically when you read a frontend file; read it explicitly before writing a new component from scratch.
  • service/ — Django REST API + PostgreSQL. Conventions in .claude/rules/backend/ (hub: index.md).
  • packages/design-playground/ — prototyping app with its own CLAUDE.md that overrides this one.

Environment

Docker (standard)

docker compose up   # frontend :5173, API :8000, DB :5432

Cloud / native

.claude/hooks/session-start.sh provisions everything (venv, PostgreSQL, npm install, Railway CLI) and is idempotent.

  • Always use service/.venv/bin/python — system python3 is 3.11, Django 6 requires 3.12+. The hook prepends the venv to PATH.
  • SQLite is not viable — some migrations use Postgres-only SQL. Use the native cluster.
  • DJANGO_DEBUG=True alone is sufficient to start the service against the local DB.
  • Without credentials, Firebase push (FIREBASE_PROJECT_ID) and Google OAuth (GOOGLE_CLIENT_ID) are disabled.
  • railway commands and /prod-query require Railway hosts allowlisted. In Claude Code on the web: set Network access to Custom, add *.railway.com and *.railway.app, and tick "Also include default list of common package managers".

Codegen

docker compose up codegen   # regenerates all four generated artefacts

Two OpenAPI schemas are produced from the same serializers, because the API has two wire representations:

Artefact Casing Consumer
service/openapi-schema.yaml camelCase HTTP clients — drives src/api/generated/ via orval
service/openapi-schema.internal.yaml snake_case in-process clients — drives service/harness/generated/api.py

camelCase is applied by CamelCaseJSONRenderer at render time, so response.data (what agent/api_client.py reads via DRF's APIClient) is snake_case. The internal schema is generated by passing --custom-settings project.openapi.INTERNAL_SCHEMA_SETTINGS, which drops the camelize postprocessing hook for that invocation only.

Never hand-edit service/harness/generated/api.py or packages/web/src/api/generated/ — both are regenerated.

After codegen, run npx tsc -b --noEmit in packages/web. See .claude/rules/backend/codegen.md for the environment config required to reproduce committed output byte-for-byte.

Tests

python -m pytest <file> -v          # single file — preferred while iterating
python -m pytest -n auto --reuse-db # full suite

Evals (service/)

python manage.py run_evals --limit 1   # quick smoke run

Permission policy: running a single epoch (the default — one pass over the dataset) is fine without asking. Do not run multiple epochs unless the user explicitly asks — that multiplies model calls and cost. For multiple epochs, invoke inspect_ai.eval(..., epochs=N) directly; the command exposes no --epochs flag.

dump_phase turns a live game phase into eval raw material:

python manage.py dump_phase --game <id> --out phase_dumps
cd packages/web
npx vite-node scripts/render-phase.mjs ../../service/phase_dumps/<prefix>_render.json /tmp/board.png

Design playground boundary

packages/design-playground/ prototypes screens before we build them, deploys independently, and ships to no users. Its own CLAUDE.md overrides this file — read it before working there. Two rules bind from this side:

  • packages/web must never import from the playground. The dependency direction is one-way; prototype code is rewritten into the app, not promoted out of it.
  • Design gallery screens belong in the playground, not the app. Do not add fixture-driven component galleries to packages/web.

Always

  • Follow existing patterns. New code should be indistinguishable from existing code in style and structure. Raise deviations as a discussion; do not silently deviate.
  • Do not add comments or docstrings, including in tests. Do not annotate assertions to explain their values. The only exception is DRF view docstrings, which are extracted for OpenAPI.
  • Never suppress lint or type violations — no eslint-disable, @ts-ignore, # noqa, pytest.mark.skip. The only exception is the mutation-in-useEffect pattern documented in .claude/rules/frontend.md.
  • Write tests alongside features, not as an afterthought.
  • Absent beats dormant scaffolding. Do not leave unused domain, apps, or wire fields “for later” — remove them and re-add when the feature is real. Backend detail in .claude/rules/backend/.

GitHub workflow

Soft WIP limits: 5 open PRs, 10 open issues. A bot warns when exceeded — check the count before opening a new PR.

Issues have three sections (enforced by the create-issue skill): Goal (always), Context (when useful), Approach (when discussed). No acceptance criteria or implementation checklists.

PR screenshots are a completion criterion, not optional polish. If a PR changes anything visible in the web app — new screens, layout, styling, copy, empty or error states — you MUST embed screenshots of the changed component in the PR description, so the reviewer sees what changed without pulling the branch. Use the screenshots skill for the workflow.

Never commit screenshots. Write them outside the working tree (/tmp/shots/) and upload them as GitHub attachments — do not add image files to the repo or reference them via raw.githubusercontent.com. screenshots/ and shots/ are gitignored; if you find committed screenshots, remove them.

Maintaining this document

When you establish a convention or make an architectural decision, update this file or the relevant file in .claude/rules/ in the same session — do not park lasting guidance only in a walkthrough ledger.

Guidance states rules, never inventories. Do not write out a list or table of what exists in the codebase — classes, fixtures, endpoints, components, settings. Claude reads the code; a copy in a guidance document only goes stale and is wrong the moment someone adds a class without updating it. Say which file to read instead. Illustrative examples of a pattern are fine; an enumeration meant to be exhaustive is not.