windmill-cli 1.625.0 → 1.628.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/esm/gen/core/OpenAPI.js +1 -1
  2. package/esm/src/commands/app/generate_agents.js +3 -1
  3. package/esm/src/commands/app/new.js +2 -0
  4. package/esm/src/commands/init/init.js +60 -21
  5. package/esm/src/commands/sync/sync.js +19 -236
  6. package/esm/src/guidance/core.js +57 -0
  7. package/esm/src/guidance/skills.js +5742 -0
  8. package/esm/src/main.js +1 -1
  9. package/esm/windmill-utils-internal/src/path-utils/path-assigner.js +2 -0
  10. package/package.json +1 -1
  11. package/types/gen/types.gen.d.ts +1091 -90
  12. package/types/gen/types.gen.d.ts.map +1 -1
  13. package/types/src/commands/app/generate_agents.d.ts.map +1 -1
  14. package/types/src/commands/app/new.d.ts.map +1 -1
  15. package/types/src/commands/init/init.d.ts.map +1 -1
  16. package/types/src/commands/sync/sync.d.ts +3 -2
  17. package/types/src/commands/sync/sync.d.ts.map +1 -1
  18. package/types/src/guidance/core.d.ts +13 -0
  19. package/types/src/guidance/core.d.ts.map +1 -0
  20. package/types/src/guidance/skills.d.ts +15 -0
  21. package/types/src/guidance/skills.d.ts.map +1 -0
  22. package/types/src/main.d.ts +1 -1
  23. package/types/windmill-utils-internal/src/gen/types.gen.d.ts +1091 -90
  24. package/types/windmill-utils-internal/src/gen/types.gen.d.ts.map +1 -1
  25. package/types/windmill-utils-internal/src/path-utils/path-assigner.d.ts.map +1 -1
  26. package/esm/src/guidance/flow_guidance.js +0 -15
  27. package/esm/src/guidance/prompts.js +0 -2620
  28. package/esm/src/guidance/script_guidance.js +0 -13
  29. package/types/src/guidance/flow_guidance.d.ts +0 -2
  30. package/types/src/guidance/flow_guidance.d.ts.map +0 -1
  31. package/types/src/guidance/prompts.d.ts +0 -4
  32. package/types/src/guidance/prompts.d.ts.map +0 -1
  33. package/types/src/guidance/script_guidance.d.ts +0 -2
  34. package/types/src/guidance/script_guidance.d.ts.map +0 -1
