Running scripts¶
Starkite scripts are Starlark programs executed from top to bottom by the kite runtime. The runtime governs the script's execution lifecycle, managing the process from initial load through termination and final resource cleanup.
Ways to run a script¶
Starkite scripts can be executed using the kite CLI via two primary commands:
| Command | Purpose | Reference |
|---|---|---|
kite run |
Executes a Starlark script file, directory, or module. | kite run CLI Reference |
kite exec |
Executes an inline Starlark code fragment directly from the shell. | kite exec CLI Reference |
Both execution methods spawn the same underlying engine.
kite run ./deploy.star # run a file
kite run ./deploy.star --var env=prod # pass variables
kite exec 'print(os.hostname())' # run inline source
To run a script directly without invoking the kite binary explicitly, configure a shebang line and make the file executable:
Once configured with execution permissions, the script runs from a system path or a scheduler (like cron) identical to a native binary.
Entry point¶
For scripts with structured execution logic, you can define a main() function. The runtime automatically invokes main() after executing the top-level script code:
Defining main is optional; scripts without it execute sequentially at the top level.
If a script defines main and also calls it explicitly at the top level, the runtime avoids double-execution by skipping the automatic invocation. A notice is printed to stderr when this occurs:
level=INFO msg="skipping automatic entry-point invocation: script calls it at top level" entrypoint=main script=hello.star
This detection is syntactic; it only recognizes a direct top-level call like main(). Calls made via an alias or within control flow structures will bypass this guard, causing main to run twice.
Automatic invocation applies only to the entry script. A main function defined in an imported module is ignored, preventing libraries from executing automatically upon load.
The entry point function must accept no arguments. External variables are passed to the script via the variable-injection system instead of function parameters.
Exit codes¶
Scripts exit either by completing top-to-bottom execution or by calling an explicit termination function. To signal execution status to shell environments, use exit(code) or fail(msg):
exit(code): Terminates script execution immediately with the specified process exit code.fail(msg): Aborts execution, prints the error message, and returns a non-zero exit code.
Cleanup and signals¶
To release resources like database handles or file locks regardless of execution success or failure, register cleanup functions using defer(fn). Deferred functions run in last-in-first-out (LIFO) order when the script finishes:
Deferred functions execute whether the script completes normally, calls fail, or exits early.
Long-running scripts can handle OS signals to perform clean shutdowns using on_signal(name, fn). For example, trapping "SIGINT" allows a script to stop gracefully:
Registering a signal handler replaces the default process termination behavior, allowing the script to release resources before exiting.