mule-headless-dev

star 1

Run, deploy, and iterate on a MuleSoft (Mule 4) application on a REAL local runtime WITHOUT Anypoint Studio — a headless build → deploy → test → repeat loop for fast, autonomous Mule development. Use this whenever you need to actually run a Mule app locally, redeploy it after a code/config change, smoke-test a flow, reproduce or confirm a runtime bug, or set up a standalone Mule runtime — even if the user just says "test the mule app", "run my mule flow", "deploy this locally", "redeploy", "why isn't my change showing up", or "spin up a mule runtime". Covers Windows, Linux, and macOS, hot-redeploy vs full restart, and the common runtime gotchas (JDK version, Studio-copy self-termination, boot timeouts, stale classloaders, object-store state). Prefer this skill over hand-rolling `mvn`/`mule` commands for anything that runs a Mule app at runtime.

chirstius By chirstius schedule Updated 6/10/2026

name: mule-headless-dev description: >- Run, deploy, and iterate on a MuleSoft (Mule 4) application on a REAL local runtime WITHOUT Anypoint Studio — a headless build → deploy → test → repeat loop for fast, autonomous Mule development. Use this whenever you need to actually run a Mule app locally, redeploy it after a code/config change, smoke-test a flow, reproduce or confirm a runtime bug, or set up a standalone Mule runtime — even if the user just says "test the mule app", "run my mule flow", "deploy this locally", "redeploy", "why isn't my change showing up", or "spin up a mule runtime". Covers Windows, Linux, and macOS, hot-redeploy vs full restart, and the common runtime gotchas (JDK version, Studio-copy self-termination, boot timeouts, stale classloaders, object-store state). Prefer this skill over hand-rolling mvn/mule commands for anything that runs a Mule app at runtime.

Mule headless dev loop (no Anypoint Studio)

Build a Mule app, deploy it to a real standalone Mule runtime, test it, and iterate — all from the command line. This is the fast, scriptable, autonomous alternative to clicking "Run" in Anypoint Studio, and it's the only practical way to do a tight edit → deploy → test loop unattended.

When to use this

  • You need to actually run a Mule app at runtime (not just unit tests) — smoke-test a flow, hit an HTTP listener, confirm a fix behaves correctly, reproduce a runtime bug.
  • You want a fast iterate loop: change code/config → redeploy in seconds → re-test.
  • You're working without Studio (CI, a headless box, an agent session, or just speed).
  • You need to stand up a local Mule runtime in the first place.

