Your own programs

Vom Skript zur nativen Executable — ein Klick. Der Empfänger installiert nichts.

Das ist das Feature, das OpticScript abhebt: Jedes Skript, das Sie im Playground schreiben, ist einen Button-Klick von einer echten, in sich geschlossenen .exe (oder Linux- / macOS-Binary) entfernt. Keine Python-Runtime, kein Node-Setup, kein pip install, kein Docker-Image, keine node_modules. Eine Datei. Versenden. Fertig.

$ ls -lh bin/
-rwxr-xr-x  1 mlc  staff   16M  17. Mai 12:33  enhance
$ ./enhance --input portrait.jpg --output portrait_warm.jpg \
            --brightness 1.15 --saturation 1.4 --vignette 0.5
✓ portrait_warm.jpg

Diese Binary ist ~16 MB groß, bettet die komplette Bild-Engine plus Ihr Skript ein und läuft in derselben nativen Geschwindigkeit wie der Playground selbst.

Im Playground — ein Klick

Den Make Exe-Button in der Editor-Toolbar klicken. Ein Dialog öffnet sich, fragt nach einem Tool-Namen, wählt standardmäßig Ihre aktuelle Plattform, und kurz darauf bekommen Sie den Pfad zur fertigen Binary. Der Build dauert Millisekunden, keine Minuten — die Engine liegt als vorgebauter Stub bereit; der Compiler hängt Ihr Skript als Blob an dessen Ende.

Dasselbe auf der Kommandozeile:

mlcos-compile-rs enhance.js
# → ./enhance       (Linux/macOS)
# → ./enhance.exe   (Windows)

Überall ausführbar — der Empfänger braucht kein OpticScript, keinen Playground, kein Rust, Go, Python oder sonstige Runtime. Die Binary ist vollständig eigenständig.

Was in der Binary landet

Eingebettet Warum das zählt
Die Bild-Engine (~16 MB) Native Pixel-Ops, keine externe Runtime.
Ihr Skript Als JS-Quelltext — --help liest es zurück, damit Sie auch später noch wissen, was das Tool tut.
Beide eingebauten Schriften (Inter + JetBrains Mono) Text-Overlays / Wasserzeichen brauchen keine Font-Dateien.
Installierte Engine-Erweiterungen Custom JS-Module (z.B. die cube-Extension) reisen automatisch mit.

Was nicht eingebettet wird (bewusst extern):

  • KI-Modellgewichte (GFPGAN, Real-ESRGAN). Tools, die diese aufrufen, laufen neben dem AI Tools Pack — dieselben Modelldateien wie im Playground.

Ihre Skript-Direktiven werden zu CLI-Flags

Jede //!INPUT:-, //!OUTPUT:- und //!PARAM:-Zeile am Skript-Anfang wird zu einem getypten Kommandozeilen-Flag. Das Skript:

// enhance.js
//!INPUT: INPUT
//!OUTPUT: OUTPUT
//!PARAM: BRIGHTNESS:number=1.10,min=0.5,max=2.0
//!PARAM: SATURATION:number=1.20,min=0,max=3
//!PARAM: VIGNETTE:number=0.30,min=0,max=1

Engine.loadImage(INPUT)
  .brightness(BRIGHTNESS)
  .saturation(SATURATION)
  .vignette(VIGNETTE)
  .save(OUTPUT);

Kompiliert, dann --help:

$ ./enhance --help
enhance
Erstellt mit MLC OpticScript v2.1.3 · https://mlcgo.eu
Copyright (c) 2026 Michael Lechner · Elastic License 2.0

VERWENDUNG:
    enhance --INPUT=<Pfad> --OUTPUT=<Pfad> --BRIGHTNESS=<Wert>
            --SATURATION=<Wert> --VIGNETTE=<Wert>

EINGABEN:
    --INPUT=<Pfad>          (Bild laden)

AUSGABEN:
    --OUTPUT=<Pfad>         (Speicherziel; `-` für stdout)

PARAMETER:
    --BRIGHTNESS=<Wert>     (Standard: 1.10)
    --SATURATION=<Wert>     (Standard: 1.20)
    --VIGNETTE=<Wert>       (Standard: 0.30)

Die in //!PARAM: deklarierten min/max-Bereiche werden zur Laufzeit geprüft — Werte außerhalb des Bereichs werden abgelehnt, bevor das Skript überhaupt startet.

Einen ganzen Ordner verarbeiten — ohne Skriptänderung

Dieselbe Binary erledigt Batch-Verarbeitung. --INPUT auf einen Glob und --OUTPUT auf ein Template setzen — die Engine bleibt über den ganzen Loop "warm":

