The Problem

Teams that need a self‑hosted platform for turning arbitrary scripts into APIs, scheduled jobs, UI‑driven apps, and orchestrated workflows currently stitch together several tools (Docker, Airflow, Retool, custom CI). That piecemeal approach creates duplicated effort, fragile integrations, and unpredictable performance, especially when scaling to hundreds of scripts written in different languages.

What This Does

windmill is a portfolio of 19 tightly‑coupled projects that together deliver a single developer experience:

  • backend/ – Rust services (Cargo) that store scripts, execute them in containers, and expose a REST/WS API. Core logic lives in backend/src/lib.rs and the HTTP layer in backend/src/server.rs.
  • frontend/ – Svelte/React UI that auto‑generates forms from script signatures, shows flow diagrams, and provides a low‑code editor (frontend/src/lib/components/apps/editor).
  • cli/ – TypeScript command‑line tools (cli/src/commands/*) for syncing git repos, managing workspaces, and serving local dev back‑ends.
  • typescript-client/ – generated SDK used by the UI and external callers.
  • ai_evals/ – test harnesses that run scripts through the platform, exercising the same paths as production workloads.

The platform supports Python, TypeScript, Go, Bash, SQL, GraphQL, PowerShell, Rust, etc., and can expose any script as a webhook, a UI page, or a node in a workflow graph. Performance claims (13× faster than Airflow) are backed by the Rust executor and in‑process flow engine.

How It Is Wired

Execution starts at the concrete entry points identified by static analysis:

  • ai_evals/cli/index.tsmain (line 35) bootstraps the evaluation harness, reaching 283 internal functions. It immediately calls git_clonegit_clone_at_commit, which creates a temporary directory via fs_async.mkdir (filesystem side‑effect).
  • ai_evals/modes/app.tsrun (line 25) builds a local pipeline graph (buildLocalPipelineGraph), walks script files (collectScriptswalk), and reads each script with fs.readFileSync. This path accounts for most script‑parsing work.
  • cli/src/commands/datatable/serve.tsserve (line 138) launches a dev server; the first internal call is startServe, which generates a random session token via crypto.randomBytes(12).toString (cryptographic side‑effect).
  • cli/test/cargo_backend.tsstart (line 135) drives a websocket test client; the chain ends with this.ws.send (outbound network).

Across the repo, writeFile (called from 76 places) and fetch (67 places) are the most fan‑out functions, making them change‑impact hotspots. Authentication (requireLogin, 57 callers) and workspace resolution (resolveWorkspace, 56 callers) also sit at the core of request handling.

File‑level responsibility highlights:

FileCore dutiesReach
ai_evals/core/appDiagnostics.tsaggregates backend/frontend diagnostics; defines collectBackendDiagnostics etc.38 functions, referenced by 59 files
cli/src/commands/sync/sync.tsworkspace sync logic; merges server state, resolves names99 functions, 13 callers
cli/src/utils/utils.tsgeneric helpers (deepEqual, generateHash)24 functions, 37 callers
frontend/src/lib/components/apps/editor/component/components.tsUI component model, dimension calculations2 functions, 98 types

The internal call graph contains 5 226 resolved edges; the most connected nodes (writeFile, fetch, requireLogin) are natural places to add instrumentation or refactor for modularity. No external library calls are captured in the graph, so side‑effects beyond the repository are limited to the four traced paths above.

How To Use It

# Clone the repo (preserve the exact URL)
git clone https://github.com/moses-y/windmill
cd windmill

# Build the backend (Rust) and UI (npm)
docker compose -f .devcontainer/docker-compose.yml up --build   # pulls Rust, Node, and Python images
# Alternatively, start only the backend:
docker build -t windmill-backend -f Dockerfile .
docker run -p 8000:8000 windmill-backend

# CLI – install node deps and run a command
cd cli
npm ci
npm run build            # compiles TypeScript
node dist/commands/script/script.js list   # example: list registered scripts

Configuration – The platform expects an .env file at the repo root (currently committed) with keys such as DATABASE_URL, REDIS_URL, and WINDMILL_SECRET. Replace it with a local copy (cp .env.example .env) and rotate any real secrets after removal (see health issues).

Running a workflow – After the backend is up, use the generated TypeScript client (typescript-client/src/index.ts) or the CLI:

# Create a simple Python script via the API
curl -X POST http://localhost:8000/api/scripts \
  -H "Authorization: Bearer $WINDMILL_SECRET" \
  -d '{"path":"hello.py","content":"print(\"hi\")","runtime":"python"}'

The UI (http://localhost:3000) will immediately expose a form to trigger hello.py.

Real‑World Use

A SaaS company can host a private Windmill instance, sync its GitHub repo of data‑pipeline scripts, and expose each script as an on‑demand API endpoint. A monitoring service calls the generated webhook (/api/run/hello.py) to trigger nightly data loads, while the internal UI lets analysts run ad‑hoc queries without writing glue code.

Code Health & Issues

  • Criticalwrite-all permission in .github/workflows/build-publish-rh-image.yml. Limit to contents: read and enumerate needed scopes.
  • High – Unpinned third‑party actions (actions-rust-lang/setup-rust-toolchain@v1, etc.). Replace with commit SHA.
  • High – Committed .env (root and frontend/.env). Remove, add to .gitignore, rotate credentials, and provide a template.
  • Medium – No explicit permissions for GITHUB_TOKEN in ai-agent-tests.yml. Add contents: read.
  • Medium – Base images in .devcontainer/Dockerfile are unpinned; use digests.
  • Medium – No dependency‑vulnerability scan in CI; add dependency-review-action or osv-scanner.
  • Medium – Large binaries (main.mp4, windmill_parser_wasm_bg.wasm) exceed 5 MiB; move to Git LFS or external storage.
  • Medium – Checkout step retains token; set persist-credentials: false.
  • Low – Jobs lack timeout-minutes; add sensible limits.
  • Low – Repository lacks standard convention files (.editorconfig, formatter config); add them to improve consistency.

The Bottom Line

windmill delivers a full‑stack, self‑hostable platform for script‑driven APIs and workflows, with a solid Rust backend and a flexible Svelte/React UI. The codebase is extensive and modular but shows typical enterprise‑scale health gaps: over‑broad CI permissions, committed secrets, and unpinned dependencies. Addressing those items will make the repo production‑ready for teams that need an open‑source alternative to Retool or Temporal.