Docs

Bring your own script

You already automated half your pipeline. Keep it — a small JSON file promotes your script into a step with a card, a run button, and a place in the chain.

How a module works

Every tool the pipeline can drive is described by one JSON file. For a standard app that means: where the executable lives (auto-detected when possible), and what to pass on the command line. No code.

Download the template module and drop it into the app’s resources/modules/ folder (next to the built-in ones), then restart:

{
  "id": "my_tool",
  "label": "My Tool",
  "type": "app_launcher",
  "settings": [
    {
      "key": "exe_path",
      "type": "exe_path",
      "label": "My Tool executable",
      "detect": {
        "paths": [
          "C:\\Program Files\\MyTool\\mytool.exe"
        ]
      }
    }
  ],
  "ui": [
    {
      "key": "script_path",
      "type": "file_picker",
      "label": "Script"
    }
  ],
  "launch": {
    "exe_key": "exe_path",
    "file_arg": {
      "extensions": [
        "obj",
        "fbx",
        "glb"
      ],
      "flag": "--file"
    },
    "script_arg": {
      "flag": "--run-script"
    }
  }
}

Finally, add your module’s id to the sources array of whichever pipeline stages it can perform in resources/skills.json — that’s what makes it appear in the task card’s tool picker.

The status-file contract

When your script runs with the app visible, the pipeline can’t watch the process exit — so it watches a file instead. If the environment variable SMP_STATUS_FILE is set, write a one-line JSON file there when your work completes:

import json, os

# ... your existing script does its work ...

status_path = os.environ.get("SMP_STATUS_FILE")
if status_path:
    with open(status_path, "w") as f:
        json.dump({"ok": True}, f)   # or {"ok": False, "error": "what broke"}

That’s the whole contract: {"ok": true} on success, {"ok": false, "error": "…"} on failure. Optional extras — warnings (a list of caveats that pause the run for review) and artifacts (declare exactly what you produced). A stdlib-only Python helper, smp_status.py, ships in the app’s resources/scripts/ folder.

Skip the status file entirely and the step simply waits for the artist to press Mark Done — your script still runs, the pipeline still chains.

When you outgrow JSON

Headless execution, API calls, and multi-step automation are driver territory — the same system the built-in Blender/Painter/ZBrush drivers use. If your automation deserves that, tell us. The roadmap is scripts that already proved themselves at someone’s desk.