./enhance --INPUT='photos/*.jpg' --OUTPUT='enhanced/{stem}.png'
batch: 17 Datei(en) via --INPUT
✓ OUTPUT → enhanced/IMG_0001.png
✓ OUTPUT → enhanced/IMG_0002.png
…
Eingabe-Muster Beispiel
Glob 'photos/*.jpg', '**/*.png'
Dateiliste (eine pro Zeile) @todo.txt (#-Kommentare erlaubt)
Komma-Liste a.png,b.png,c.png

Ausgabe-Templates unterstützen die Platzhalter {stem} / {name} / {ext} / {dir} / {idx} / {n}.

Filter-Modus — - ist stdin / stdout

Jede kompilierte Binary funktioniert auch als Unix-Filter:

# PNG von stdin lesen, JPEG nach stdout schreiben
cat foto.png | ./enhance --INPUT=- --OUTPUT=- \
                         --stdout-format=jpg --silent > raus.jpg

# Zwei Filter verketten
cat in.jpg | ./grayscale --INPUT=- --OUTPUT=- --silent \
           | ./watermark --INPUT=- --OUTPUT=- --silent \
                         --BRAND="© Acme" > final.png

Feature-Check

Was in jeder kompilierten Binary „einfach läuft", ohne externe Abhängigkeiten:

  • PNG / JPEG / WebP / AVIF / TIFF lesen + schreiben
  • Animiertes WebP + APNG + Multi-Page TIFF für Animationen
  • EXIF beim Laden gelesen, beim JPEG-Save geschrieben (meta.exif.*)
  • SVG-Import (resvg) und SVG-Export (vtracer) — voller Vektor-Loop
  • 35+ Pixel-Operationen — Weichzeichnen, Schärfen, Warp, Blend, Farbkorrektur, Kantenerkennung, …
  • Textrendering mit zwei eingebetteten Variable-Fonts (Inter, JetBrains Mono)
  • WarpGrid-Mesh-Transformationen für Perspektive / 3D-Flächen-Projektion
  • Eigene Convolution-Kernel für Schärfen / Prägen / Motion-Blur / etc.

Cross-Plattform-Builds

Der „Make Exe"-Button im Playground baut standardmäßig für Ihr aktuelles OS. Cross-Compilation (z.B. Windows-.exe von macOS aus) ist ein Pro-Feature — siehe Preisliste.

Auf der Kommandozeile:

# Nativ (Host-Plattform)
mlcos-compile-rs enhance.js --overwrite

# Ausgabename / -pfad überschreiben
mlcos-compile-rs enhance.js --name colour-enhancer --output ~/bin/

# Cross-Target (Pro): auf einen vorgebauten Stub für das Ziel-OS zeigen
mlcos-compile-rs enhance.js --stub ./stubs/mlcos-run-rs-windows-x64.exe

Windows: Icon und Dateieigenschaften

Eine kompilierte .exe trägt das OpticScript-Icon und füllt Eigenschaften → Details: Produktname und Beschreibung kommen aus //!TITLE: und //!DESC: des Skripts, die Version ist ohne Angabe 1.0.0. Eigene Angaben:

mlcos-compile-rs verbessern.js --icon logo.png --app-version 1.2.0 \
    --company "Beispiel GmbH" --copyright "© 2026 Beispiel GmbH"

--icon nimmt eine .ico oder ein beliebiges PNG/JPEG/WebP — die Größen, die Windows braucht, werden erzeugt. Das klappt auch, wenn unter Linux oder macOS für Windows kompiliert wird (--stub …/mlcos-run-rs.exe).

macOS: lokal ja, weitergeben nein

Auf macOS laufen die erzeugten Binaries auf Ihrem Rechner einwandfrei — weitergeben lassen sie sich aber nicht.

Der Compiler haengt das Skript hinter das Dateiende des Stubs. Fuer den Kernel ist das unsichtbar, er prueft nur bis zum codeLimit der Signatur. codesign sieht es sehr wohl:

codesign --verify ./enhance   → main executable failed strict validation
spctl --assess    ./enhance   → rejected
codesign --sign - ./enhance   → verweigert die Signatur ganz

Die Datei laesst sich also weder signieren noch notarisieren. Solange sie auf Ihrem Rechner bleibt, merkt niemand etwas davon: lokal erzeugte Dateien tragen kein Quarantine-Attribut, und Gatekeeper sieht sie nie an. Sobald jemand sie herunterlaedt oder per AirDrop bekommt, lehnt Gatekeeper sie ab — und zwar ohne Umweg fuer den Empfaenger.

Fuer die Weitergabe an macOS-Nutzer nehmen Sie deshalb einen der leichteren Wege aus dem naechsten Abschnitt (Wrapper-Skript oder das blanke .js), oder Sie liefern das Skript und lassen den Empfaenger mlcos-compile-rs selbst aufrufen. Windows und Linux sind davon nicht betroffen.

Drei Wege zur Distribution, sortiert nach Aufwand

Nicht jedes Mal braucht es einen vollständigen Compile. Wenn Ihr Publikum den OpticScript-Installer schon hat, gibt es leichtere Varianten:

Zielgruppe Was Sie ausliefern Was sie installieren
Eigenes Team / intern enhance.js + mlcos-run-rs enhance.js … OpticScript
Poliertes Tool, intern mlcos-compile-rs --wrap=auto enhance.js → enhance.cmd / enhance.sh OpticScript
Externe Nutzer enhance.exe (kompiliert) Nichts

Kompilierte Binaries sind die Antwort für die dritte Zeile — die, in der Sie null Rückfragen vom Empfänger wollen.

Fehlerbehebung

  • INPUT is not defined zur Laufzeit — das Skript verwendet INPUT, deklariert aber //!INPUT: INPUT nicht (oder den passenden Key). Die Direktive ergänzen, damit der Compiler weiß, was er verdrahten soll.
  • batch mode … requires a placeholder — Ihr Eingabe-Flag passte auf mehrere Dateien, aber der Ausgabe-Pfad ist fix. Einen Platzhalter wie {stem} in die Ausgabe einbauen.
  • two inputs are multi-valued patterns; only one input may batch — Eine der Eingaben auf eine einzelne Datei fixieren; die andere darf weiter batchen.

Siehe auch