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.
- package/esm/gen/core/OpenAPI.js +1 -1
- package/esm/src/commands/app/generate_agents.js +3 -1
- package/esm/src/commands/app/new.js +2 -0
- package/esm/src/commands/init/init.js +60 -21
- package/esm/src/commands/sync/sync.js +19 -236
- package/esm/src/guidance/core.js +57 -0
- package/esm/src/guidance/skills.js +5742 -0
- package/esm/src/main.js +1 -1
- package/esm/windmill-utils-internal/src/path-utils/path-assigner.js +2 -0
- package/package.json +1 -1
- package/types/gen/types.gen.d.ts +1091 -90
- package/types/gen/types.gen.d.ts.map +1 -1
- package/types/src/commands/app/generate_agents.d.ts.map +1 -1
- package/types/src/commands/app/new.d.ts.map +1 -1
- package/types/src/commands/init/init.d.ts.map +1 -1
- package/types/src/commands/sync/sync.d.ts +3 -2
- package/types/src/commands/sync/sync.d.ts.map +1 -1
- package/types/src/guidance/core.d.ts +13 -0
- package/types/src/guidance/core.d.ts.map +1 -0
- package/types/src/guidance/skills.d.ts +15 -0
- package/types/src/guidance/skills.d.ts.map +1 -0
- package/types/src/main.d.ts +1 -1
- package/types/windmill-utils-internal/src/gen/types.gen.d.ts +1091 -90
- package/types/windmill-utils-internal/src/gen/types.gen.d.ts.map +1 -1
- package/types/windmill-utils-internal/src/path-utils/path-assigner.d.ts.map +1 -1
- package/esm/src/guidance/flow_guidance.js +0 -15
- package/esm/src/guidance/prompts.js +0 -2620
- package/esm/src/guidance/script_guidance.js +0 -13
- package/types/src/guidance/flow_guidance.d.ts +0 -2
- package/types/src/guidance/flow_guidance.d.ts.map +0 -1
- package/types/src/guidance/prompts.d.ts +0 -4
- package/types/src/guidance/prompts.d.ts.map +0 -1
- package/types/src/guidance/script_guidance.d.ts +0 -2
- package/types/src/guidance/script_guidance.d.ts.map +0 -1
package/esm/gen/core/OpenAPI.js
CHANGED
|
@@ -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 {
|
|
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 .
|
|
180
|
+
// Create guidance files (AGENTS.md, CLAUDE.md, and Claude skills)
|
|
170
181
|
try {
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
const
|
|
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",
|
|
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 -
|
|
206
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
|
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>\` -
|
|
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
|
-
##
|
|
251
|
+
## Quick Reference
|
|
385
252
|
|
|
386
|
-
|
|
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
|
|
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
|
-
|
|
451
|
-
\`\`\`
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
+
}
|