Script library
The script library is where you store, edit, and version scripts once and then reference them from jobs — instead of pasting script text into each job that needs it. A referenced job always runs the library copy, so a fix in one place reaches every job that points at it.
What a script has
| Field | Notes |
|---|---|
| Name / Description | Identify the script. A name is 1–255 characters and follows the platform naming rules. |
| Type | The script's language, chosen from the script type catalog. It sets the editor's syntax highlighting and is fixed once the script is created. |
| Content | The script body, edited in-place. |
| Workspace | The workspace the script belongs to. |
New scripts default to the Shell type. You can Import a script from a file (up to 1 MB); for a new script the type is detected from the file extension.
Script types
A script type is a language in the catalog: a name, a file extension, and the editor language that decides syntax highlighting. Continuum ships eight built-in types, and you can add your own.
| Built-in type | File extension |
|---|---|
| PowerShell | .ps1 |
| Python | .py |
| Perl | .pl |
| Command Shell | .cmd |
| VBScript | .vbs |
| Bash | .sh |
| Shell | .sh (the default for a new script) |
| SQL | .sql |
Add your own script type
Scripts › Script Types lists every type you can see, with Built-in or Custom in the Source column. New Script Type adds one. A type you add belongs to your tenant and is visible only inside it, and it is then offered everywhere a built-in type is — a script's Type list, the Scripts report's type filter, and search.
| Field | Notes |
|---|---|
| Name | Required, 1–100 characters. Compared case-insensitively against every type you can see, built-ins included, so you cannot add a second Shell. |
| Extension | Required, 1–12 letters or digits, without the dot — a dot you type is stripped. Matched case-insensitively. More than one type can share an extension. |
| Default for this extension | Makes this the type a new or imported script with that extension is given. Only one type you can see may hold an extension's default: when another already holds it, the switch is unavailable and names the holder — .sh already defaults to Shell. Because built-ins cannot be edited, an extension a built-in type defaults to can never be taken over. |
| Editor Language | Optional, from a fixed list. Sets syntax highlighting; None (plain text) leaves the script unhighlighted. |
| Description | Optional, up to 2000 characters. |
The extension and the editor language of a type you own can be changed afterwards. Changing the extension does not re-type the scripts already using it — a script's type is fixed when it is created. If you change the extension of a type that is the default into one that is already taken, the save is refused until you turn Default for this extension off or choose another extension.
A built-in row's menu offers View rather than Edit, its Delete is unavailable, and the
dialog that opens explains why and offers Duplicate — which starts a new type pre-filled from
it, named <name> (copy). The same applies to built-in runners.
A script type cannot be deleted while anything uses it. The delete is refused and the dialog lists what is in the way — the scripts of that type, and the runners built for it. Repoint or remove those first.
Versions
Every content change creates a new version with an optional change description, linked to the version it came from — a full history you can review. You can open an earlier version (read-only) and Restore it, which creates a new version from that older content rather than erasing the ones in between.
Version 1 can carry a change description too. Earlier builds accepted one only from version 2 onwards, so the first version of every script was the one entry in its history that could not explain itself — which mattered most for a script brought in from elsewhere, where the note is the record of where it came from. A change description is optional, at most 500 characters, and is trimmed before it is stored; a blank one is stored as no note at all.
When a job references a script it either tracks the latest version or pins a specific version number (see below).
When a save is refused
Two different things make a save fail, and they need opposite responses. The page tells them apart rather than guessing:
| What happened | What the page says | What to do |
|---|---|---|
| Someone else saved first — the script changed underneath you while you were editing | This script was changed by someone else while you were editing. | Reload. Nothing you change on the form can fix it. |
| The name is taken | A script with this name already exists | Type a different name. Reloading cannot help. |
A conflict of the first kind offers a Reload latest action. When you have unsaved edits, the button reads Reload latest, discarding my changes and the message tells you to copy anything you still need out of the form first — reloading replaces the form with the stored version, and nothing snapshots your work.
Every kind of save on this page sends the version it was working from, including a description-only edit and a Restore, so any of them can lose this race. A restore that loses it says so in its own words — you were viewing an older version rather than editing — and reloading leaves you on the latest, so the restore has to be repeated.
Three things can go wrong with the reload itself, and each says which:
| Outcome | Meaning |
|---|---|
| Could not load the latest version. Check your connection and try again. | A transient failure. The offer stays up so you can retry. |
| This script has been deleted, or you no longer have permission to view it… | Nothing to reload. Retrying cannot fix it, so no retry is offered — copy what you need and leave the page. |
| The server has not caught up with the change yet, so nothing was reloaded. | The reload came back no newer than the version your failed save was built on. Try again in a moment; re-seeding the form from it would only conflict again. |
A lost race was reported as A script with this name already exists, which sent you to rename a script whose name was never the problem — and offered no way out, because renaming does not clear a stale version. A description-only edit and a Restore send no name at all, so blaming one was pointing at a field that was not on screen.
The script form re-reads the stored script whenever the page regains focus, and re-seeds itself from what comes back — so unsaved edits can be replaced without you doing anything. A save conflict is exactly the moment you are likely to switch away to go and ask the colleague who saved first, so copy anything you still need before leaving the page. The sibling workflow and property editors keep unsaved work across that refresh; the script editor does not yet.
Runners
A runner is the program a legacy LSAM agent starts a script with, and the command template it uses to do it. A runner belongs to one script type and one agent platform, so the choices a job offers depend on the script's language — pick the script first. Universal Agent jobs don't use runners; for scripts that run on the Universal Agent, see Run Script job.
Continuum ships ten built-in runners, covering Windows and UNIX:
| Platform | Script types with a built-in runner |
|---|---|
| Windows | Everything except Shell and Bash |
| UNIX/Linux | Shell, Bash, Perl, Python |
Which script types have a runner for a platform decides what each job's Script list offers. A script with no runner for a platform cannot be used by a job on that platform, and is not offered in that job's Script list. In the built-in catalog, Shell and Bash have no Windows runner — which matters because Shell is the default type for a new script, and is also what library scripts carried over from before script types existed were given — and SQL has no UNIX runner.
The built-in UNIX runners name their interpreter by absolute path (/bin/sh, /bin/bash,
/usr/bin/perl, /usr/bin/python3), because a UNIX LSAM agent may start the script without
searching PATH. A host without the interpreter at that path fails when the script starts.
Adding a runner is how you fix both of those. The Script list is worked out from the runners
you can see, so a Windows runner you add for Shell makes every Shell script available to Windows -
Embedded Script jobs, and a UNIX runner naming your own interpreter path — say
/opt/python3.11/bin/python3 — makes Python scripts run on a host that does not have
/usr/bin/python3.
Add your own runner
Scripts › Runners lists every runner you can see, with its script type, platform, command format, and Built-in or Custom in the Source column. New Runner adds one, and Duplicate on any row starts from a copy of it. A runner you add belongs to your tenant and is visible only inside it.
| Field | Notes |
|---|---|
| Script Type | Required. Any type you can see, built-in or your own. Fixed once the runner is created. |
| Platform | Required, Windows or UNIX. Fixed once the runner is created. |
| Name | Required, 1–100 characters. It has to be unique only among your own runners for the same script type and platform, compared case-insensitively — so a runner of yours may reuse a built-in runner's name. |
| Command Format | Required. The command the agent runs, with $FILE where the script file goes and $ARGUMENTS where the job's arguments go. The rules differ by platform — see below. |
Script Type and Platform cannot be changed afterwards because every job that already points at the runner chose it for that pair. To move a runner to another type or platform, duplicate it and repoint the jobs.
Command format rules
$FILE is required — without it the agent would have nothing to run. $ARGUMENTS is optional,
and is where the job's Arguments field is inserted. The form checks the template as you type and
Save stays unavailable until it is valid, which is the same check the platform applies when the
job is dispatched.
| Rule | Windows | UNIX |
|---|---|---|
$FILE | Required, in any case, anywhere in the template | Required, spelled exactly $FILE, as its own word separated by spaces |
$ARGUMENTS | Any case, anywhere | Exactly $ARGUMENTS, as its own space-separated word |
| Length | At most 4000 characters | At most 127 bytes — the form counts the bytes for you |
| Also rejected | — | The text </F> or <F I=, which the UNIX agent protocol reserves |
The UNIX rules are stricter because a UNIX LSAM agent matches whole, space-delimited, upper-case
words: "$FILE", $file and --in=$FILE are all read as literal text rather than as the script
path, so they are refused at save rather than failing on the agent. A UNIX template is measured in
bytes, not characters, so a non-ASCII character costs more than one.
A template may contain [[property]] tokens — /opt/[[PYTHON_DIR]]/bin/python3, for example. They
are resolved when the job is dispatched, and the result is re-checked against the rules above, so a
token that expands to something the agent could not run fails the job with a reason instead of
running the wrong command. The tokens that resolve are the same ones job parameters support — see
Properties and tags.
When a change to a runner takes effect
An edit is live on the next run, and runners are not versioned — there is no pinning, so every job that uses the runner picks up the change. When you edit a runner that is in use, the dialog says so: Used by N jobs. Changes apply to their next run. The count is the jobs you can see. For up to about a minute after you save, a job starting in that moment may still be sent the previous template; after that every dispatch uses the current one. The same window applies to a deleted runner.
A runner cannot be deleted while a job references it. The delete is refused and the dialog lists the jobs in the way. A job counts if it is in a workflow's current version, or in a version an active deployment has pinned — a job that only exists in some older, unpinned version does not hold the runner. The guard counts every reference in your tenant, while the list shows only those in workspaces you can view, so a refusal can name fewer jobs than it counted.
Who can change the catalog
Reading runners and script types needs scripts.view — the same permission as the script library,
so anyone who can pick a runner on a job can see the catalog. Changing it needs scripts.view
plus one of script-catalog.create, script-catalog.edit or script-catalog.delete.
The actions you lack are unavailable and say why.
script-catalog is tenant-wide, so a role's workspace scope does not narrow it, and it has no view
of its own — which also means granting its create, edit or delete does not imply any view
permission the way other object types do. A role needs scripts.view granted as well. Administrator
holds all three; any other role has to be granted them. See
Roles and permissions.
Referencing a script from a job
Two job types run a library script on a legacy machine: Windows - Embedded Script
(windows-embedded-script) and UNIX - Embedded Script (unix-embedded-script). Both take the
same four fields:
| Field | Notes |
|---|---|
| Script | The library script to run. Only scripts whose type has a runner for that job's platform are listed; if a script you expect is missing, change its type or add a runner for that type. |
| Version | Track the newest version, or pin a specific version number. |
| Runner | The program that starts it on the agent; the choices depend on the script's language, so pick the script first. |
| Arguments | Optional arguments passed to the script. |
On the UNIX job type, Batch User is required, and it is also the account that owns the script
file the agent writes for the run. Its Arguments are inserted into the runner's command line
unquoted, so the agent's shell interprets quotes, $VAR references and metacharacters — see
UNIX - Embedded Script.
Script and runner are checked when the workflow is saved
A script and a runner that do not go together are caught by the workflow save, which names the job and what is wrong, rather than by the job failing on its next run:
| Refused | What the message says |
|---|---|
| The script is not there | script '…' was not found. Choose another script. |
| Runner was left empty | a Runner is required to run a script. |
| The runner is not there | runner '…' was not found. Choose another runner. |
| The runner is built for another script type | runner '…' does not run this script's type. Choose a runner for the script's type. |
| The runner targets the other platform | runner '…' targets UNIX agents, but this job runs on WINDOWS agents. Choose a WINDOWS runner. |
Only the jobs this save changed are checked — a job whose script, runner or job type is untouched is left alone. So a workflow that already holds a broken pair, because the runner was deleted since or the job was written through the API, can still be saved for an unrelated edit rather than trapping the person who has to repair it. Every job is checked when a workflow is first created, since nothing there is unchanged.
Importing automation reports the same problems as warnings and still completes, because a bundle carries no scripts or runners of its own and an export from another installation names ids that exist only there.
A job also says when the script or runner it holds has gone. Rather than leaving an identifier on screen with no explanation, the Script and Runner fields read This script is no longer available. Choose another. once the platform has confirmed the stored value cannot be found.
See the Job type catalog for where these job types sit, and Relays for how legacy LSAM jobs reach the machine.
Copy, delete, and cross-references
- Copy duplicates a script into a new one — same content, type, and workspace — starting a fresh
version history. The dialog suggests
<name> - Copy. - Delete is blocked while a job references the script. The delete is refused and a dialog lists the jobs that use it; remove those references (or repoint them) first. The Cross Reference action shows the same list at any time.
Things to know
- Scripts are a reportable object. Build a Scripts report to list them — see Reports.
- The type can't change after creation. If you picked the wrong language, copy the script and choose the right type on the copy.
- A pinned version keeps running even as the script evolves. A job set to a pinned version doesn't pick up later edits until you change it to Latest or pin a newer version.
Related topics
- Job type catalog — every job type, including Windows - Embedded Script
- Run Script job — running an embedded script on the Universal Agent
- Reports — reporting on scripts and other objects