304 lines
9.9 KiB
Markdown
304 lines
9.9 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Build and Development Commands
|
|
|
|
This is a pnpm 10.23.0 monorepo using Turborepo. Run commands from root with `pnpm run`.
|
|
|
|
### Essential Commands
|
|
|
|
```bash
|
|
# Start Docker services (PostgreSQL, Redis, Electric)
|
|
pnpm run docker
|
|
|
|
# Run database migrations
|
|
pnpm run db:migrate
|
|
|
|
# Seed the database (required for reference projects)
|
|
pnpm run db:seed
|
|
|
|
# Build packages (required before running)
|
|
pnpm run build --filter webapp && pnpm run build --filter trigger.dev && pnpm run build --filter @trigger.dev/sdk
|
|
|
|
# Run webapp in development mode (http://localhost:3030)
|
|
pnpm run dev --filter webapp
|
|
|
|
# Build and watch for changes (CLI and packages)
|
|
pnpm run dev --filter trigger.dev --filter "@trigger.dev/*"
|
|
```
|
|
|
|
### Testing
|
|
|
|
We use vitest exclusively. **Never mock anything** - use testcontainers instead.
|
|
|
|
```bash
|
|
# Run all tests for a package
|
|
pnpm run test --filter webapp
|
|
|
|
# Run a single test file (preferred - cd into directory first)
|
|
cd internal-packages/run-engine
|
|
pnpm run test ./src/engine/tests/ttl.test.ts --run
|
|
|
|
# May need to build dependencies first
|
|
pnpm run build --filter @internal/run-engine
|
|
```
|
|
|
|
Test files go next to source files (e.g., `MyService.ts` → `MyService.test.ts`).
|
|
|
|
#### Testcontainers for Redis/PostgreSQL
|
|
|
|
```typescript
|
|
import { redisTest, postgresTest, containerTest } from "@internal/testcontainers";
|
|
|
|
// Redis only
|
|
redisTest("should use redis", async ({ redisOptions }) => {
|
|
/* ... */
|
|
});
|
|
|
|
// PostgreSQL only
|
|
postgresTest("should use postgres", async ({ prisma }) => {
|
|
/* ... */
|
|
});
|
|
|
|
// Both Redis and PostgreSQL
|
|
containerTest("should use both", async ({ prisma, redisOptions }) => {
|
|
/* ... */
|
|
});
|
|
```
|
|
|
|
### Changesets
|
|
|
|
When modifying any public package (`packages/*` or `integrations/*`), add a changeset:
|
|
|
|
```bash
|
|
pnpm run changeset:add
|
|
```
|
|
|
|
- Default to **patch** for bug fixes and minor changes
|
|
- Confirm with maintainers before selecting **minor** (new features)
|
|
- **Never** select major (breaking changes) without explicit approval
|
|
|
|
## Architecture Overview
|
|
|
|
### Apps
|
|
|
|
- **apps/webapp**: Remix 2.1.0 app - main API, dashboard, and Docker image. Uses Express server.
|
|
- **apps/supervisor**: Node.js app handling task execution, interfacing with Docker/Kubernetes.
|
|
|
|
### Public Packages
|
|
|
|
- **packages/trigger-sdk** (`@trigger.dev/sdk`): Main SDK
|
|
- **packages/cli-v3** (`trigger.dev`): CLI package
|
|
- **packages/core** (`@trigger.dev/core`): Shared code between SDK and webapp. Import subpaths only (never root).
|
|
- **packages/build**: Build extensions and types
|
|
- **packages/react-hooks**: React hooks for realtime and triggering
|
|
- **packages/redis-worker** (`@trigger.dev/redis-worker`): Custom Redis-based background job system
|
|
|
|
### Internal Packages
|
|
|
|
- **internal-packages/database** (`@trigger.dev/database`): Prisma 6.14.0 client and schema
|
|
- **internal-packages/clickhouse** (`@internal/clickhouse`): ClickHouse client and schema migrations
|
|
- **internal-packages/run-engine** (`@internal/run-engine`): "Run Engine 2.0" - run lifecycle management
|
|
- **internal-packages/redis** (`@internal/redis`): Redis client creation utilities
|
|
- **internal-packages/testcontainers** (`@internal/testcontainers`): Test helpers for Redis/PostgreSQL containers
|
|
- **internal-packages/zodworker** (`@internal/zodworker`): Graphile-worker wrapper (being replaced by redis-worker)
|
|
|
|
### Reference Projects
|
|
|
|
The `references/` directory contains test workspaces for developing and testing new SDK and platform features. Use these projects (e.g., `references/hello-world`) to manually test changes to the CLI, SDK, core packages, and webapp before submitting PRs.
|
|
|
|
## Webapp Development
|
|
|
|
### Key Locations
|
|
|
|
- Trigger API: `apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts`
|
|
- Batch trigger: `apps/webapp/app/routes/api.v1.tasks.batch.ts`
|
|
- Prisma setup: `apps/webapp/app/db.server.ts`
|
|
- Run engine config: `apps/webapp/app/v3/runEngine.server.ts`
|
|
- Services: `apps/webapp/app/v3/services/**/*.server.ts`
|
|
- Presenters: `apps/webapp/app/v3/presenters/**/*.server.ts`
|
|
- OTEL endpoints: `apps/webapp/app/routes/otel.v1.logs.ts`, `otel.v1.traces.ts`
|
|
|
|
### Environment Variables
|
|
|
|
Access via `env` export from `apps/webapp/app/env.server.ts`, never `process.env` directly.
|
|
|
|
For testable code, **never import env.server.ts** in test files. Pass configuration as options instead. Example pattern:
|
|
|
|
- `realtimeClient.server.ts` (testable service)
|
|
- `realtimeClientGlobal.server.ts` (configuration)
|
|
|
|
### Legacy vs Run Engine 2.0
|
|
|
|
The codebase is transitioning from the "legacy run engine" (spread across codebase) to "Run Engine 2.0" (`@internal/run-engine`). Focus on Run Engine 2.0 for new work.
|
|
|
|
## Docker Image Guidelines
|
|
|
|
When updating Docker image references in `docker/Dockerfile` or other container files:
|
|
|
|
- **Always use multiplatform/index digests**, not architecture-specific digests
|
|
- Architecture-specific digests (e.g., for `linux/amd64` only) will cause CI failures on different build environments
|
|
- On Docker Hub, the multiplatform digest is shown on the main image page, while architecture-specific digests are listed under "OS/ARCH"
|
|
- Example: Use `node:20.20-bullseye-slim@sha256:abc123...` where the digest is from the multiplatform index, not from a specific OS/ARCH variant
|
|
|
|
## Database Migrations (PostgreSQL)
|
|
|
|
1. Edit `internal-packages/database/prisma/schema.prisma`
|
|
2. Create migration:
|
|
```bash
|
|
cd internal-packages/database
|
|
pnpm run db:migrate:dev:create --name "add_new_column"
|
|
```
|
|
3. **Important**: Generated migration includes extraneous changes. Remove lines related to:
|
|
- `_BackgroundWorkerToBackgroundWorkerFile`
|
|
- `_BackgroundWorkerToTaskQueue`
|
|
- `_TaskRunToTaskRunTag`
|
|
- `_WaitpointRunConnections`
|
|
- `_completedWaitpoints`
|
|
- `SecretStore_key_idx`
|
|
- Various `TaskRun` indexes unless you added them
|
|
4. Apply migration:
|
|
```bash
|
|
pnpm run db:migrate:deploy && pnpm run generate
|
|
```
|
|
|
|
### Index Migration Rules
|
|
|
|
- Indexes **must use CONCURRENTLY** to avoid table locks
|
|
- **CONCURRENTLY indexes must be in their own separate migration file** - they cannot be combined with other schema changes
|
|
|
|
## ClickHouse Migrations
|
|
|
|
ClickHouse migrations use Goose format and live in `internal-packages/clickhouse/schema/`.
|
|
|
|
1. Create a new numbered SQL file (e.g., `010_add_new_column.sql`)
|
|
2. Use Goose markers:
|
|
|
|
```sql
|
|
-- +goose Up
|
|
ALTER TABLE trigger_dev.your_table
|
|
ADD COLUMN new_column String DEFAULT '';
|
|
|
|
-- +goose Down
|
|
ALTER TABLE trigger_dev.your_table
|
|
DROP COLUMN new_column;
|
|
```
|
|
|
|
Follow naming conventions in `internal-packages/clickhouse/README.md`:
|
|
|
|
- `raw_` prefix for input tables
|
|
- `_v1`, `_v2` suffixes for versioning
|
|
- `_mv_v1` suffix for materialized views
|
|
|
|
## Writing Trigger.dev Tasks
|
|
|
|
Always import from `@trigger.dev/sdk`. Never use `@trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern.
|
|
|
|
```typescript
|
|
import { task } from "@trigger.dev/sdk";
|
|
|
|
// Every task must be exported
|
|
export const myTask = task({
|
|
id: "my-task", // Unique ID
|
|
run: async (payload: { message: string }) => {
|
|
// Task logic - no timeouts
|
|
},
|
|
});
|
|
```
|
|
|
|
### SDK Documentation Rules
|
|
|
|
The `rules/` directory contains versioned documentation for writing Trigger.dev tasks, distributed to users via the SDK installer. Current version is defined in `rules/manifest.json`.
|
|
|
|
- `rules/4.3.0/` - Latest: batch trigger v2 (1,000 items, 3MB payloads), debouncing
|
|
- `rules/4.1.0/` - Realtime streams v2, updated config
|
|
- `rules/4.0.0/` - Base v4 SDK documentation
|
|
|
|
When adding new SDK features, create a new version directory with only the files that changed from the previous version. Update `manifest.json` to point unchanged files to previous versions.
|
|
|
|
### Claude Code Skill
|
|
|
|
The `.claude/skills/trigger-dev-tasks/` skill provides Claude Code with Trigger.dev task expertise. It includes:
|
|
|
|
- `SKILL.md` - Core instructions and patterns
|
|
- Reference files for basic tasks, advanced tasks, scheduled tasks, realtime, and config
|
|
|
|
Keep the skill in sync with the latest rules version when SDK features change.
|
|
|
|
## Testing with hello-world Reference Project
|
|
|
|
First-time setup:
|
|
|
|
1. Run `pnpm run db:seed` to seed the database (creates the hello-world project)
|
|
2. Build CLI: `pnpm run build --filter trigger.dev && pnpm i`
|
|
3. Authorize CLI: `cd references/hello-world && pnpm exec trigger login -a http://localhost:3030`
|
|
|
|
Running:
|
|
|
|
```bash
|
|
cd references/hello-world
|
|
pnpm exec trigger dev # or with --log-level debug
|
|
```
|
|
|
|
## Local Task Testing Workflow
|
|
|
|
This workflow enables Claude Code to run the webapp and trigger dev simultaneously, trigger tasks, and inspect results for testing code changes.
|
|
|
|
### Step 1: Start Webapp in Background
|
|
|
|
```bash
|
|
# Run from repo root with run_in_background: true
|
|
pnpm run dev --filter webapp
|
|
```
|
|
|
|
Verify webapp is running:
|
|
|
|
```bash
|
|
curl -s http://localhost:3030/healthcheck # Should return 200
|
|
```
|
|
|
|
### Step 2: Start Trigger Dev in Background
|
|
|
|
```bash
|
|
# Run from hello-world directory with run_in_background: true
|
|
cd references/hello-world && pnpm exec trigger dev
|
|
```
|
|
|
|
The worker will build and register tasks. Check output for "Local worker ready [node]" message.
|
|
|
|
### Step 3: Trigger and Monitor Tasks via MCP
|
|
|
|
Use the Trigger.dev MCP tools to interact with tasks:
|
|
|
|
```
|
|
# Get current worker and registered tasks
|
|
mcp__trigger__get_current_worker(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev")
|
|
|
|
# Trigger a task
|
|
mcp__trigger__trigger_task(
|
|
projectRef: "proj_rrkpdguyagvsoktglnod",
|
|
environment: "dev",
|
|
taskId: "hello-world",
|
|
payload: {"message": "Hello from Claude"}
|
|
)
|
|
|
|
# List runs to see status
|
|
mcp__trigger__list_runs(
|
|
projectRef: "proj_rrkpdguyagvsoktglnod",
|
|
environment: "dev",
|
|
taskIdentifier: "hello-world",
|
|
limit: 5
|
|
)
|
|
```
|
|
|
|
### Step 4: Monitor Execution
|
|
|
|
- Check trigger dev output file for real-time execution logs
|
|
- Successful runs show: `Task | Run ID | Success (Xms)`
|
|
- Dashboard available at: http://localhost:3030/orgs/references-9dfd/projects/hello-world-97DT/env/dev/runs
|
|
|
|
### Key Project Refs
|
|
|
|
- hello-world: `proj_rrkpdguyagvsoktglnod`
|