# vs Windmill

Source: https://routineos.org/compare/windmill

> A Windmill alternative for judgment work: convert an OpenFlow JSON flow to a Claude routine. Suspend steps become gates. Free (MIT). Needs a paid Claude plan.

Compare / Windmill

# Convert a Windmill flow to a Claude routine. What it cannot carry over is listed, not guessed.

RoutineOS is a Windmill alternative for jobs where a person reads something and decides. Export your flow as OpenFlow JSON, run one command, and you get a routine pack plus a file called MIGRATION.md that lists what a person still has to finish. It is free (MIT) and needs a paid Claude plan.

[Get started](https://routineos.org/#start)[Convert your flow](https://docs.routineos.org/guides/migrate/windmill)[Migrate overview](https://routineos.org/migrate)[All comparisons](https://routineos.org/compare)

Converter builtFree (MIT). Needs a paid Claude plan.Converted routines are unpiloted

What converts

## What the Windmill converter carries over

The converter is deterministic Python. It reads OpenFlow, the JSON format for a Windmill flow, and writes a pack plus a report. It reads paths and names only, never a secret value.

| In the Windmill flow | In RoutineOS |
|---|---|
| A raw script module (TypeScript, Python, Bash and others) | A code stage. Your original source is kept in `lib/source/` and is never run. |
| A script or flow referenced by path | A step marked "needs a person", with the path named. |
| For loops and while loops | The inner steps are listed after it and marked "for each item". |
| Branches | The branches are listed and marked by their summary. |
| AI agent module | A skill stage. The system prompt and user message are used when they are static. |
| AI decision module | A model stage. |
| A suspend step (approval) | An approval gate stage placed after that step and before the next one. |
| Failure module | Failure handling. |
| Flow input schema | Settings: a boolean becomes a toggle, a number a number, an enum a choice, a list of strings a list. The rest is reported. |
| Resources and variables | Listed by path only. You re-create each value yourself. A resource whose name matches a known app also gets an unverified connector. |
| Values from earlier steps and flow input | Explicit inputs, such as "x from step a" or "Setting y". |

**Any step that writes is gated**If a step sends, posts or writes to an app, the converted routine is approval-gated and that step moves after the gate. Do not remove the gate to match the original. A converted routine starts report-only and unpiloted.

Source: [Migrate from Windmill](https://docs.routineos.org/guides/migrate/windmill) and the 0.6.0 changelog (which says only that it reads OpenFlow JSON and refuses YAML; the module mapping is from the docs page). Where the gate sits for a suspend step is unverified: the converter puts it after the step, which is what Windmill's approval page implies but does not state in so many words.

What it refuses or needs from you

## What is refused, and what a person finishes

### Refused or stopped

- **YAML.** A `flow.yaml` file is refused with a message to export the flow as JSON, because the converter has no YAML parser. Whether the Windmill app exports JSON is unverified.
- **An inconsistent input.** A number input whose minimum is above its maximum stops the conversion and names the input.
- **A file it cannot read.** It ends with "this workflow could not be converted", exit code 2 and no output.

### A person finishes

- **The schedule.** A flow file carries no schedule. The default (weekdays at 22:00 UTC) applies and is reported as needing a person. Give the real cron, in UTC, at most hourly.
- **Code.** The skill translates it to a Python 3.11 standard library script, or you replace it with a model step.
- **Resources and variables.** Re-create each one and reconnect apps on claude.ai.
- **Referenced scripts and flows.** Each becomes a "needs a person" step.

The first thing to read is MIGRATION.md. Each item marked needs a person should have an owner before you turn the routine on.

The command

## Convert a Windmill flow with one command

Give it the exported JSON file and a folder that does not exist yet (or is empty). Or paste the flow into Claude Code and ask Claude to use the routineos-migrate skill.

$ python3 skills/routineos/scripts/routineos.py migrate windmill <flow.json> --out <dir>

1. **You get two files**`pack.json` and `MIGRATION.md`, in the folder you named.
2. **Read the exit code**0 means nothing needs a person. 1 means the pack was written and the report lists items for a person. 2 means it failed.
3. **Check, then install**Validate the pack, install it, then run it once report-only before you trust it.

Windmill, as the docs here describe it, is a flow format you export. This page says nothing about Windmill's pricing, limits or hosting, so read Windmill's own pages for those. RoutineOS is not affiliated with Windmill. See also [migrate limits](https://docs.routineos.org/guides/migrate/limits).

When to keep Windmill

## When to keep Windmill

- **Nothing in the job needs a judgment call.** A fixed flow runs fine as a fixed flow.
- **You need it to react in seconds.** A routine runs on a schedule of an hour or more, in UTC.
- **You do not use Claude.** A routine runs on a paid Claude plan.
- **You need a settled platform.** Claude scheduled tasks are a research preview.

You can also keep Windmill for the plumbing and move only the step that reads and decides. If you also run n8n, see the [n8n comparison](https://routineos.org/compare/n8n), or [all comparisons](https://routineos.org/compare) and the [templates](https://routineos.org/templates).

## Convert a flow

Export it as OpenFlow JSON, run the command, and read MIGRATION.md before you turn anything on.

[Get started](https://routineos.org/#start)[Read the Windmill guide](https://docs.routineos.org/guides/migrate/windmill)
