Skip to content

Latest commit

 

History

History
70 lines (54 loc) · 5.6 KB

File metadata and controls

70 lines (54 loc) · 5.6 KB

CLAUDE.md

Guidance for Claude Code working in this repository. Super Productivity is a todo and time-tracking app on Angular + Electron + Capacitor.

Required reading per task

Core commands

ALWAYS run npm run checkFile <filepath> on every .ts or .scss file you modify before reporting work as done.

npm run checkFile <filepath>   # prettier + lint a single file
npm run prettier               # multi-file format
npm run lint                   # multi-file lint
npm test                       # all unit tests (Jasmine/Karma, .spec.ts co-located)
npm run test:file <filepath>   # single spec
npm run e2e                    # all E2E (Playwright, slow)
npm run e2e:file <path> -- --retries=0   # single E2E (~20s/test); add --grep "name" for one test
npm start                      # Electron dev
ng serve                       # web dev (or npm run startFrontend)
npm run dist                   # production build (all platforms available locally)

For SuperSync E2E (docker-compose) and the full E2E reference, see e2e/CLAUDE.md.

Project rules

  • Translations: UI strings go through T / TranslateService. Edit only en.json; never other locales.
  • Privacy: no analytics or tracking — user data stays local unless explicitly synced.
  • Electron: check IS_ELECTRON before using Electron-specific APIs.
  • Templates: plain HTML, minimal CSS/classes, Angular Material sparingly. See docs/styling-guide.md.
  • Strict TypeScript: no any (use unknown if truly unknown).
  • State: never mutate NgRx state — return new objects in reducers. Prefer Signals to Observables.
  • Tests: add unit tests for new services and state logic.

Sync-correctness rules

Touched on most state-related PRs. Read the linked source/doc for full reasoning before editing. Rules 1–3 and 6 are one invariant — one user intent = one op; replayed/remote ops must not re-trigger effects — fully explained in docs/sync-and-op-log/contributor-sync-model.md.

  1. Effects inject LOCAL_ACTIONS, never Actions (ALL_ACTIONS only for the op-log capture effect; remote archive side effects → ArchiveOperationHandler, not ALL_ACTIONS). Lint-enforced (no-actions-in-effects). → contributor-sync-model.md, src/app/util/local-actions.token.ts.
  2. Prefer action-based effects; a selector-based effect needs skipDuringSyncWindow(). Lint-enforced (require-hydration-guard). → contributor-sync-model.md.
  3. Multi-entity change = meta-reducer, not an effect fan-out (one reducer pass = one op). → contributor-sync-model.md, src/app/root-store/meta/task-shared-meta-reducers/.
  4. Logical clock: route "what day is this?" through DateService (getLogicalTodayDate, isToday, todayStr). Pure reducers/selectors take startOfNextDayDiffMs as an arg and call isTodayWithOffset for replay determinism. The raw DateService.startOfNextDayDiff is private; use getStartOfNextDayDiffMs() at service boundaries.
  5. TODAY_TAG ('TODAY') is virtual — never add to task.tagIds; membership comes from task.dueWithTime or task.dueDay. TODAY_TAG.taskIds only stores ordering. → ARCHITECTURE-DECISIONS.md Decision #2.
  6. Bulk dispatch loop: await new Promise(r => setTimeout(r, 0)) after the loop (else 50+ rapid dispatches lose state). → contributor-sync-model.md, OperationApplierService.applyOperations().
  7. SYNC_IMPORT / BACKUP_IMPORT replace state and intentionally drop concurrent ops (CONCURRENT or LESS_THAN by vector clock) — by design, not a bug. → SyncImportFilterService.
  8. Vector clocks: MAX_VECTOR_CLOCK_SIZE = 20. Server prunes after conflict detection, before storage. → docs/sync-and-op-log/vector-clocks.md.
  9. Logging: Log.log({ id: task.id }), never Log.log(task) or Log.log(title) — log history is exportable, never log user content.

Commit messages

Angular format type(scope): description. Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore. Examples: feat(tasks): add recurring task support, fix(sync): handle network timeout. Never fix(test): or fix(e2e): — test changes use test:.

Anti-patterns

Avoid Do instead
any type proper types, unknown if truly unknown
Direct DOM access Angular bindings, viewChild()
Side effects in constructors async pipe or toSignal
Subscribing without cleanup takeUntilDestroyed() or async pipe
NgModules for new code standalone components
Re-declaring Material theme styles existing theme variables