External scripts & plugins

Two opt-in extension points let you bolt your own automation onto Starship without touching core. Both are disabled by default.

External scripts (run_script)

Run an external script or command at any point in a sequence or blockscript - a phase action (on_start / on_error / on_suspend / on_resume / on_end), a sequence body step, or a blockscript state action. Everything flows through one sandboxed executor, so the safety rules live in one place.

Enable it in config.toml:

[scripts] enabled = true allowed_dir = "scripts/user" # scripts MUST resolve under here default_timeout_s = 120.0 allow_shell = false # keep false unless you truly need a shell inherit_env = false # pass the full environment vs a minimal one max_output_chars = 20000

Safety model:

(path-escape and .. traversal are caught by resolved-path containment).

shell-injection surface. allow_shell = true is a documented opt-in.

or a sequence stop fires, so it can never delay safing the rig. An aborted script comes back as success with an "interrupted (abort)" note, so tearing the rig down never trips a spurious error policy.

Script type is detected by extension and run with the right interpreter: .py → python, .ps1 → powershell, .bat/.cmd → cmd, .sh → bash; anything else is executed directly. The script always runs from allowed_dir unless you set an explicit cwd.

Using it:

command = "calibrate.py --filter $filter" (path plus inline args in one string) or command/script for the path and a separate args = [...] list. Optional per-step overrides: timeout_s, cwd, shell. command and script are interchangeable.

set command (the path plus any inline args) and an optional timeout. In a blockscript you can also pass an explicit args list, a cwd, and shell. A non-zero exit is a failed action, so the normal per-action error policy (retry / notify / on_error) applies. Set fail_ok = true to treat a non-zero exit as success-with-note.

Run script is offered by default in the on_start and on_end phases, but you can add it to any phase or step - it is allowed everywhere.

It runs with your account's privileges. A script can do anything - including commanding hardware outside the safety model. The roof keeps its hardwired CloudWatcher interlock; the mount does not. Keep allowed_dir under your control.

Plugins

Drop a .py file in the plugins folder and Starship loads it at startup (in alphabetical order) and calls its register(service) entrypoint. The plugin gets the live service - it can subscribe to the event bus, send notifications, register state, register external scripts, and more.

[plugins] enabled = true plugins_dir = "plugins"

A minimal plugin:

def register(service): bus = service.bus bus.subscribe("safety.state_changed", lambda ev: print("safety:", ev.payload))

Files whose name starts with _ are skipped, so you can keep helper modules or work-in-progress alongside your live plugins. A broken plugin is logged and skipped - it never stops the others or the service. Plugins run with full trust: they are local code you dropped in, exactly like a script.

Astroworx Starship v22.2.10 · this page is the in-app help of that buildDownload · HTTP API