write-flow
Automatically scaffolds Windmill flows using CLI best practices and correct configuration templates.
Install
mkdir -p .claude/skills/write-flow && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/3755" && unzip -o skill.zip -d .claude/skills/write-flow && rm skill.zipInstalls to .claude/skills/write-flow
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
MUST use when creating flows.Key capabilities
- →Scaffold new Windmill flow directory structure
- →Generate initial flow.yaml configuration
- →Run local flow previews without deployment
- →Regenerate local lock and hash files
- →Execute single-step flow previews for iteration
How it works
The skill uses the CLI to create a standardized directory structure and configuration file, ensuring correct suffix resolution and metadata generation.
Inputs & outputs
When to use write-flow
- →Scaffold a new Windmill flow
- →Initialize a workflow directory
- →Configure flow modules and schema
About this skill
Windmill Flow CLI Guide
Creating a Flow
You — the AI agent — scaffold the flow yourself by running wmill flow new <path> with the right flags. Do NOT hand-create the folder + flow.yaml, and do NOT tell the user to "run wmill flow new and follow the prompts".
wmill flow new creates the folder with the correct suffix (__flow or .flow depending on the workspace's nonDottedPaths setting), writes a minimal flow.yaml shell, and prints Claude-specific next-step hints. Scaffolding by hand skips all of that and often picks the wrong suffix.
Step 1 — Gather path + summary by asking the user
You need two things:
- path — the windmill path, e.g.
f/folder/my_floworu/username/my_flow. - summary — a short description of the flow.
If the user's request didn't supply both, ask for both in a single round-trip. Use whichever interactive question facility your runtime provides — a structured multi-choice tool if available, otherwise plain chat — and provide one or two example values for each (with an "Other" / free-form fallback). Do not guess paths or summaries.
Step 2 — Run the command yourself
wmill flow new f/folder/my_flow --summary "Short description"
Add --description "..." when the user provided a longer explanation worth preserving separately from the summary.
Step 3 — Fill in flow.yaml
Open the generated flow.yaml (under the folder the command just created) and replace the empty value.modules + schema with the real flow definition.
For rawscript modules, use !inline path/to/script.ts for the content key. Inline script files should NOT include .inline_script. in their names (e.g. use a.ts, not a.inline_script.ts).
Once the flow has real content, offer to open the visual preview as a one-sentence next step (e.g. "Want me to open the visual preview?"). Don't auto-open — opening the dev page has side effects (browser window, possibly a launch.json entry) and the user should consent.
Anti-patterns to avoid
- ❌ Hand-creating the
__flowfolder +flow.yamlinstead of runningwmill flow new. You'll miss the suffix-setting resolution, the default shape, and the Claude hints. - ❌ Telling the user to "run
wmill flow new <path>" — you can and should run it yourself. - ❌ Inventing a path/summary instead of asking the user.
CLI Commands — running, previewing, deploying
After writing, act on the user's intent instead of just listing commands. Run wmill flow preview yourself when it fits (see "After writing — offer to run, don't wait passively" below). wmill generate-metadata regenerates local lock/hash files (not a deploy) but re-resolves deps — offer it and run on agreement, unless the project's AGENTS.md opts into running metadata automatically. Only name wmill sync push (the deploy) so the user can approve it. The options:
wmill flow preview <flow_path>— default when iterating on a local flow. Runs the localflow.yamlagainst local inline scripts without deploying. Add--remoteto use deployed workspace scripts for PathScript steps instead of local files. Add--step <step_id>to run only one module in isolation (see "Single-step vs whole-flow preview" below).wmill flow run <path>— runs the flow already deployed in the workspace. Use only when the user explicitly wants to test the deployed version, not local edits.wmill generate-metadata— regenerate stale local.lockfiles for the flow and its inline scripts and refresh their content hashes inwmill-lock.yaml. Writes local files only (not a deploy). Run it after editing inline scripts whose imports or arguments changed, sowmill-lock.yamldoesn't drift and add noise to git-sync/CI. By default it scans scripts, flows, and apps across the workspace but only regenerates stale ones; pass the flow's folder as an argument (or run from that subdirectory) to limit the scope to the flow you edited. Note a flow (or script) that imports a changed shared script is pulled in too — runwmill generate-metadata --dry-runto see exactly what is stale and why (content changedvsdepends on <path>) before applying.- Deploy local changes to the workspace — via
git pushorwmill sync pushdepending on how the repo is wired (see the Deploying section inAGENTS.wmill.md). Only suggest/run a deploy when the user explicitly asks to deploy/publish/push — not when they say "run", "try", or "test".
Preview vs run — choose by intent, not habit
If the user says "run the flow", "try it", "test it", "does it work" while there are local edits to a flow.yaml, use flow preview. Do NOT push the flow to then flow run it — pushing is a deploy, and deploying just to test overwrites the workspace version with untested changes.
Only use flow run when:
- The user explicitly says "run the deployed version" / "run what's on the server".
- There is no local
flow.yamlbeing edited (you're just invoking an existing flow).
Only use sync push when:
- The user explicitly asks to deploy, publish, push, or ship.
- The preview has already validated the change and the user wants it in the workspace.
Single-step vs whole-flow preview
Use flow preview <flow_path> --step <step_id> when the user is iterating on one module and the flow's upstream steps aren't part of what they're trying to validate. It runs only that step's runnable (rawscript: the inline script; script: the PathScript, locally if available; flow: the subflow by path) and is much faster than running the whole flow when previous steps are slow or expensive. The step id is resolved by walking nested branchone/branchall/forloopflow/whileloopflow modules and includes the special preprocessor and failure modules.
Use flow preview <flow_path> (no --step) when steps depend on each other's outputs, when the user is validating the overall control flow, or when --step doesn't apply (branchone, branchall, forloopflow, whileloopflow, identity, and AI agent steps cannot themselves be tested in isolation — for branchone/branchall/forloopflow/whileloopflow, the contained steps can, by passing the inner step's id).
After writing — offer to run, don't wait passively
This is about programmatic execution (wmill flow preview -d '<args>'), which actually runs the flow and has side effects. Visual preview (the preview skill) is offered separately — see "Visual preview" below.
If the user hasn't already told you to run/test the flow, offer it as a one-sentence next step (e.g. "Want me to run wmill flow preview with sample args?"). Do not present a multi-option menu.
If the user already asked to test/run/try the flow in their original request, skip the offer and just execute wmill flow preview <path> -d '<args>' directly — pick plausible args from the flow's input schema.
wmill flow preview is safe to run yourself (it does not deploy). wmill generate-metadata does not deploy either (it only writes local lock/hash files) but re-resolves deps — offer it and run on agreement, unless the project's AGENTS.md opts into automatic metadata. After running it, check the regenerated .lock diff and tell the user which inline-script dependency versions changed, so they can catch an unwanted bump before deploying. Only wmill sync push deploys; run it only when the user explicitly asks.
Visual preview
To open the flow visually in the dev page (graph + live reload), use the preview skill. Always offer it as a one-sentence next step (e.g. "Want me to open the visual preview?") rather than opening it automatically — opening the dev page has side effects (browser window, possibly a launch.json entry under MCP-preview branches) the user should consent to. If the user already asked to see/preview/visualize the flow in their original request, skip the offer and just invoke the skill.
Windmill Flow Building Guide
OpenFlow Schema
The OpenFlow schema (openflow.openapi.yaml) is the source of truth for flow structure. Refer to OPENFLOW_SCHEMA for the complete type definitions.
Reserved Module IDs
failure- Reserved for failure handler modulepreprocessor- Reserved for preprocessor moduleInput- Reserved for flow input reference
Hard Structural Rules
These are strict Windmill schema rules. Follow them exactly.
value.modulesis only for normal sequential stepsvalue.preprocessor_moduleandvalue.failure_moduleare special top-level fields insidevalue, not entries invalue.modules- If a flow needs a preprocessor, create
value.preprocessor_modulewithid: preprocessor - If a flow needs a failure handler, create
value.failure_modulewithid: failure - Do NOT create regular modules inside
value.modulesnamedpreprocessororfailure preprocessor_moduleandfailure_moduleonly supportscriptorrawscriptpreprocessor_moduleruns before normal modules and cannot referenceresults.*failure_modulecan use theerrorobject witherror.message,error.step_id,error.name, anderror.stack
Correct shape:
value:
preprocessor_module:
id: preprocessor
value:
type: rawscript
...
failure_module:
id: failure
value:
type: rawscript
...
modules:
- id: process_event
value:
type: rawscript
...
Incorrect shape:
value:
modules:
- id: preprocessor
...
- id: process_event
...
- id: failure
...
Module ID Rules
- Must be unique across the entire flow
- Use underscores, not spaces (e.g.,
fetch_datanotfetch data) - Use descriptive names that reflect the step's purpose
Common Mistakes to Avoid
- Missing
input_transforms- Rawscript parameters won't receive values without them - Referencing future steps -
results.step_idonly works for steps that execute before the current one - Duplicate module IDs - Each module ID must be unique in the flow
Content truncated.
When not to use it
- →Manually creating flow folders or configuration files
- →Deploying flows without explicit user request
Prerequisites
Limitations
- →Requires explicit user consent for deployment
- →Does not auto-open visual previews
How it compares
It automates the scaffolding process to prevent naming errors and missing metadata that occur with manual creation.
Compared to similar skills
write-flow side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| write-flow (this skill) | 1 | 2mo | Review | Beginner |
| bazel-build-optimization | 14 | 2mo | No flags | Advanced |
| github-workflow-automation | 11 | 2mo | Review | Advanced |
| wolf-scripts-core | 5 | 9mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by windmill-labs
View all by windmill-labs →You might also like
bazel-build-optimization
wshobson
Optimize Bazel builds for large-scale monorepos. Use when configuring Bazel, implementing remote execution, or optimizing build performance for enterprise codebases.
github-workflow-automation
ruvnet
Advanced GitHub Actions workflow automation with AI swarm coordination, intelligent CI/CD pipelines, and comprehensive repository management
wolf-scripts-core
Nice-Wolf-Studio
Core automation scripts for archetype selection, evidence validation, quality scoring, and safe bash execution
github-actions-templates
wshobson
Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, automating development workflows, or creating reusable workflow templates.
bash-defensive-patterns
wshobson
Master defensive Bash programming techniques for production-grade scripts. Use when writing robust shell scripts, CI/CD pipelines, or system utilities requiring fault tolerance and safety.
hooks-automation
ruvnet
Automated coordination, formatting, and learning from Claude Code operations using intelligent hooks with MCP integration. Includes pre$post task hooks, session management, Git integration, memory coordination, and neural pattern training for enhanced development workflows.