8.8 KiB
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 modepnpm 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 Prettierpnpm test:lint- Run ESLint across all packagespnpm test:typecheck- Run TypeScript type checkingpnpm test:unit- Run unit tests with Vitest
Code quality:
pnpm fix- Auto-fix formatting and linting issuespnpm knip- Check for unused dependencies
E2E testing:
- (from the
apps/e2edirectory) pnpm e2e- Run all E2E testspnpm e2e-http- Run HTTP edge E2E testspnpm 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
- Request hits gateway with deployment identifier
- Gateway validates consumer authentication/rate limits/caching
- Request is transformed and forwarded to origin service
- Response is processed and returned with appropriate headers
- 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
constoverlet(never usevar) - Use kebab-case for file and directory names
- Use clear, descriptive names for variables, functions, and components
Modules
- Always use ESM
importandexport(never use CJSrequire)- File imports should never use an extension (NOT
.js,.tsor.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'
- File imports should never use an extension (NOT
- Always prefer named exports over default exports except for when default exports are required (like in Next.js
page.tsxcomponents)
Packages
All packages must follow these package.json rules:
typemust be set tomodule
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/unknownor casting values like(value as any)in TypeScript outside of test files e.g.*.test.tsor 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 constas needed for better type inference - Functions should accept an object parameter instead of multiple parameters
- GOOD examples:
function myFunction({ foo, bar }: { foo: boolean; bar: string }) {} function VideoPlayer({ sid }: { sid: string }) {} - BAD examples:
function myFunction(foo: boolean, bar: string, baz: number) {}
- GOOD examples:
- Arguments should generally be destructured in the function definition, not the function body.
- GOOD example:
function myFunction({ foo, bar }: { foo: boolean; bar: string }) {} function exampleWithOptionalParams({ foo = 'example' }: { foo?: string } = {}) {} - BAD example:
function myFunction(opts: { foo: boolean; bar: string }) { const { foo, bar } = opts }
- GOOD example:
- 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 enumz.enum([ 'youtube', 'spotify' ])
- For example, this union
- Promises (and
asyncfunctions which implicitly create Promises) must always be properly handled, either via:- Using
awaitto wait for the Promise to resolve successfully - Using
.thenor.catchto handle Promise resolution - Returning a Promise to a calling function which itself has to handle the Promise.
- Using
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
fetchAPI for making HTTP requests instead of Node.js modules likehttporhttps- Prefer using the
kyfetchwrapper for HTTP requests instead ofaxios,superagent,node-fetchor any other HTTP request library - Never use
node-fetch; preferkyor nativefetchdirectly
- Prefer using the
- Use the WHATWG
URLandURLSearchParamsclasses instead of the Node.jsurlmodule - Use
RequestandResponseobjects from the Fetch API instead of Node.js-specific request and response objects
Error Handling
- Prefer
async/awaitover.then()and.catch() - Always handle errors correctly (eg:
try/catchor.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
consolefor 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.tsand placed in the same directory as the code they are testing (NOT a separate directory)- GOOD example:
src/my-file.tsandsrc/my-file.test.ts - BAD example:
src/my-file.tsandsrc/test/my-file.test.tsortest/my-file.test.tsorsrc/__tests__/my-file.test.ts
- GOOD example:
- Tests should be run with
pnpm test:unit - You may use
any/unknownin 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 addandgit commitcommands into a singlegit commit -amcommand, to speed things up