The mental model (read this once)

  • mvn clean package on a Mule project produces target/<artifactId>-<version>-mule-application.jar.
  • A standalone Mule runtime continuously watches its apps/ folder. Drop a jar in → it deploys. Replace the jar (newer timestamp) → it hot-redeploys in place in a few seconds, no restart.
  • So the loop is: keep one runtime running, and iterate by rebuilding + copying the jar. Test by exercising the app (HTTP calls, the project's test scripts, etc.).
  • Keep exactly ONE runtime per app. If several exist (a leftover standalone, Studio's embedded runtime, two copies in different folders), you can rebuild + deploy into one while the port you're testing is served by another — your change silently never lands, and it looks exactly like a stale classloader. The deploy target must be the runtime that owns the test port (find it via the port → PID → -Dmule.home query in references/troubleshooting.md §11). Retire the rest.
  • Full restarts are rarely needed — but they ARE sometimes the only way to be sure a change is live (see "Hot-redeploy vs full restart" below). Reach for one when in doubt.

Prerequisites

Check these first; the setup script verifies them too.

  • JDK 17. Mule 4.9+ runs on Java 17. Many machines default java to 8 or 11 — that will fail with UnsupportedClassVersionError. You must point JAVA_HOME at a JDK 17 for every mvn and mule invocation. (The bundled scripts auto-detect a JDK 17 and set this for you.)
  • Maven 3.9+.
  • Anypoint Maven credentials in ~/.m2/settings.xml — needed to download the EE runtime and to resolve EE connectors / Exchange dependencies. Required if the app uses EE features (ee:transform/DataWeave, most connectors). If you can already mvn clean package the project, you have these.

One-time setup (per machine)

Run scripts/setup.sh (Linux/macOS) or scripts/setup.ps1 (Windows). It detects the OS and a JDK 17, downloads the runtime, extracts it, and configures it. Or do it by hand:

  1. Download a CLEAN standalone Mule EE distribution via Maven (one zip works on every OS — it bundles Windows/Linux/macOS launchers + wrapper binaries):
    mvn dependency:get -Dartifact=com.mulesoft.mule.distributions:mule-ee-distribution-standalone:<version>:zip
    
    Pick a <version> that matches your app's target runtime (e.g. 4.11.4). It runs on a 30-day evaluation license out of the box — fine for local dev.
  2. Extract the zip to a user-writable directory (e.g. ~/mule-ee or D:\mule-ee). NOT under C:\Program Files / a path that needs admin, or hot-deploy will fail on permissions.
  3. Configure conf/wrapper.conf:
    • wrapper.ping.timeout=300 — the default 30 can kill a slow or resource-contended boot (the wrapper pings the JVM; if it can't answer within the window during a heavy boot, it does DUMP,RESTART and the runtime dies ~30 s in).
    • Add any system properties / secure properties your app needs as wrapper.java.additional.N=-Dkey=value (e.g. -Dclaude.apiKey=…). ignore_sequence_gaps=TRUE is set, so any free N (e.g. 101) works.
  4. Deploy the app: mvn clean package then copy target/*-mule-application.jar into <runtime>/apps/.

CRITICAL — do NOT use Anypoint Studio's embedded runtime as your standalone runtime. The runtime bundled inside …/AnypointStudio/plugins/…server.<ver>.ee…/mule is coupled to the IDE: run standalone it deploys the app and then self-terminates ~200 ms later (AgentStudioManagementService teardown → shutdown hook), in every launch mode. Always download a fresh standalone distribution.

The loop

  1. Start the runtime (once): scripts/start.{sh,ps1}. This pins JDK 17 and launches the runtime.
    • Linux/macOS: bin/mule start daemonizes cleanly; the runtime survives the shell. bin/mule stop to stop.
    • Windows: run bin\mule.bat console under a background shell so it persists. (Do NOT use the Windows servicemule.bat install/start hits the Windows SCM ~30 s service-start timeout vs Mule's slower boot and the SCM aborts it. Console-under-a-background-shell is the reliable path; no admin needed.)
  2. Redeploy after a change: scripts/redeploy.{sh,ps1}mvn clean package, copy the jar into apps/, then wait until the runtime logs Started app '<name>' (and, if given, an app health endpoint returns 200).
  3. Test: exercise the app — curl its HTTP listener, run the project's *-test scripts, etc.
  4. Repeat. Edit → redeploy → test.

Platform specifics

Windows Linux / macOS
Launcher bin\mule.bat bin/mule
Keep it running console mode under a background shell (service path fails: SCM 30 s timeout) mule start daemonizes — survives the shell
Stop mule.bat stop if started as console it ignores; kill the wrapper/javaw (scripts/stop.ps1) mule stop
Find JDK 17 Eclipse Adoptium under Program Files; else winget install EclipseAdoptium.Temurin.17.JDK mac: /usr/libexec/java_home -v 17; linux: update-alternatives, sdkman, or /usr/lib/jvm/java-17-*
Process tools taskkill, Get-CimInstance Win32_Process ps, pkill, kill

Windows: prefer the .ps1 scripts. Run under PowerShell, not Git-Bash. Git-Bash/MSYS rewrites /-leading paths and some env values into Windows paths when it calls a native exe (e.g. /a2aC:/Program Files/Git/a2a), which silently corrupts args/-D props/baked config. The .ps1 scripts set env vars natively and avoid it. If you must use .sh under Git-Bash, see references/troubleshooting.md §12.

Readiness & deploy-result detection (works for ANY Mule app)

The reliable, app-agnostic signal is the runtime log at <runtime>/logs/mule_ee.log:

  • Success: a line Started app '<artifactId>...'.
  • Failure: Failed to deploy, DeploymentException, or ... could not be deployed.

If the app exposes an HTTP listener, also poll its endpoint (or /console, or any known path) for a 200 to confirm it's actually serving. The bundled redeploy script does both.

Hot-redeploy vs FULL restart — when in doubt, restart

Hot-deploy (copy the jar) is fast and usually correct. But Mule reuses classloaders and caches some resources, so occasionally a redeploy does not reflect your latest code or config — you'll see stale behavior, a config/property change that "isn't picked up," or generally weird state. This is the single most important troubleshooting reflex: when you're not certain a change is actually live, do a FULL restart / full redeploy. It's cheap and removes all doubt.

Full clean redeploy (see references/troubleshooting.md for the scripted version):

  1. Stop the runtime.
  2. Remove the exploded app in apps/: delete both <runtime>/apps/<name>/ (the exploded directory) and <runtime>/apps/<name>-anchor.txt. This forces a clean re-explode of the jar (not a patch of the old one).
  3. Copy the freshly built jar into apps/.
  4. Start the runtime and watch for Started app.

scripts/restart.{sh,ps1} does exactly this. Use it whenever a hot-redeploy's result is suspicious, when you changed something the hot path doesn't reliably re-read (some META-INF/resource files, log4j2 config, certain global configs), or just to get a known-good baseline before chasing a bug.

Also beware persistent state between test runs: persistent Object Stores and other on-disk state live under <runtime>/.mule/ (and survive restarts). A test that assumes a clean slate can be polluted by a prior run. If results look "remembered," clear the relevant Object Store data (or <runtime>/.mule/<app>/) before re-testing.

Troubleshooting

references/troubleshooting.md has the full catalog with concrete fixes: boot dies ~30 s, Studio-copy self-termination, UnsupportedClassVersionError (wrong JDK), port already in use, stale hot-reload → full restart, Object-Store state leakage, license/eval, mule.bat/JAVA_HOME not found, and clean-vs-hot redeploy. Read it when anything doesn't behave as expected.

Scripts reference

All scripts are parameterized (no hardcoded paths). They take options via flags or environment variables; run any with -h/--help (or read the header). Common settings: the runtime home (MULE_RUNTIME), the Maven project dir (MULE_PROJECT, default = current dir), the JDK 17 home (MULE_JDK17, auto-detected), and an optional app health URL for readiness.

  • scripts/setup.{sh,ps1} — download + extract + configure a clean standalone runtime (one-time).
  • scripts/start.{sh,ps1} — start the runtime (Unix daemon / Windows console-in-background) under JDK 17.
  • scripts/redeploy.{sh,ps1}mvn clean package → copy jar → wait until deployed. The iterate primitive.
  • scripts/restart.{sh,ps1} — FULL clean restart (stop → wipe exploded app + anchor → copy jar → start).
  • scripts/stop.{sh,ps1} — stop the runtime.
Install via CLI
npx skills add https://github.com/chirstius/mule-headless-dev --skill mule-headless-dev
Repository Details
star Stars 1
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator