# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a monorepo for Agentic - a platform that provides API gateway services for MCP (Model Context Protocol) and OpenAPI integrations. ### Core Architecture The platform consists of: - **API Service** (`apps/api/`) - Platform backend API with authentication, billing, and resource management - **Gateway Service** (`apps/gateway/`) - Cloudflare Worker that proxies requests to origin MCP/OpenAPI services - **Website** (`apps/web/`) - Next.js site for both the marketing site and authenticated webapp - **E2E Tests** (`apps/e2e/`) - End-to-end test suite for HTTP and MCP gateway requests - **Shared Packages** (`packages/`) - Common utilities, types, validators, and config - **StdLib Packages** (`stdlib/`) - TS AI SDK adapters The gateway accepts HTTP requests at `https://gateway.agentic.so/deploymentIdentifier/tool-name` or `https://gateway.agentic.so/deploymentIdentifier/mcp` for MCP. ### Development Commands **Main development workflow:** - `pnpm dev` - Start all services in development mode - `pnpm build` - Build all packages and apps (except for the website) - `pnpm test` - Run all tests (format, lint, typecheck, unit, but not e2e tests) - `pnpm clean` - Clean all build artifacts **Individual test commands:** - `pnpm test:format` - Check code formatting with Prettier - `pnpm test:lint` - Run ESLint across all packages - `pnpm test:typecheck` - Run TypeScript type checking - `pnpm test:unit` - Run unit tests with Vitest **Code quality:** - `pnpm fix` - Auto-fix formatting and linting issues - `pnpm knip` - Check for unused dependencies **E2E testing:** - (from the `apps/e2e` directory) - `pnpm e2e` - Run all E2E tests - `pnpm e2e-http` - Run HTTP edge E2E tests - `pnpm e2e-mcp` - Run MCP edge E2E tests ### Key Database Models The system uses Drizzle ORM with PostgreSQL. Core entities: - **User** - Platform users - **Team** - Organizations with members and billing - **Project** - Namespace API products comprised of immutable Deployments - **Deployment** - Immutable instances of MCP/OpenAPI services, including gateway and pricing config - **Consumer** - Customer subscription tracking usage and billing ### Agentic Configuration Agentic projects use `agentic.config.{ts,js,json}` files to define: - Project name and metadata - Origin adapter (MCP server or OpenAPI spec) - Tool configurations and permissions - Pricing plans and rate limits - Authentication requirements The platform supports both MCP servers and OpenAPI specifications as origin adapters. ### Gateway Request Flow 1. Request hits gateway with deployment identifier 2. Gateway validates consumer authentication/rate limits/caching 3. Request is transformed and forwarded to origin service 4. Response is processed and returned with appropriate headers 5. Usage is tracked for billing and analytics ### Environment Setup All apps require environment variables for: - Database connections (`DATABASE_URL`) - External services (Stripe, GitHub, Resend, Sentry) - Internal services (API, gateway, etc) - Authentication secrets - Stripe secrets - Admin API keys - Sentry DSN - etc ## Coding Conventions ### General - Write elegant, concise, and readable code - Prefer `const` over `let` (never use `var`) - Use kebab-case for file and directory names - Use clear, descriptive names for variables, functions, and components ### Modules - Always use ESM `import` and `export` (never use CJS `require`) - File imports should never use an extension (NOT `.js`, `.ts` or `.tsx`). - GOOD examples: - `import { Foo } from './foo'` - `import { type Route } from './types/root'` - `import zod from 'zod'` - `import { logger } from '~/types'` - BAD examples: - `import { Foo } from './foo.js'` - `import { type Route } from './types/root.js'` - `import { Foo } from './foo.ts'` - Always prefer named exports over default exports except for when default exports are required (like in Next.js `page.tsx` components) ### Packages All packages must follow these `package.json` rules: - `type` must be set to `module` ### TypeScript - Avoid semicolons at the end of lines - Use TypeScript's utility types (e.g., `Partial`, `Pick`, `Omit`) to manipulate existing types - Create custom types for complex data structures used throughout the application - If possible, avoid using `any`/`unknown` or casting values like `(value as any)` in TypeScript outside of test files e.g. `*.test.ts` or test fixtures e.g. `**/test-data.ts`. - Try not to rely on `typeof`, `ReturnType<>`, `Awaited<>`, etc for complex type inference (it's ok for simple types) - You can use `as const` as needed for better type inference - Functions should accept an object parameter instead of multiple parameters - GOOD examples: ```ts function myFunction({ foo, bar }: { foo: boolean; bar: string }) {} function VideoPlayer({ sid }: { sid: string }) {} ``` - BAD examples: ```ts function myFunction(foo: boolean, bar: string, baz: number) {} ``` - Arguments should generally be destructured in the function definition, not the function body. - GOOD example: ```ts function myFunction({ foo, bar }: { foo: boolean; bar: string }) {} function exampleWithOptionalParams({ foo = 'example' }: { foo?: string } = {}) {} ``` - BAD example: ```ts function myFunction(opts: { foo: boolean; bar: string }) { const { foo, bar } = opts } ``` - Zod should be used to parse untrusted data, but not for data that is trusted like function arguments - Prefer Zod unions over Zod enums - For example, this union `z.union([ z.literal('youtube'), z.literal('spotify') ])` is better than this enum `z.enum([ 'youtube', 'spotify' ])` - Promises (and `async` functions which implicitly create Promises) must always be properly handled, either via: - Using `await` to wait for the Promise to resolve successfully - Using `.then` or `.catch` to handle Promise resolution - Returning a Promise to a calling function which itself has to handle the Promise. ## Node.js - Utilize the `node:` protocol when importing Node.js modules (e.g., `import fs from 'node:fs/promises'`) - Prefer promise-based APIs over Node's legacy callback APIs - Use environment variables for secrets (avoid hardcoding sensitive information) ### Web Standard APIs Always prefer using standard web APIs like `fetch`, `WebSocket`, and `ReadableStream` when possible. Avoid redundant libraries (like `node-fetch`). - Prefer the `fetch` API for making HTTP requests instead of Node.js modules like `http` or `https` - Prefer using the `ky` `fetch` wrapper for HTTP requests instead of `axios`, `superagent`, `node-fetch` or any other HTTP request library - Never use `node-fetch`; prefer `ky` or native `fetch` directly - Use the WHATWG `URL` and `URLSearchParams` classes instead of the Node.js `url` module - Use `Request` and `Response` objects from the Fetch API instead of Node.js-specific request and response objects ### Error Handling - Prefer `async`/`await` over `.then()` and `.catch()` - Always handle errors correctly (eg: `try`/`catch` or `.catch()`) - Avoid swallowing errors silently; always log or handle caught errors appropriately ### Comments Comments should be used to document and explain code. They should complement the use of descriptive variable and function names and type declarations. - Add comments to explain complex sections of code - Add comments that will improve the autocompletion preview in IDEs (eg: functions and types) - Don't add comments that just reword symbol names or repeat type declarations - Use **JSDoc** formatting for comments (not TSDoc or inline comments) ### Logging - Just use `console` for logging. ### Testing #### Unit Testing - **All unit tests should use Vitest** - DO NOT attempt to install or use other testing libraries like Jest - Test files should be named `[target].test.ts` and placed in the same directory as the code they are testing (NOT a separate directory) - GOOD example: `src/my-file.ts` and `src/my-file.test.ts` - BAD example: `src/my-file.ts` and `src/test/my-file.test.ts` or `test/my-file.test.ts` or `src/__tests__/my-file.test.ts` - Tests should be run with `pnpm test:unit` - You may use `any`/`unknown` in test files (such as `*.test.ts`) or test fixtures (like `**/test-data.ts`) to facilitate mocking or stubbing external modules or partial function arguments, referencing the usage guidelines in the TypeScript section. - Frontend react code does not need unit tests #### Test Coverage - Test critical business logic and edge cases - Don't add tests for trivial code or just to increase test coverage - Don't make tests too brittle or flaky by relying on implementation details ### Git - When possible, combine the `git add` and `git commit` commands into a single `git commit -am` command, to speed things up