This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a pnpm 10.23.0 monorepo using Turborepo. Run commands from root with pnpm run.
# 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/*"We use vitest exclusively. Never mock anything - use testcontainers instead.
# 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-engineTest files go next to source files (e.g., MyService.ts → MyService.test.ts).
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 }) => {
/* ... */
});When modifying any public package (packages/* or integrations/*), add a changeset:
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
- 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.
- 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/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)
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.
- 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
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)
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.
- Edit
internal-packages/database/prisma/schema.prisma - Create migration:
cd internal-packages/database pnpm run db:migrate:dev:create --name "add_new_column"
- Important: Generated migration includes extraneous changes. Remove lines related to:
_BackgroundWorkerToBackgroundWorkerFile_BackgroundWorkerToTaskQueue_TaskRunToTaskRunTag_WaitpointRunConnections_completedWaitpointsSecretStore_key_idx- Various
TaskRunindexes unless you added them
- Apply migration:
pnpm run db:migrate:deploy && pnpm run generate
- 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 use Goose format and live in internal-packages/clickhouse/schema/.
-
Create a new numbered SQL file (e.g.,
010_add_new_column.sql) -
Use Goose markers:
-- +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,_v2suffixes for versioning_mv_v1suffix for materialized views
Always import from @trigger.dev/sdk. Never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern.
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
},
});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), debouncingrules/4.1.0/- Realtime streams v2, updated configrules/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.
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.
First-time setup:
- Run
pnpm run db:seedto seed the database (creates the hello-world project) - Build CLI:
pnpm run build --filter trigger.dev && pnpm i - Authorize CLI:
cd references/hello-world && pnpm exec trigger login -a http://localhost:3030
Running:
cd references/hello-world
pnpm exec trigger dev # or with --log-level debugThis workflow enables Claude Code to run the webapp and trigger dev simultaneously, trigger tasks, and inspect results for testing code changes.
# Run from repo root with run_in_background: true
pnpm run dev --filter webappVerify webapp is running:
curl -s http://localhost:3030/healthcheck # Should return 200# Run from hello-world directory with run_in_background: true
cd references/hello-world && pnpm exec trigger devThe worker will build and register tasks. Check output for "Local worker ready [node]" message.
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
)
- 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
- hello-world:
proj_rrkpdguyagvsoktglnod