@@ -32,7 +32,7 @@ export const OpenAPI = {
32
32
  PASSWORD: undefined,
33
33
  TOKEN: getEnv("WM_TOKEN"),
34
34
  USERNAME: undefined,
35
- VERSION: '1.625.0',
35
+ VERSION: '1.628.0',
36
36
  WITH_CREDENTIALS: true,
37
37
  interceptors: {
38
38
  request: new Interceptors(),
@@ -156,11 +156,13 @@ export async function regenerateAgentDocs(workspaceId, targetDir, silent = false
156
156
  // Generate and write AGENTS.md
157
157
  const agentsContent = generateAgentsDocumentation(localData);
158
158
  await dntShim.Deno.writeTextFile(path.join(targetDir, "AGENTS.md"), agentsContent);
159
+ // Generate and write CLAUDE.md referencing AGENTS.md
160
+ await dntShim.Deno.writeTextFile(path.join(targetDir, "CLAUDE.md"), `Instructions are in @AGENTS.md\n`);
159
161
  // Generate and write DATATABLES.md
160
162
  const datatablesContent = generateDatatablesMarkdown(schemas, localData);
161
163
  await dntShim.Deno.writeTextFile(path.join(targetDir, "DATATABLES.md"), datatablesContent);
162
164
  if (!silent) {
163
- log.info(colors.green(`✓ Generated AGENTS.md and DATATABLES.md`));
165
+ log.info(colors.green(`✓ Generated AGENTS.md, CLAUDE.md, and DATATABLES.md`));
164
166
  // Summary
165
167
  const datatableCount = schemas.length;
166
168
  const tableCount = schemas.reduce((acc, dt) => {
@@ -440,6 +440,8 @@ CREATE SCHEMA IF NOT EXISTS ${schemaName};
440
440
  : undefined;
441
441
  const agentsContent = generateAgentsDocumentation(dataForDocs);
442
442
  await dntShim.Deno.writeTextFile(path.join(appDir, "AGENTS.md"), agentsContent);
443
+ // Create CLAUDE.md referencing AGENTS.md
444
+ await dntShim.Deno.writeTextFile(path.join(appDir, "CLAUDE.md"), `Instructions are in @AGENTS.md\n`);
443
445
  // Create DATATABLES.md with the configured data
444
446
  const datatablesContent = generateDatatablesDocumentation(dataForDocs);
445
447
  await dntShim.Deno.writeTextFile(path.join(appDir, "DATATABLES.md"), datatablesContent);
@@ -1,11 +1,22 @@
1
1
  import * as dntShim from "../../../_dnt.shims.js";
2
2
  import { colors, Command, log, yamlStringify, Confirm } from "../../../deps.js";
3
3
  import { readLockfile } from "../../utils/metadata.js";
4
- import { SCRIPT_GUIDANCE } from "../../guidance/script_guidance.js";
5
- import { FLOW_GUIDANCE } from "../../guidance/flow_guidance.js";
6
4
  import { getActiveWorkspaceOrFallback } from "../workspace/workspace.js";
7
5
  import { generateRTNamespace } from "../resource-type/resource-type.js";
8
- import { CLI_COMMANDS } from "../../guidance/prompts.js";
6
+ import { SKILLS, SKILL_CONTENT, SCHEMAS, SCHEMA_MAPPINGS } from "../../guidance/skills.js";
7
+ import { generateAgentsMdContent } from "../../guidance/core.js";
8
+ /**
9
+ * Format a YAML schema for inclusion in skill markdown files.
10
+ */
11
+ function formatSchemaForMarkdown(schemaYaml, schemaName, filePattern) {
12
+ return `## ${schemaName} (\`${filePattern}\`)
13
+
14
+ Must be a YAML file that adheres to the following schema:
15
+
16
+ \`\`\`yaml
17
+ ${schemaYaml.trim()}
18
+ \`\`\``;
19
+ }
9
20
  /**
10
21
  * Bootstrap a windmill project with a wmill.yaml file
11
22
  */
@@ -166,32 +177,60 @@ async function initAction(opts) {
166
177
  }
167
178
  }
168
179
  }
169
- // Create .cursor/rules directory and files with SCRIPT_GUIDANCE content
180
+ // Create guidance files (AGENTS.md, CLAUDE.md, and Claude skills)
170
181
  try {
171
- const scriptGuidanceContent = SCRIPT_GUIDANCE;
172
- const flowGuidanceContent = FLOW_GUIDANCE;
173
- const cliCommandsContent = CLI_COMMANDS;
174
- // Create AGENTS.md file
182
+ // Generate skills reference section for AGENTS.md
183
+ const skills_base_dir = ".claude/skills";
184
+ const skillsReference = SKILLS.map((s) => `- \`${skills_base_dir}/${s.name}/SKILL.md\` - ${s.description}`).join("\n");
185
+ // Create AGENTS.md file with minimal instructions
175
186
  if (!(await dntShim.Deno.stat("AGENTS.md").catch(() => null))) {
176
- await dntShim.Deno.writeTextFile("AGENTS.md", `
177
- You are a helpful assistant that can help with Windmill scripts and flows creation.
178
-
179
- ## Script Guidance
180
- ${scriptGuidanceContent}
181
-
182
- ## Flow Guidance
183
- ${flowGuidanceContent}
184
-
185
- ## CLI Commands
186
- ${cliCommandsContent}
187
- `);
187
+ await dntShim.Deno.writeTextFile("AGENTS.md", generateAgentsMdContent(skillsReference));
188
188
  log.info(colors.green("Created AGENTS.md"));
189
189
  }
190
190
  // Create CLAUDE.md file, referencing AGENTS.md
191
191
  if (!(await dntShim.Deno.stat("CLAUDE.md").catch(() => null))) {
192
- await dntShim.Deno.writeTextFile("CLAUDE.md", "Instructions are in @AGENTS.md");
192
+ await dntShim.Deno.writeTextFile("CLAUDE.md", `Instructions are in @AGENTS.md
193
+ `);
193
194
  log.info(colors.green("Created CLAUDE.md"));
194
195
  }
196
+ // Create .claude/skills/ directory and skill files
197
+ try {
198
+ await dntShim.Deno.mkdir(".claude/skills", { recursive: true });
199
+ await Promise.all(SKILLS.map(async (skill) => {
200
+ const skillDir = `.claude/skills/${skill.name}`;
201
+ await dntShim.Deno.mkdir(skillDir, { recursive: true });
202
+ let skillContent = SKILL_CONTENT[skill.name];
203
+ if (skillContent) {
204
+ // Check if this skill has schemas that need to be appended
205
+ const schemaMappings = SCHEMA_MAPPINGS[skill.name];
206
+ if (schemaMappings && schemaMappings.length > 0) {
207
+ // Combine base content with schemas
208
+ const schemaDocs = schemaMappings
209
+ .map((mapping) => {
210
+ const schemaYaml = SCHEMAS[mapping.schemaKey];
211
+ if (schemaYaml) {
212
+ return formatSchemaForMarkdown(schemaYaml, mapping.name, mapping.filePattern);
213
+ }
214
+ return null;
215
+ })
216
+ .filter((doc) => doc !== null);
217
+ if (schemaDocs.length > 0) {
218
+ skillContent = skillContent + "\n\n" + schemaDocs.join("\n\n");
219
+ }
220
+ }
221
+ await dntShim.Deno.writeTextFile(`${skillDir}/SKILL.md`, skillContent);
222
+ }
223
+ }));
224
+ log.info(colors.green(`Created .claude/skills/ with ${SKILLS.length} skills`));
225
+ }
226
+ catch (skillError) {
227
+ if (skillError instanceof Error) {
228
+ log.warn(`Could not create skills: ${skillError.message}`);
229
+ }
230
+ else {
231
+ log.warn(`Could not create skills: ${skillError}`);
232
+ }
233
+ }
195
234
  }
196
235
  catch (error) {
197
236
  if (error instanceof Error) {
@@ -202,8 +202,9 @@ export function extractFieldsForRawApps(runnables) {
202
202
  });
203
203
  }
204
204
  /**
205
- * Generates AGENTS.md - the main documentation file for AI agents working with raw apps.
206
- * This includes app structure, backend runnables, datatables usage, and all critical rules.
205
+ * Generates AGENTS.md - app-specific configuration for AI agents working with raw apps.
206
+ * References the raw-app skill for complete documentation and includes instance-specific
207
+ * data configuration (datatable, schema, whitelisted tables).
207
208
  */
208
209
  export function generateAgentsDocumentation(data) {
209
210
  const tables = data?.tables ?? [];
@@ -211,146 +212,13 @@ export function generateAgentsDocumentation(data) {
211
212
  const defaultSchema = data?.schema;
212
213
  return `# AI Agent Instructions
213
214
 
214
- This file contains instructions for AI agents (Claude, GPT, etc.) working with this Windmill raw app.
215
- **Read this file first** before making any changes to the app.
215
+ For complete raw app documentation (app structure, backend runnables, datatables, SQL migrations), use the \`raw-app\` skill.
216
216
 
217
- ## App Structure
218
-
219
- \`\`\`
220
- my_app.raw_app/
221
- ├── AGENTS.md # This file - read first!
222
- ├── DATATABLES.md # Database schemas (run 'wmill app generate-agents' to refresh)
223
- ├── raw_app.yaml # App configuration (summary, path, data settings)
224
- ├── index.tsx # Frontend entry point
225
- ├── App.tsx # Main React/Svelte/Vue component
226
- ├── index.css # Styles
227
- ├── package.json # Frontend dependencies
228
- ├── wmill.ts # Auto-generated - backend type definitions (DO NOT EDIT)
229
- ├── backend/ # Backend runnables (server-side scripts)
230
- │ ├── <id>.<ext> # Code file (e.g., get_user.ts) - auto-detected as inline
231
- │ ├── <id>.yaml # Optional: config for fields, or to reference existing scripts
232
- │ └── <id>.lock # Lock file (run 'wmill app generate-locks' to create)
233
- └── sql_to_apply/ # SQL migrations (dev only, not synced)
234
- └── *.sql # SQL files to apply via dev server
235
- \`\`\`
236
-
237
- ## Backend Runnables
238
-
239
- Backend runnables are server-side scripts that your frontend can call. They live in the \`backend/\` folder.
240
-
241
- ### Creating a Backend Runnable
242
-
243
- The simplest way to create a runnable is to add a code file:
244
-
245
- \`\`\`
246
- backend/<id>.<ext>
247
- \`\`\`
248
-
249
- The runnable ID is the filename without extension. For example, \`get_user.ts\` creates a runnable with ID \`get_user\`.
250
-
251
- **Optional:** Add a \`<id>.yaml\` file for additional configuration (fields, static values, etc.).
252
-
253
- ### Supported Languages and Extensions
254
-
255
- | Language | Extension | Example |
256
- |-------------|----------------|--------------------|
257
- | TypeScript | \`.ts\` | \`myFunc.ts\` |
258
- | TypeScript (Bun) | \`.bun.ts\` | \`myFunc.bun.ts\` |
259
- | TypeScript (Deno) | \`.deno.ts\` | \`myFunc.deno.ts\` |
260
- | Python | \`.py\` | \`myFunc.py\` |
261
- | Go | \`.go\` | \`myFunc.go\` |
262
- | Bash | \`.sh\` | \`myFunc.sh\` |
263
- | PowerShell | \`.ps1\` | \`myFunc.ps1\` |
264
- | PostgreSQL | \`.pg.sql\` | \`myFunc.pg.sql\` |
265
- | MySQL | \`.my.sql\` | \`myFunc.my.sql\` |
266
- | BigQuery | \`.bq.sql\` | \`myFunc.bq.sql\` |
267
- | Snowflake | \`.sf.sql\` | \`myFunc.sf.sql\` |
268
- | MS SQL | \`.ms.sql\` | \`myFunc.ms.sql\` |
269
- | GraphQL | \`.gql\` | \`myFunc.gql\` |
270
- | PHP | \`.php\` | \`myFunc.php\` |
271
- | Rust | \`.rs\` | \`myFunc.rs\` |
272
- | C# | \`.cs\` | \`myFunc.cs\` |
273
- | Java | \`.java\` | \`myFunc.java\` |
274
-
275
- ### Example: Creating a Runnable
276
-
277
- **backend/get_user.ts:**
278
- \`\`\`typescript
279
- import * as wmill from 'windmill-client';
280
-
281
- export async function main(user_id: string) {
282
- const sql = wmill.datatable();
283
- const user = await sql\`SELECT * FROM users WHERE id = \${user_id}\`.fetchOne();
284
- return user;
285
- }
286
- \`\`\`
287
-
288
- That's it! The runnable is automatically detected and ready to use.
289
-
290
- **Generate lock files** for dependency management:
291
- \`\`\`bash
292
- wmill app generate-locks
293
- \`\`\`
294
-
295
- ### Optional: YAML Configuration
296
-
297
- Add a \`<id>.yaml\` file to configure fields, static values, or other settings:
298
-
299
- **backend/get_user.yaml:**
300
- \`\`\`yaml
301
- type: inline
302
- fields:
303
- user_id:
304
- type: static
305
- value: "default_user"
306
- \`\`\`
307
-
308
- ### Referencing Existing Scripts
309
-
310
- To reference an existing Windmill script instead of inline code, use a different type:
311
-
312
- **backend/existing_script.yaml:**
313
- \`\`\`yaml
314
- type: script
315
- path: f/my_folder/existing_script
316
- \`\`\`
317
-
318
- For flows:
319
- \`\`\`yaml
320
- type: flow
321
- path: f/my_folder/my_flow
322
- \`\`\`
323
-
324
- ### Calling Backend Runnables from Frontend
325
-
326
- Import from the auto-generated \`wmill.ts\`:
327
-
328
- \`\`\`typescript
329
- import { backend } from './wmill';
330
-
331
- // Call a backend runnable
332
- const user = await backend.get_user({ user_id: '123' });
333
- \`\`\`
334
-
335
- The \`wmill.ts\` file is auto-generated and provides type-safe access to all backend runnables.
217
+ This file contains **app-specific configuration** for this raw app instance.
336
218
 
337
219
  ---
338
220
 
339
- ## ⚠️ CRITICAL RULES FOR DATA TABLES
340
-
341
- **These rules are mandatory - violating them will cause runtime errors:**
342
-
343
- 1. **ONLY USE WHITELISTED TABLES**: You can ONLY query tables listed in \`raw_app.yaml\` → \`data.tables\`.
344
- Tables not in this list are NOT accessible to the app.
345
-
346
- 2. **ADD TABLES BEFORE USING**: To use a new table, you MUST first add it to \`data.tables\` in \`raw_app.yaml\`.
347
-
348
- 3. **USE CONFIGURED DATATABLE/SCHEMA**: When looking for tables:
349
- - First, check the whitelisted tables below
350
- - If creating new tables, use the default datatable${defaultSchema ? ` and schema` : ''} configured for this app
351
- - See \`DATATABLES.md\` for full schema information
352
-
353
- ### Current Data Configuration
221
+ ## Data Configuration
354
222
 
355
223
  ${defaultDatatable
356
224
  ? `**Default Datatable:** \`${defaultDatatable}\`${defaultSchema ? ` | **Default Schema:** \`${defaultSchema}\`` : ''}`
@@ -362,7 +230,7 @@ ${tables.length > 0
362
230
  ? `These tables are accessible to this app:\n\n${tables.map(t => `- \`${t}\``).join('\n')}`
363
231
  : `**No tables whitelisted.** Add tables to \`data.tables\` in \`raw_app.yaml\`.`}
364
232
 
365
- ### Adding a Table to the Whitelist
233
+ ### Adding a Table
366
234
 
367
235
  Edit \`raw_app.yaml\`:
368
236
 
@@ -375,116 +243,31 @@ ${tables.length > 0 ? tables.map(t => ` - ${t}`).join('\n') : ' # Add tabl
375
243
  \`\`\`
376
244
 
377
245
  **Table reference formats:**
378
- - \`<datatable>\` - All tables in the datatable
379
- - \`<datatable>/<table>\` - Specific table in public schema
246
+ - \`<datatable>/<table>\` - Table in public schema
380
247
  - \`<datatable>/<schema>:<table>\` - Table in specific schema
381
248
 
382
249
  ---
383
250
 
384
- ## Querying Data Tables
251
+ ## Quick Reference
385
252
 
386
- ### TypeScript (Bun/Deno)
253
+ **Backend runnable:** Add \`backend/<name>.ts\` (or .py, etc.), then run \`wmill app generate-locks\`
387
254
 
255
+ **Call from frontend:**
388
256
  \`\`\`typescript
389
- import * as wmill from 'windmill-client';
390
-
391
- export async function main(user_id: string) {
392
- const sql = wmill.datatable(); // Or: wmill.datatable('other_datatable')
393
-
394
- // Parameterized queries (safe from SQL injection)
395
- const user = await sql\`SELECT * FROM users WHERE id = \${user_id}\`.fetchOne();
396
- const users = await sql\`SELECT * FROM users WHERE active = \${true}\`.fetch();
397
-
398
- // Insert/Update
399
- await sql\`INSERT INTO users (name, email) VALUES (\${name}, \${email})\`;
400
- await sql\`UPDATE users SET name = \${newName} WHERE id = \${user_id}\`;
401
-
402
- return user;
403
- }
404
- \`\`\`
405
-
406
- ### Python
407
-
408
- \`\`\`python
409
- import wmill
410
-
411
- def main(user_id: str):
412
- db = wmill.datatable() # Or: wmill.datatable('other_datatable')
413
-
414
- # Use $1, $2, etc. for parameters
415
- user = db.query('SELECT * FROM users WHERE id = $1', user_id).fetch_one()
416
- users = db.query('SELECT * FROM users WHERE active = $1', True).fetch()
417
-
418
- # Insert/Update
419
- db.query('INSERT INTO users (name, email) VALUES ($1, $2)', name, email)
420
- db.query('UPDATE users SET name = $1 WHERE id = $2', new_name, user_id)
421
-
422
- return user
423
- \`\`\`
424
-
425
- ---
426
-
427
- ## SQL Migrations (sql_to_apply/)
428
-
429
- The \`sql_to_apply/\` folder is for creating/modifying database tables during development.
430
-
431
- ### How It Works
432
-
433
- 1. Create \`.sql\` files in \`sql_to_apply/\`
434
- 2. Run \`wmill app dev\` - the dev server watches this folder
435
- 3. When SQL files change, a modal appears in the browser to confirm execution
436
- 4. After creating tables, **add them to \`data.tables\`** in \`raw_app.yaml\`
437
-
438
- ### Example Migration
439
-
440
- **sql_to_apply/001_create_users.sql:**
441
- \`\`\`sql
442
- CREATE TABLE IF NOT EXISTS ${defaultSchema ? defaultSchema + '.' : ''}users (
443
- id SERIAL PRIMARY KEY,
444
- email TEXT NOT NULL UNIQUE,
445
- name TEXT,
446
- created_at TIMESTAMP DEFAULT NOW()
447
- );
257
+ import { backend } from './wmill';
258
+ const result = await backend.<name>({ arg: 'value' });
448
259
  \`\`\`
449
260
 
450
- After applying, add to \`raw_app.yaml\`:
451
- \`\`\`yaml
452
- data:
453
- tables:
454
- - ${defaultDatatable || 'main'}/${defaultSchema ? defaultSchema + ':' : ''}users
261
+ **Query datatable (TypeScript):**
262
+ \`\`\`typescript
263
+ const sql = wmill.datatable();
264
+ const rows = await sql\`SELECT * FROM table WHERE id = \${id}\`.fetch();
455
265
  \`\`\`
456
266
 
457
- ### Important Notes
458
-
459
- - **This folder is NOT synced** - it's local development only
460
- - **Use idempotent SQL**: \`CREATE TABLE IF NOT EXISTS\`, etc.
461
- - **Number your files**: \`001_\`, \`002_\` for ordering
462
- - **Always whitelist tables after creation**
463
-
464
- ---
465
-
466
- ## Commands Reference
467
-
468
- | Command | Description |
469
- |---------|-------------|
470
- | \`wmill app dev\` | Start dev server with live reload |
471
- | \`wmill app generate-agents\` | Refresh AGENTS.md and DATATABLES.md |
472
- | \`wmill app generate-locks\` | Generate lock files for backend runnables |
473
- | \`wmill sync push\` | Deploy app to Windmill |
474
- | \`wmill sync pull\` | Pull latest from Windmill |
475
-
476
- ---
477
-
478
- ## Best Practices
479
-
480
- 1. **Check DATATABLES.md** for existing tables before creating new ones
481
- 2. **Use parameterized queries** - never concatenate user input into SQL
482
- 3. **Keep runnables focused** - one function per file
483
- 4. **Use descriptive IDs** - \`get_user.ts\` not \`a.ts\`
484
- 5. **Always whitelist tables** - add to \`data.tables\` before querying
267
+ **SQL migrations:** Add \`.sql\` files to \`sql_to_apply/\`, run \`wmill app dev\`, then whitelist tables
485
268
 
486
269
  ---
487
- *This file is auto-generated. Run \`wmill app new\` or \`wmill sync pull\` to regenerate.*
270
+ *Run \`wmill app generate-agents\` to refresh. See \`.claude/skills/raw-app\` skill for full documentation.*
488
271
  `;
489
272
  }
490
273
  /**
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Core guidance content for AGENTS.md
3
+ *
4
+ * This module exports the template for the AGENTS.md file that provides
5
+ * AI agent instructions for working with Windmill projects.
6
+ */
7
+ /**
8
+ * Generate the AGENTS.md content with the given skills reference.
9
+ * @param skillsReference - A formatted list of skills to include in the document
10
+ * @returns The complete AGENTS.md content
11
+ */
12
+ export function generateAgentsMdContent(skillsReference) {
13
+ return `# Windmill AI Agent Instructions
14
+
15
+ You are a helpful assistant that can help with Windmill scripts, flows, apps, and resources management.
16
+
17
+ ## Important Notes
18
+ - Every new entity MUST be created using the skills listed below.
19
+ - Every modification of an entity MUST be done using the skills listed below.
20
+ - User MUST be asked where to create the entity. It can be in its user folder, under u/{user_name} folder, or in a new folder, /f/{folder_name}/. folder_name and user_name must be provided by the user.
21
+
22
+ ## Script Writing Guide
23
+
24
+ You MUST use the \`write-script-<language>\` skill to write or modify scripts in the language specified by the user. Use bun by default.
25
+
26
+ ## Flow Writing Guide
27
+
28
+ You MUST use the \`write-flow\` skill to create or modify flows.
29
+
30
+ ## Raw App Development
31
+
32
+ You MUST use the \`raw-app\` skill to create or modify raw apps.
33
+ Whenever a new app needs to be created you MUST ask the user to run \`wmill app new\` in its terminal first.
34
+
35
+ ## Triggers
36
+
37
+ You MUST use the \`triggers\` skill to configure HTTP routes, WebSocket, Kafka, NATS, SQS, MQTT, GCP, or Postgres CDC triggers.
38
+
39
+ ## Schedules
40
+
41
+ You MUST use the \`schedules\` skill to configure cron schedules.
42
+
43
+ ## Resources
44
+
45
+ You MUST use the \`resources\` skill to manage resource types and credentials.
46
+
47
+ ## CLI Reference
48
+
49
+ You MUST use the \`cli-commands\` skill to use the CLI.
50
+
51
+ ## Skills
52
+
53
+ For specific guidance, ALWAYS use the skills listed below.
54
+
55
+ ${skillsReference}
56
+ `;
57
+ }