# AGENTS.md It's a Plan, a self-hosted project tracker. Bun + Turborepo monorepo: Elysia api, Next.js (SSR) web with shadcn/ui, better-auth, Drizzle + PostgreSQL. Before you change files in an app or package, read its `AGENTS.md`: `apps/api`, `apps/web`, `apps/worker`, `apps/bot`, `packages/auth`, `packages/db`. It overrides this file. ## Rules - **KISS and YAGNI, no exceptions.** Write the simplest thing that works. Add an abstraction only when several concrete implementations need it. - Study the existing code first and follow its patterns. Reuse shared modules, components and utilities. Extend them instead of adding a parallel solution. - **Bun only.** `bun install`, `bun run`. Never npm, yarn, or pnpm. Run tasks from the repo root. - All code, comments and strings are in English. - Cross-package imports use the workspace protocol: `"@repo/db": "workspace:*"`. Packages export raw `.ts` and have no build step. `packages/runner` is the exception: it is published to npm, bundles to `dist/`, and its source uses no Bun APIs because the CLI runs on plain Node. - The web app never imports a package. It calls the API over HTTP. Dependencies run `api → @repo/auth → @repo/db → @repo/crypto`. - A server-side fetch of a supplied URL goes through `@repo/net`, the SSRF guard. - Never skip the pre-commit hook with `--no-verify`. It runs `eslint --fix` and `prettier --write`. - Minimum comments. A comment says why; the code says what. No comment longer than its code, none on layout or styling. Change or delete a comment in the same edit as its code. Full rules are in the `tidy` skill. ## When the work is done Run on the new code, in this order, without being asked: `tidy`, `code-review`, `security-audit`. Then propose a commit message in chat. Never run `git commit` or `git push` unless the user asks. ## Writing style (docs, comments, commits, chat) - Plain, literal, short sentences. No metaphors, personification or drama. Bad: "data lives in Postgres", "self-healing queue". Good: "data is stored in Postgres", "a failed donor is retried on the next run". Standard terms (queue, pipeline, backlog, watermark) are fine. - Write the final state, not the edit history. Do not write "not X, but Y", "previously", "moved from", "decided". - Forward-looking rationale is allowed ("column `project_key` is added now so steps 3–4 need no migration"). A discarded idea appears only as a lasting "considered and rejected because…". ## Commands (from root) | Command | Purpose | | ------------------------- | --------------------------------------------------------- | | `bun run dev` | api, web, worker and bot in watch mode | | `bun run typecheck` | tsc in every workspace member, then at the root | | `bun run lint` | ESLint across the workspace | | `bun run format:check` | Prettier check (CI runs the same) | | `bun run test` | `scripts/` tests, then every member's suite | | `bun run db:generate` | generate SQL migrations from the Drizzle schema | | `bun run db:migrate` | apply migrations | | `bun run db:migrate:test` | apply migrations to the test DB (`.env.test`) | | `bun run auth:generate` | regenerate better-auth tables | - One test file: `cd apps/api && bun test --env-file=../../.env.test `. worker, bot and `packages/db` need the same flag. Packages without a database need no flag. - `bun --filter` needs the `=` form: `bun --filter='@repo/db' run