Skip to content

Commit 18b9028

Browse files
authored
feat(cli): set up AI tooling in trigger init and add getting-started skill (#3872)
## Summary `trigger init` now sets up your AI coding assistant as part of project setup. Instead of the old either/or "MCP or CLI" prompt, it offers the MCP server and agent skills together, then asks whether to scaffold with the CLI or let your assistant do it. A new `getting-started` agent skill backs that hand-off: it teaches the assistant the bootstrap recipe (install the SDK, write `trigger.config.ts`, scaffold a first task, wire tsconfig/gitignore, run `trigger dev`) and is explicit about the two steps that genuinely need a human (`trigger login` and copying the DEV secret key from the dashboard). It ships in the CLI alongside the existing skills, version-matched to your SDK. Prompt-once gating is shared, so opting in or out during `init` means `trigger dev` won't ask about skills again.
1 parent e9c459f commit 18b9028

5 files changed

Lines changed: 438 additions & 18 deletions

File tree

.changeset/cli-init-ai-tooling.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"trigger.dev": patch
3+
---
4+
5+
`trigger init` now sets up your AI coding assistant as part of project setup: pick the MCP server, the agent skills, or both, then scaffold with the CLI or hand off to your assistant. Adds a new `getting-started` agent skill that teaches assistants how to bootstrap Trigger.dev (install the SDK, write `trigger.config.ts`, create a first task, run `trigger dev`), so the AI-driven setup path works end to end. It ships in the CLI alongside the existing skills, version-matched to your SDK.
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
---
2+
name: getting-started
3+
description: >
4+
Bootstrap Trigger.dev into an existing project from scratch: authenticate the
5+
CLI, install @trigger.dev/sdk and @trigger.dev/build, write trigger.config.ts
6+
with the project ref and task dirs, scaffold a /trigger directory with a first
7+
task, wire tsconfig and .gitignore, set TRIGGER_SECRET_KEY, and run the dev
8+
server. Load this when a project has no trigger.config.ts yet and the user
9+
asks to "add Trigger.dev", "set up Trigger.dev", "initialize Trigger.dev", or
10+
get a first task running, including in a monorepo. Once the project is set up
11+
and you are writing task code, switch to the authoring-tasks skill.
12+
type: core
13+
library: trigger.dev
14+
library_version: "{{TRIGGER_SDK_VERSION}}"
15+
sources:
16+
- docs/quick-start.mdx
17+
- docs/manual-setup.mdx
18+
- docs/config/config-file.mdx
19+
- docs/triggering.mdx
20+
---
21+
22+
# Getting started with Trigger.dev
23+
24+
Set up Trigger.dev in an existing project. The end state is: the SDK installed, a
25+
`trigger.config.ts` pointing at a project ref, a `/trigger` directory with at least
26+
one exported task, and `trigger dev` running so the task shows up in the dashboard.
27+
28+
The fastest path is the CLI's own wizard, which performs every mechanical step below
29+
and also offers to install the MCP server and these agent skills:
30+
31+
```bash
32+
npx trigger.dev@latest init
33+
```
34+
35+
Prefer `init` when you can. Do the manual steps further down when `init` does not fit
36+
(monorepos, an existing config to extend, or a non-interactive environment).
37+
38+
## Two steps need the human
39+
40+
Most of setup is automatable, but two steps require a person and cannot be done
41+
headlessly. When you reach them, stop and ask the user to do them, then continue:
42+
43+
1. **Authenticating the CLI.** `npx trigger.dev@latest login` opens a browser for the
44+
user to sign in. If they have no account, point them to https://cloud.trigger.dev
45+
(or a self-hosted instance) first. You cannot complete this for them.
46+
2. **The secret key and project ref.** `TRIGGER_SECRET_KEY` and the project ref
47+
(`proj_...`) come from the dashboard. Ask the user to copy the **DEV** secret key
48+
from the project's API Keys page, and to pick or create the project so you have its
49+
ref. `trigger init` can select the project interactively once the user is logged in.
50+
51+
Treat these as handoffs: state exactly what you need, wait for the user, then resume.
52+
53+
## Manual setup
54+
55+
### 1. Authenticate (human step)
56+
57+
```bash
58+
npx trigger.dev@latest login
59+
# self-hosted:
60+
npx trigger.dev@latest login --api-url https://your-trigger-instance.com
61+
```
62+
63+
### 2. Install the packages
64+
65+
`@trigger.dev/sdk` is a runtime dependency; `@trigger.dev/build` is a dev dependency.
66+
Pin both to the same version as the `trigger.dev` CLI you run; the CLI warns on a
67+
mismatch during `dev`/`deploy`.
68+
69+
```bash
70+
npm add @trigger.dev/sdk@latest
71+
npm add --save-dev @trigger.dev/build@latest
72+
```
73+
74+
### 3. Write `trigger.config.ts`
75+
76+
Create it in the project root (or `trigger.config.mjs` for JavaScript). The `project`
77+
ref and `dirs` are the only required fields.
78+
79+
```ts
80+
import { defineConfig } from "@trigger.dev/sdk";
81+
82+
export default defineConfig({
83+
project: "<project ref>", // e.g. "proj_abc123", from the dashboard
84+
dirs: ["./src/trigger"], // where your tasks live
85+
maxDuration: 3600,
86+
retries: {
87+
enabledInDev: false,
88+
default: { maxAttempts: 3, factor: 2, minTimeoutInMs: 1000, maxTimeoutInMs: 10000, randomize: true },
89+
},
90+
});
91+
```
92+
93+
Use the Bun runtime by adding `runtime: "bun"`. Build extensions (`prismaExtension`,
94+
`puppeteer`, `additionalFiles`, etc.) come from `@trigger.dev/build` and go in
95+
`build.extensions`.
96+
97+
### 4. Add a first task
98+
99+
Create the directory that matches `dirs` and export a task from it. Every task must be
100+
a named export with a project-unique `id`.
101+
102+
```ts
103+
// src/trigger/example.ts
104+
import { task } from "@trigger.dev/sdk";
105+
106+
export const helloWorld = task({
107+
id: "hello-world",
108+
run: async (payload: { name: string }) => {
109+
return { message: `Hello ${payload.name}!` };
110+
},
111+
});
112+
```
113+
114+
### 5. Wire tsconfig and gitignore
115+
116+
Add `trigger.config.ts` to the `include` array in `tsconfig.json`, and add `.trigger`
117+
to `.gitignore` (the CLI writes local dev state there).
118+
119+
```jsonc
120+
// tsconfig.json
121+
{ "include": ["trigger.config.ts" /* ...existing */] }
122+
```
123+
124+
```bash
125+
# .gitignore
126+
.trigger
127+
```
128+
129+
### 6. Set the secret key (human step)
130+
131+
For triggering from your own code, set `TRIGGER_SECRET_KEY` to the DEV key from the
132+
dashboard's API Keys page. Self-hosted users also set `TRIGGER_API_URL`.
133+
134+
```bash
135+
# .env (or .env.local for Next.js)
136+
TRIGGER_SECRET_KEY=tr_dev_xxxxxxxx
137+
```
138+
139+
### 7. Run the dev server
140+
141+
```bash
142+
npx trigger.dev@latest dev
143+
```
144+
145+
Leave it running. Tasks register with the dashboard, where the user can fire a test run
146+
from the task's test page. On first run the CLI offers to install the MCP server and
147+
agent skills; recommend both.
148+
149+
## Triggering from your app
150+
151+
Once a task exists, trigger it from backend code with a **type-only** import so the
152+
task code is never bundled into your app. Trigger by id, not by calling the task object.
153+
154+
```ts
155+
import { tasks } from "@trigger.dev/sdk";
156+
import type { helloWorld } from "@/trigger/example"; // type-only
157+
158+
const handle = await tasks.trigger<typeof helloWorld>("hello-world", { name: "Ada" });
159+
```
160+
161+
`TRIGGER_SECRET_KEY` must be set wherever this runs. Framework specifics live in the
162+
Next.js / Remix / Node.js guides.
163+
164+
## Monorepos
165+
166+
Two layouts, both supported: put tasks in a shared package (`@repo/tasks` with its own
167+
`trigger.config.ts`, consumed via `workspace:*`), or install Trigger.dev directly in the
168+
app that needs it. Run `trigger dev` from the directory that holds `trigger.config.ts`.
169+
See the manual setup docs for full Turborepo examples before scaffolding either.
170+
171+
## Common mistakes
172+
173+
1. **Trying to do the human-only steps headlessly.** You cannot complete `trigger login`
174+
or read the dashboard secret key for the user.
175+
- Wrong: spawning `trigger login` and waiting on it to finish in an agent session.
176+
- Correct: ask the user to log in and to paste the DEV key, then continue.
177+
178+
2. **Mismatched CLI and SDK versions.** A `trigger.dev` CLI on a different major than
179+
`@trigger.dev/sdk` breaks dev/deploy.
180+
- Wrong: `npx trigger.dev@latest dev` against an old pinned SDK.
181+
- Correct: keep `trigger.dev`, `@trigger.dev/sdk`, and `@trigger.dev/build` on the same version.
182+
183+
3. **Importing from `@trigger.dev/sdk/v3` or using `client.defineJob()`.** Both are old.
184+
- Correct: always import from `@trigger.dev/sdk`; define work with `task()`.
185+
186+
4. **Tasks not exported, or outside `dirs`.** A task that is not a named export inside a
187+
configured directory will not be picked up.
188+
- Correct: `export const ... = task({ ... })` in a file under a `dirs` path.
189+
190+
5. **Importing the task instance into backend code.** This bundles the task.
191+
- Wrong: `import { helloWorld } from "@/trigger/example"` in a route handler.
192+
- Correct: `import type { helloWorld }` plus `tasks.trigger<typeof helloWorld>("hello-world", payload)`.
193+
194+
6. **Forgetting `TRIGGER_SECRET_KEY`.** Triggering from your app fails without it; the
195+
`dev` server itself works once the CLI is logged in.
196+
197+
## References
198+
199+
Sibling skills:
200+
201+
- **authoring-tasks** for writing the tasks themselves once setup is done: retries, waits,
202+
queues, scheduled tasks, triggering, and the full `trigger.config.ts`.
203+
- **realtime-and-frontend** for showing live run status in a frontend.
204+
- **authoring-chat-agent** and **chat-agent-advanced** for building AI chat agents.
205+
206+
Docs:
207+
208+
- [Quick start](https://trigger.dev/docs/quick-start)
209+
- [Manual setup](https://trigger.dev/docs/manual-setup)
210+
- [Configuration file](https://trigger.dev/docs/config/config-file)
211+
212+
## Version
213+
214+
Generated for @trigger.dev/sdk {{TRIGGER_SDK_VERSION}}. Re-run the trigger.dev skills installer after upgrading.

packages/cli-v3/src/commands/init.ts

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { intro, isCancel, log, outro, select, text } from "@clack/prompts";
1+
import { intro, isCancel, log, multiselect, outro, select, text } from "@clack/prompts";
22
import { context, trace } from "@opentelemetry/api";
33
import {
44
GetProjectResponseBody,
@@ -43,6 +43,7 @@ import {
4343
writeConfigHasSeenMCPInstallPrompt,
4444
} from "../utilities/configFiles.js";
4545
import { installMcpServer } from "./install-mcp.js";
46+
import { installSkillsFromInit, markSkillsPromptSeen } from "./skills.js";
4647

4748
const cliVersion = VERSION as string;
4849
const cliTag = cliVersion.includes("v4-beta") ? "v4-beta" : "latest";
@@ -147,27 +148,53 @@ async function _initCommand(dir: string, options: InitCommandOptions) {
147148

148149
const hasSeenMCPInstallPrompt = readConfigHasSeenMCPInstallPrompt();
149150

150-
// Skip the MCP-vs-CLI prompt when --yes is set: the user explicitly chose CLI
151-
// by running `trigger.dev init` non-interactively, and the prompt would
151+
// Skip the AI-tooling prompt when --yes is set: the user explicitly chose the CLI
152+
// scaffold by running `trigger.dev init` non-interactively, and the prompt would
152153
// otherwise hang on a fresh machine where `hasSeenMCPInstallPrompt` is false.
153154
if (!hasSeenMCPInstallPrompt && !options.yes) {
154-
const installChoice = await select({
155-
message: "Choose how you want to initialize your project:",
155+
const tooling = await multiselect({
156+
message: "Set up AI tooling for your coding assistant? (optional, space to toggle)",
156157
options: [
157158
{
158159
value: "mcp",
159-
label: "Trigger.dev MCP",
160-
hint: "Automatically install the Trigger.dev MCP server and then vibe your way to a new project.",
160+
label: "MCP server",
161+
hint: "live access to your project: trigger tasks, deploy, monitor runs",
162+
},
163+
{
164+
value: "skills",
165+
label: "Agent skills",
166+
hint: "teach your AI to write Trigger.dev code, version-matched to your SDK",
161167
},
162-
{ value: "cli", label: "CLI", hint: "Continue with the CLI" },
163168
],
169+
required: false,
164170
});
165171

166172
writeConfigHasSeenMCPInstallPrompt(true);
167173

168-
const continueWithCLI = isCancel(installChoice) || installChoice === "cli";
174+
const selectedTooling = isCancel(tooling) ? [] : tooling;
175+
176+
// Track what actually installed (not just what was selected), so the AI hand-off is
177+
// only offered, and only described, in terms of tooling that really landed.
178+
let installedSkills = false;
179+
let installedMcp = false;
180+
181+
// Skills are auth-free and bundled in the CLI. The user opted in here, so install
182+
// straight away (no extra confirm). If they declined, still mark the prompt seen so
183+
// `trigger dev` doesn't ask about skills a second time.
184+
if (selectedTooling.includes("skills")) {
185+
log.step("Installing the Trigger.dev agent skills");
186+
const [skillsError, installed] = await tryCatch(installSkillsFromInit());
187+
if (skillsError) {
188+
log.warn(`Skipped agent skills: ${skillsError.message}`);
189+
} else {
190+
installedSkills = installed === true;
191+
}
192+
} else {
193+
await tryCatch(markSkillsPromptSeen());
194+
}
169195

170-
if (!continueWithCLI) {
196+
// The MCP server is also auth-free.
197+
if (selectedTooling.includes("mcp")) {
171198
log.step("Welcome to the Trigger.dev MCP server install wizard 🧙");
172199

173200
const [installError] = await tryCatch(
@@ -179,11 +206,44 @@ async function _initCommand(dir: string, options: InitCommandOptions) {
179206
);
180207

181208
if (installError) {
182-
outro(`Failed to install MCP server: ${installError.message}`);
183-
return;
209+
// Don't abort init if MCP fails: skills may already be installed and the user
210+
// still needs the project scaffolded. Warn and carry on.
211+
log.warn(`Skipped MCP server: ${installError.message}`);
212+
} else {
213+
installedMcp = true;
184214
}
215+
}
216+
217+
// Vibe path: once AI tooling is actually installed, the user can hand scaffolding to
218+
// their assistant instead of the CLI. Only offered when something landed, and the
219+
// hand-off message names only the tooling that did.
220+
if (installedSkills || installedMcp) {
221+
const setupChoice = await select({
222+
message: "How do you want to set up your project?",
223+
options: [
224+
{
225+
value: "cli",
226+
label: "Scaffold it now with the CLI",
227+
hint: "log in, create trigger.config.ts and an example task",
228+
},
229+
{
230+
value: "ai",
231+
label: "Let my AI assistant set it up",
232+
hint: "hand off and let your assistant bootstrap the project",
233+
},
234+
],
235+
});
185236

186-
return;
237+
if (!isCancel(setupChoice) && setupChoice === "ai") {
238+
outro(
239+
installedSkills && installedMcp
240+
? "Your AI tooling is ready. Ask your assistant to set up Trigger.dev; it can use the getting-started skill and the MCP server to add the SDK, config, and your first task."
241+
: installedSkills
242+
? "Your AI tooling is ready. Ask your assistant to set up Trigger.dev and it will use the getting-started skill to add the SDK, config, and your first task."
243+
: "The MCP server is installed. Ask your assistant to set up Trigger.dev using the MCP server."
244+
);
245+
return;
246+
}
187247
}
188248
}
189249

@@ -288,7 +348,7 @@ async function _initCommand(dir: string, options: InitCommandOptions) {
288348
log.info("Next steps:");
289349
log.info(
290350
` 1. To start developing, run ${chalk.green(
291-
`npx trigger.dev@${cliTag} dev${options.profile ? "" : ` --profile ${options.profile}`}`
351+
`npx trigger.dev@${cliTag} dev${options.profile ? ` --profile ${options.profile}` : ""}`
292352
)} in your project directory`
293353
);
294354
log.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);

0 commit comments

Comments
 (0)