This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
MeshiTrack is a self-hosted medicine & nutrition management platform. It is a TypeScript monorepo with three packages: `packages/api` (Fastify backend), `packages/web` (Next.js frontend), and `packages/shared` (types + Zod schemas used by both). Medicine tracking is implemented first (Phases 1-4), followed by food tracking (Phases 5-9).
- **`packages/shared`** — Single source of truth for all domain types, enums, and Zod v4 schemas. Consumed by both `api` and `web`. Must be pure TypeScript with no Node.js, browser, or framework dependencies.
- **`packages/api`** — Fastify 5 backend. ESM-only, TypeScript strict. Uses Awilix for DI, Mongoose 9 for MongoDB, jose 6 for JWT verification.
Every domain document is scoped to a `householdId`. A Fastify `preHandler` hook validates the `householdId` from the URI against the user's `householdIds[]` JWT claim. **Every data query must filter by `householdId`.**
Routes can opt out with `config: { public: true }` (skips auth) or `config: { skipHousehold: true }` (skips household validation).
Services throw `AppError` subclasses (`NotFoundError`, `ConflictError`, `ForbiddenError`, etc.). The global Fastify error handler maps them to the standard `ApiError` response shape (`statusCode`, `error`, `message`, `timestamp`, `path`).
## Key Rules
1.**No `any` types** — use `unknown` + Zod validation at boundaries
2.**ESM everywhere** — `"type": "module"`, `.js` extensions on all imports, `import type` for type-only
3.**Cursor-based pagination only** — never `skip()` for large collections
4.**Zod v4** — import from `'zod/v4'`
5.**`.lean().exec()`** on all Mongoose read queries
6.**`householdId` filter** on every domain query — this is the multi-tenancy boundary
7.**No emojis** — never use emoji characters in source code, UI text, console output, or documentation
9.**Never pipe or redirect `npm run` commands** — run `npm run <script>` exactly as written; never append `2>&1`, `|`, `Select-Object`, `Select-String`, or any other shell constructs to it.
10.**Never use shell commands to read files** — always use `read_file` tool. Commands like `Get-Content`, `cat`, `head`, `tail` will be denied.
11.**Never use shell commands to search** — always use `grep_search` or `file_search`. Commands like `Select-String`, `grep`, `rg`, `find` will be denied.
12.**Never call tools in parallel** — always wait for one tool call to complete before calling the next. This applies to all tools: file reads, searches, and terminal commands.
13.**Every implementation task must end with `npm run build`, `npm run test:cov`, and `npm run lint` all passing.** Always use `test:cov` (not `test`) to enforce coverage thresholds. If coverage fails, write additional tests before considering the task done.