mirror of https://github.com/buster-so/buster.git
5.3 KiB
5.3 KiB
CLAUDE.md
This file provides core guidance to Claude/AI assistants when working with the Buster monorepo.
Note: Each package and app has its own CLAUDE.md with specific implementation details. This document contains only universal principles.
Monorepo Philosophy
Architecture Principles
- Packages are standalone building blocks - Modular components with minimal cross-dependencies
- Apps assemble packages - Apps piece together package code, never contain business logic directly
- Avoid spaghetti dependencies - Keep clean boundaries between packages
- Type flow hierarchy - Types flow:
database
→server-shared
→apps
Critical Package Boundaries
@buster/database
- Owns ALL database queries. No direct Drizzle usage elsewhere@buster/server-shared
- API contract layer. All request/response types live here@buster/data-source
- Isolated data source connection logic for customer databases- Package imports - Packages can use each other but maintain clear, logical dependencies
Development Principles
Functional Programming First
- Pure functions only - No classes for business logic
- Composable modules - Build features by composing small, focused functions
- Immutable data - Never mutate; always create new data structures
- Higher-order functions - Use functions that return configured functions for dependency injection
- No OOP - No classes, no inheritance, no
this
keyword in business logic
Type Safety Standards
- Zod-first everything - Define ALL types as Zod schemas with descriptions
- Export inferred types - Always use
z.infer<typeof Schema>
for TypeScript types - Runtime validation - Use
.parse()
for trusted data,.safeParse()
for user input - No implicit any - Every variable, parameter, and return type must be explicitly typed
- Constants for strings - Use const assertions for type-safe string literals
Testing Philosophy
- Test-driven development - Write tests and assertions first, then implement
- Colocate tests - Keep
.test.ts
(unit) and.int.test.ts
(integration) next to implementation - Test naming - If file is
user.ts
, tests areuser.test.ts
and/oruser.int.test.ts
- Minimize integration dependencies - Most logic should be testable with unit tests
- Test descriptions - Test names should describe the assertion and situation clearly
Development Workflow
Command Standards
CRITICAL: Only use Turbo commands. Never use pnpm, npm, or vitest directly.
# Build commands
turbo build # Build entire monorepo
turbo build --filter=@buster/ai # Build specific package
# Linting
turbo lint # Lint entire monorepo
turbo lint --filter=@buster-app/web # Lint specific app
# Testing
turbo test:unit # Run all unit tests
turbo test:unit --filter=@buster/database # Test specific package
turbo test:integration --filter=@buster/ai # Integration tests for specific package
# Development
turbo dev # Start development servers
Pre-Completion Checklist
Before completing any task:
- Run
turbo build
- Ensure everything compiles - Run
turbo lint
- Fix all linting issues - Run
turbo test:unit
- All unit tests must pass
Code Organization
File Structure
- Small, focused files - Each file has a single responsibility
- Deep nesting is OK - Organize into logical subdirectories
- Explicit exports - Use named exports and comprehensive index.ts files
- Functional patterns - Export factory functions that return configured function sets
Module Patterns
// Good: Functional approach with Zod
import { z } from 'zod';
const UserParamsSchema = z.object({
userId: z.string().describe('Unique user identifier'),
orgId: z.string().describe('Organization identifier')
});
type UserParams = z.infer<typeof UserParamsSchema>;
export function validateUser(params: UserParams) {
const validated = UserParamsSchema.parse(params);
// Implementation
}
// Bad: Class-based approach
class UserService { // Never do this
validateUser() { }
}
Cross-Cutting Concerns
Environment Variables
- Centralized at root level in
.env
file - Turbo passes variables via
globalEnv
configuration - Individual packages validate their required variables
Database Operations
- ALL queries go through
@buster/database
package - Never use Drizzle directly outside the database package
- Soft deletes only (use
deleted_at
field) - Prefer upserts over updates
API Development
- Request/response types in
@buster/server-shared
- Import database types through server-shared for consistency
- Validate with Zod at API boundaries
- Use type imports:
import type { User } from '@buster/database'
Legacy Code Migration
- Rust code (
apps/api
) is legacy and being migrated to TypeScript - Focus new development on TypeScript patterns
- Follow patterns in
apps/server
for new API development
Agent Workflows
- Use
planner
agent for spec, plan, ticket, research development workflows.
Important Reminders
- Do only what has been asked; nothing more, nothing less
- Never create files unless absolutely necessary
- Always prefer editing existing files over creating new ones
- Never proactively create documentation unless explicitly requested
- Check package/app-specific CLAUDE.md files for implementation details