Skip to content

AI Workflow ​

AgentReady Stack is built from the ground up for AI-assisted development. Point Claude, Cursor, or ChatGPT at this codebase and watch them write code that actually works.

The Core Idea ​

Most codebases fail with AI agents because:

  • AI doesn't know your architecture
  • AI creates types that don't match your backend
  • AI puts code in the wrong places
  • AI-generated code breaks your tests

AgentReady Stack solves this with AGENTS.md—a comprehensive guide that AI agents read before writing code. When Claude reads your codebase, it reads AGENTS.md first and follows the patterns.

The AGENTS.md File ​

At the root of the repository, AGENTS.md contains instructions for AI agents:

markdown
# INSTRUCTIONS FOR AI AGENTS

When writing code for this repository, you MUST strictly adhere
to the following architectural constraints...

How Different AI Tools Discover AGENTS.md ​

ToolDiscovery Method
Claude CodeReads CLAUDE.md automatically, which references AGENTS.md
CursorReads .cursorrules which summarizes and references AGENTS.md
ChatGPT/OtherReads README.md which prominently links to AGENTS.md

All three discovery files are configured to direct agents to AGENTS.md for complete guidelines.

The Golden Rule: Type Flow ​

The most important pattern in AgentReady Stack:

Backend DTOs → OpenAPI → Generated Client → Frontend/CLI

AI agents must never:

  • Create duplicate types in the frontend
  • Manually write API response interfaces
  • Skip running pnpm codegen after backend changes

AI agents should always:

  • Define types as DTOs in the backend first
  • Use @ApiProperty() decorators for OpenAPI
  • Import types from @platform/api-client

Feature Scaffolding Workflow ​

When you ask an AI to add a new feature, it follows this order:

1. Create Backend DTOs ​

typescript
// apps/api/src/products/dto/create-product.dto.ts
export class CreateProductDto {
  @ApiProperty()
  @IsString()
  name!: string;

  @ApiPropertyOptional()
  @IsNumber()
  price?: number;
}

2. Create Backend Module ​

typescript
// apps/api/src/products/products.controller.ts
@ApiTags('Products')
@Controller('products')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class ProductsController {
  @Post()
  async create(@Body() dto: CreateProductDto) {
    return this.service.create(dto);
  }
}

3. Create Database Entity ​

typescript
// packages/database/src/entities/product.entity.ts
@Entity()
export class ProductEntity extends BaseEntity {
  @Property()
  name!: string;

  @Property({ nullable: true })
  price?: number;
}

4. Regenerate API Client ​

bash
pnpm codegen

5. Create Frontend Route ​

typescript
// apps/web/app/routes/products.tsx
export async function loader({ request }: Route.LoaderArgs) {
  const session = await requireUser(request);
  const products = await getProducts(session.accessToken);
  return { products };
}

export default function Products() {
  const { products } = useLoaderData<typeof loader>();
  return <ProductList items={products} />;
}

6. (Optional) Create CLI Command ​

typescript
// apps/cli/src/commands/products/list.ts
export default class ListProducts extends AuthenticatedCommand {
  async run() {
    const products = await this.apiClient.getProducts();
    this.table(products, { name: {}, price: {} });
  }
}

Layer-Specific Patterns ​

Backend Rules ​

RuleWhy
Always use @UseGuards(JwtAuthGuard) on protected endpointsSecurity
Transform entities to DTOs in controllersNever leak database structure
Use class-validator decoratorsAutomatic validation
Add @ApiProperty() decoratorsOpenAPI generation

Frontend Rules ​

RuleWhy
Fetch data in loader, never in useEffectSSR and performance
Mutations in action functionsReact Router pattern
Use typeof loader for type inferenceType safety
Return errors from actions, don't throwBetter UX

CLI Rules ​

RuleWhy
Extend AuthenticatedCommand for protected commandsAutomatic credential handling
Use ApiClient class for API callsConsistent auth headers
No business logic in command filesSeparation of concerns

Testing Patterns ​

AI agents write tests that follow these patterns:

Backend Unit Tests ​

typescript
describe('ProductsService', () => {
  let service: ProductsService;
  let mockRepo: ReturnType<typeof createMockRepository>;

  beforeEach(async () => {
    mockRepo = createMockRepository();
    const module = await Test.createTestingModule({
      providers: [
        ProductsService,
        { provide: getRepositoryToken(ProductEntity), useValue: mockRepo },
      ],
    }).compile();
    service = module.get(ProductsService);
  });

  it('should create a product', async () => {
    mockRepo.create.mockReturnValue({ id: '1', name: 'Test' });
    const result = await service.create({ name: 'Test' });
    expect(result.name).toBe('Test');
  });
});

Frontend Component Tests ​

typescript
vi.mock('react-router', async () => {
  const actual = await vi.importActual('react-router');
  return {
    ...actual,
    useLoaderData: () => ({ products: [{ id: '1', name: 'Test' }] }),
  };
});

describe('Products', () => {
  it('renders product list', () => {
    render(<Products />);
    expect(screen.getByText('Test')).toBeInTheDocument();
  });
});

Common Commands Reference ​

AI agents use these commands frequently:

bash
# Start development
pnpm dev

# After changing backend DTOs
pnpm codegen

# Type check everything
pnpm typecheck

# Run all tests
pnpm test

# Run E2E tests
pnpm test:e2e

# Start specific app
pnpm --filter @platform/api dev
pnpm --filter @platform/web dev

Tips for Working with AI ​

  1. Be specific about the layer: "Add a backend endpoint" vs "Add a frontend page"
  2. Mention the type flow: "Create the DTO first, then I'll run codegen"
  3. Reference existing patterns: "Follow the organization module pattern"
  4. Ask for tests: "Include unit tests following the existing patterns"

The Result ​

With AgentReady Stack:

  • AI writes code that fits — No more fighting hallucinations
  • Tests catch mistakes — AI-generated code is verified automatically
  • Types stay in sync — Change once, propagate everywhere
  • You ship faster — Hours instead of weeks

Example Prompts That Work ​

Here are prompts you can give Claude right after setup:

"Add a projects feature similar to organizations. Projects belong to
an organization and have a name, description, and status."
"Create a CLI command to list all projects in the current organization."
"Add a frontend page that shows all projects with a create button."

Claude will read AGENTS.md, understand the patterns, and write code that fits.