{"owner":"tambo-ai","repo":"tambo","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md","AGENTS.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nGuidelines for Claude Code (claude.ai/code) when touching this repo.\n\n**Read @AGENTS.md first.** It owns architecture, naming, workflow rules, testing expectations, and anything code-related. Keep that file open—this doc just points you there.\n\n## Three Things to Remember\n\n1. Follow that doc for everything: repo layout, commands, coding standards, doc rules, Charlie workflow, MCP guidance, etc.\n2. Use the workspace scripts it lists (see below for key commands).\n3. Defer to it whenever instructions collide; if something's still unclear, ask the user.\n\n## Key Commands\n\n```bash\n# Development (two different apps)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261\nnpm run dev              # Start React SDK (showcase + docs)\n\n# Quality checks (run before commits)\nnpm run lint\nnpm run check-types\nnpm test\n\n# Database (requires -w flag)\nnpm run db:generate -w packages/db\nnpm run db:migrate -w packages/db\nnpm run db:studio -w packages/db\n\n# Docker (for PostgreSQL in local dev)\ndocker compose --env-file docker.env up postgres -d\n```\n\n## Documentation Structure\n\n- **CONTRIBUTING.md** - Dev setup and PR workflow for contributors\n- **SELF-HOSTING.md** - Self-hosting/deployment guide\n- **AGENTS.md** - Coding standards, architecture (this is the source of truth)\n","AGENTS.md":"# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nGuidelines for Claude Code (claude.ai/code) when touching this repo.\n\n**Read @AGENTS.md first.** It owns architecture, naming, workflow rules, testing expectations, and anything code-related. Keep that file open—this doc just points you there.\n\n## Three Things to Remember\n\n1. Follow that doc for everything: repo layout, commands, coding standards, doc rules, Charlie workflow, MCP guidance, etc.\n2. Use the workspace scripts it lists (see below for key commands).\n3. Defer to it whenever instructions collide; if something's still unclear, ask the user.\n\n## Key Commands\n\n```bash\n# Development (two different apps)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261\nnpm run dev              # Start React SDK (showcase + docs)\n\n# Quality checks (run before commits)\nnpm run lint\nnpm run check-types\nnpm test\n\n# Database (requires -w flag)\nnpm run db:generate -w packages/db\nnpm run db:migrate -w packages/db\nnpm run db:studio -w packages/db\n\n# Docker (for PostgreSQL in local dev)\ndocker compose --env-file docker.env up postgres -d\n```\n\n## Documentation Structure\n\n- **CONTRIBUTING.md** - Dev setup and PR workflow for contributors\n- **SELF-HOSTING.md** - Self-hosting/deployment guide\n- **AGENTS.md** - Coding standards, architecture (this is the source of truth)\n","AGENTS.md":"# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nGuidelines for Claude Code (claude.ai/code) when touching this repo.\n\n**Read @AGENTS.md first.** It owns architecture, naming, workflow rules, testing expectations, and anything code-related. Keep that file open—this doc just points you there.\n\n## Three Things to Remember\n\n1. Follow that doc for everything: repo layout, commands, coding standards, doc rules, Charlie workflow, MCP guidance, etc.\n2. Use the workspace scripts it lists (see below for key commands).\n3. Defer to it whenever instructions collide; if something's still unclear, ask the user.\n\n## Key Commands\n\n```bash\n# Development (two different apps)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261\nnpm run dev              # Start React SDK (showcase + docs)\n\n# Quality checks (run before commits)\nnpm run lint\nnpm run check-types\nnpm test\n\n# Database (requires -w flag)\nnpm run db:generate -w packages/db\nnpm run db:migrate -w packages/db\nnpm run db:studio -w packages/db\n\n# Docker (for PostgreSQL in local dev)\ndocker compose --env-file docker.env up postgres -d\n```\n\n## Documentation Structure\n\n- **CONTRIBUTING.md** - Dev setup and PR workflow for contributors\n- **SELF-HOSTING.md** - Self-hosting/deployment guide\n- **AGENTS.md** - Coding standards, architecture (this is the source of truth)\n","category":"root","tokens":327},{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n","category":"root","tokens":6915}]}