Files
windmill/cli
Ruben Fiszel 3cda447621 fix(flows): reject corrupt step paths at deploy + atomic cache writes (#9751) (#9813)
* fix(flows): reject corrupt step paths at deploy + atomic cache writes (#9751)

A flow step could execute an unrelated (and in the reported case, destructive)
script at runtime even though every stored definition looked correct. A forensic
dump traced it to two issues:

- Deploy accepted absolute/local step paths. `wmill sync push` from a feature-
  branch checkout under /tmp baked an absolute path
  (`/tmp/.../ops/scripts/clean_device/...`) into a step's `value.path`. Persisted
  verbatim, it mis-resolved to an unrelated script at runtime.
- The on-disk cache write was neither truncating nor atomic. `FsBackedCache::put`
  used `write+create`, so a shorter overwrite left stale trailing bytes and
  concurrent writers could interleave into a torn file — a corrupt cached blob
  that a worker then scheduled from.

Fixes:
- Reject non-workspace flow step paths (must be u/, f/, g/ or hub/) in
  `validate_flow_value` (covers create_flow + update_flow, recursively through
  loops/branches/AI-agent tools) and early in the CLI `pushFlow`.
- Make `FsBackedCache::put` write a unique temp file (truncate + fsync) then
  atomically rename it over the target, cleaning up on error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(flows): validate failure/preprocessor module paths + sub-flow paths in CLI

Address PR review (cubic + claude):
- Backend `validate_flow_value` is the authoritative guard but only walked
  `modules`; extend it to also validate `failure_module` and `preprocessor_module`
  (which can themselves be sub-flows/loops/branches), so an absolute path there
  can't be persisted.
- CLI preflight only collected `type: "script"` paths; now collects sub-flow
  (`type: "flow"`) step paths too (recursively, incl. failure/preprocessor), so the
  comment's claim matches the behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(cli): include AI-agent tool step paths in flow path preflight

Address Codex review: collectStepPaths skipped aiagent tools, so a bad path in
a tool fell through to the API error instead of the local fail-fast. The backend
already validates these (traverse_modules walks AIAgent tools); this aligns the
CLI early-error with it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(flows): make failure/preprocessor path test key explicit

The test used `slot:` as a json! key. json! does interpolate an ident key to its
variable's value (json!({slot:1}) with slot="failure_module" => {"failure_module":1}),
so the test was correct and exercised the validation — but the behavior is subtle,
so build the key explicitly via serde_json::Map to remove ambiguity (review nit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(cache): use a UUID temp name for atomic put (shared-volume safe)

Address Codex (P1): pid+counter temp names collide across container PID
namespaces on a shared cache volume (same pid, PUT_SEQ resets to 0 per process),
so two workers could truncate/clobber the same temp file before rename. Use a
random UUID suffix (matching worker.rs's atomic-write helpers) — globally unique,
so the cross-process temp-file hazard is closed. Also trims the comment to the
AGENTS.md <=4-line limit (Pi nit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:06:27 +02:00
..
2022-11-01 15:53:28 +01:00
2023-02-03 19:49:46 +01:00
2026-02-23 09:09:16 +00:00
2025-12-26 20:32:42 +00:00

Windmill CLI

A simple CLI allowing interactions with windmill from the command line.

You can find more information in Windmill Docs

Installation

Install the wmill CLI tool using npm install -g windmill-cli.

Update to the latest version using wmill upgrade.

Workspaces

To get started run wmill workspace add or use the instructions from the workspace settings.

Running Flows & Scripts

Run a script or flow using wmill flow/script run u/username/path/to/script and pass any inputs using --data + Inputs specified as a JSON string or a file using @ <filename> or stdin using @-.

Curl-style syntax using -d @- for stdin or -d @<filename> is also supported.

Flow Steps and Logs will be streamed during execution automatically.

CLI input example

Pushing Resources, Scripts & More

The CLI can push specifications to a windmill instance. See the examples/ folder for formats.

Switch to a different workspace

wmill workspace switch <workspace_name>

Sync a workspace

Pull

wmill sync pull

Push

wmill sync push

We recommend using the --yaml option to use yaml instead of json as the encoding format. Yaml will be made the default soon.

Pushing individual files

You can push individual resources using wmill <type> push <file_name> \<remote_name\>. This does not require a special folder layout or file name, as this is given at runtime.

Listing

All commands support listing by just not providing a subcommand, ie wmill script will result in a list of scripts. Some allow additional options, learn about this by specifying --help.

User Management

You can add & remove users via wmill user add/remove, and list them using wmill user

Pulling

You can pull the entire workspace using wmill pull

Completion

The CLI comes with completions out of the box via wmill completions <shell>. (Via cliffy)

Bash

To enable bash completions add the following line to your ~/.bashrc:

source <(wmill completions bash)

Fish

To enable fish completions add the following line to your ~/.config/fish/config.fish:

source (wmill completions fish | psub)

Zsh

To enable zsh completions add the following line to your ~/.zshrc:

source <(wmill completions zsh)

Development

AI Guidance Variants

wmill init can now materialize alternate AI guidance bundles without changing the generated defaults in the repo, but this is exposed as internal env-var overrides rather than public CLI flags.

Examples:

WMILL_INIT_AI_SKILLS_SOURCE=/path/to/custom/skills wmill init --use-default
WMILL_INIT_AI_SKILLS_SOURCE=/path/to/custom/skills WMILL_INIT_AI_AGENTS_SOURCE=/path/to/AGENTS.md wmill init --use-default
WMILL_INIT_AI_SKILLS_SOURCE=/path/to/custom/skills WMILL_INIT_AI_CLAUDE_SOURCE=/path/to/CLAUDE.md wmill init --use-default

This is the same guidance-writing path used by the benchmark CLI under ai_evals/, so the benchmark harness and wmill init now generate the same project guidance shape:

  • AGENTS.md
  • CLAUDE.md
  • .agents/skills/*
  • .claude/skills/*

Testing with a local windmill-yaml-validator

To test local changes to the validator before publishing, use npm link:

# In windmill-yaml-validator/
npm run build
npm link

# In cli/
npm link windmill-yaml-validator

Running Tests

Prerequisites:

  • PostgreSQL running locally (default: postgres://postgres:changeme@localhost:5432)
  • Rust toolchain installed

Run tests locally (full features):

bun test test/

Run tests in CI mode (minimal features, skips EE tests):

CI_MINIMAL_FEATURES=true bun test test/
Variable Description
CI_MINIMAL_FEATURES Set to true to skip EE-dependent tests
DATABASE_URL PostgreSQL connection string
EE_LICENSE_KEY Enterprise license key for EE features