2025-06-12 15:05:55 +00:00
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
2025-06-13 15:54:36 +00:00
## Project Overview
2025-06-12 15:05:55 +00:00
2025-06-13 15:54:36 +00:00
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:
2025-06-12 15:05:55 +00:00
2025-06-18 09:26:09 +00:00
- **API Service** (`apps/api/`) - Platform backend API with authentication, billing, and resource management
2025-06-12 15:05:55 +00:00
- **Gateway Service** (`apps/gateway/`) - Cloudflare Worker that proxies requests to origin MCP/OpenAPI services
2025-06-18 09:26:09 +00:00
- **Website** (`apps/web/`) - Next.js site for both the marketing site and authenticated webapp
2025-06-13 19:31:20 +00:00
- **E2E Tests** (`apps/e2e/`) - End-to-end test suite for HTTP and MCP gateway requests
2025-06-12 15:05:55 +00:00
- **Shared Packages** (`packages/`) - Common utilities, types, validators, and configuration
2025-06-18 09:26:09 +00:00
The gateway accepts requests at `https://gateway.agentic.so/deploymentIdentifier/toolName` for HTTP requests or `https://gateway.agentic.so/deploymentIdentifier/mcp` for MCP.
2025-06-12 15:05:55 +00:00
2025-06-13 15:54:36 +00:00
### Development Commands
2025-06-12 15:05:55 +00:00
**Main development workflow:**
- `pnpm dev` - Start all services in development mode
- `pnpm build` - Build all packages and apps
2025-06-18 09:26:09 +00:00
- `pnpm test` - Run all tests (format, lint, typecheck, unit, but not e2e tests)
2025-06-12 15:05:55 +00:00
- `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:**
2025-06-18 09:26:09 +00:00
- (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
2025-06-12 15:05:55 +00:00
2025-06-13 15:54:36 +00:00
### Key Database Models
2025-06-12 15:05:55 +00:00
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
2025-06-18 09:26:09 +00:00
- **Deployment** - Immutable instances of MCP/OpenAPI services, including gateway and pricing config
2025-06-12 15:05:55 +00:00
- **Consumer** - Customer subscription tracking usage and billing
2025-06-13 15:54:36 +00:00
### Agentic Configuration
2025-06-12 15:05:55 +00:00
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.
2025-06-13 15:54:36 +00:00
### Gateway Request Flow
2025-06-12 15:05:55 +00:00
1. Request hits gateway with deployment identifier
2025-06-18 09:26:09 +00:00
2. Gateway validates consumer authentication/rate limits/caching
2025-06-12 15:05:55 +00:00
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
2025-06-13 15:54:36 +00:00
### Environment Setup
2025-06-12 15:05:55 +00:00
2025-06-18 09:26:09 +00:00
All apps require environment variables for:
2025-06-12 15:05:55 +00:00
- Database connections (`DATABASE_URL`)
- External services (Stripe, GitHub, Resend, Sentry)
2025-06-18 09:26:09 +00:00
- Internal services (API, gateway, etc)
2025-06-12 15:05:55 +00:00
- Authentication secrets
2025-06-18 09:26:09 +00:00
- Stripe secrets
2025-06-12 15:05:55 +00:00
- Admin API keys
2025-06-18 09:26:09 +00:00
- Sentry DSN
- etc
2025-06-13 15:54:36 +00:00
## 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'`
2025-06-18 09:26:09 +00:00
- Always prefer named exports over default exports except for when default exports are required (like in Next.js `page.tsx` components)
2025-06-13 15:54:36 +00:00
### 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` .
2025-06-13 19:31:20 +00:00
- Try not to rely on `typeof` , `ReturnType<>` , `Awaited<>` , etc for complex type inference (it's ok for simple types)
2025-06-13 15:54:36 +00:00
- You can use `as const` as needed for better type inference
- Functions should accept an object parameter instead of multiple parameters
2025-06-13 19:31:20 +00:00
- GOOD examples:
2025-06-13 15:54:36 +00:00
```ts
function myFunction({ foo, bar }: { foo: boolean; bar: string }) {}
function VideoPlayer({ sid }: { sid: string }) {}
```
2025-06-13 19:31:20 +00:00
- BAD examples:
2025-06-13 15:54:36 +00:00
```ts
function myFunction(foo: boolean, bar: string, baz: number) {}
```
- Arguments should generally be destructured in the function definition, not the function body.
2025-06-13 19:31:20 +00:00
- GOOD example:
2025-06-13 15:54:36 +00:00
```ts
function myFunction({ foo, bar }: { foo: boolean; bar: string }) {}
2025-06-13 19:31:20 +00:00
function exampleWithOptionalParams({
foo = 'example'
}: { foo?: string } = {}) {}
2025-06-13 15:54:36 +00:00
```
2025-06-13 19:31:20 +00:00
- BAD example:
2025-06-13 15:54:36 +00:00
```ts
2025-06-13 19:31:20 +00:00
function myFunction(opts: { foo: boolean; bar: string }) {
const { foo, bar } = opts
2025-06-13 15:54:36 +00:00
}
```
- 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)
2025-06-13 19:31:20 +00:00
- 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`
2025-06-13 15:54:36 +00:00
- 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