SandboxStartup scripts

Run setup scripts when a sandbox starts

Save a script once, and it runs in every matching sandbox you create: install a tool, write a config file, log in to a registry with a stored secret. You manage scripts through the REST API; they apply to sandboxes created from any SDK, the CLI or the dashboard.

Save a script

curl -X POST "https://sandbox.tangle.tools/v1/startup-scripts" \
  -H "Authorization: Bearer $TANGLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "install-ripgrep-config",
    "description": "Default ripgrep config for coding agents",
    "scriptType": "bash",
    "content": "mkdir -p ~/.config && printf -- \"--smart-case\\n\" > ~/.config/ripgreprc"
  }'

The next sandbox you create runs the script while it starts. The Python SDK’s client.fetch returns the raw response and does not raise on an error status.

Script fields

FieldEffect
name, descriptionLabels.
scriptTypebash (the default), python, node, ruby or custom.
contentThe script.
environmentsRun only in sandboxes created from these environments. Empty runs in all of them.
minCpuCores, minRamGBRun only in sandboxes at least this large.
runOrderScripts run in ascending order.
timeoutSecondsThe script fails if it runs longer.
continueOnFailurefalse (the default) fails the create when the script fails; true logs the failure and continues.
runAsRootRun as root. Needs a paid plan; a free account gets 403 TIER_REQUIRED.
injectSecretsNames of your stored secrets to give the script.
enabledDisabled scripts never run.

Size caps, defaults and the allowed ranges are on Limits. Scripts run in the workspace directory.

Which scripts run

At create, every enabled script whose environments, minCpuCores and minRamGB match the new sandbox runs, in runOrder. To run an enabled script that does not match those filters, name it in the create body’s startupScriptIds:

SANDBOX_ID=$(curl -s -X POST "https://sandbox.tangle.tools/v1/sandboxes" \
  -H "Authorization: Bearer $TANGLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "with-setup", "startupScriptIds": ["<script-id>"]}' | jq -r '.id')
 
curl -X DELETE "https://sandbox.tangle.tools/v1/sandboxes/$SANDBOX_ID" \
  -H "Authorization: Bearer $TANGLE_API_KEY"

Naming a script never turns on a disabled one.

No startup scripts run in isolated sandboxes, and an isolated create that names startupScriptIds is refused.

A create with agent: false provisions no startup scripts. It is refused with 400 when it names startupScriptIds or when one of your enabled scripts applies to it, so disable or narrow those scripts before you create sandboxes with agent: false.

A script with injectSecrets reads those secrets even when the create did not select them. A secret stored with proxy custody still reaches the script as a placeholder.

Manage scripts

RoutePurpose
GET /v1/startup-scriptsList your scripts: { scripts }.
POST /v1/startup-scriptsCreate one: { script }.
GET /v1/startup-scripts/{id}Read one.
PUT /v1/startup-scripts/{id}Update any field.
PATCH /v1/startup-scripts/{id}/toggleTurn a script on or off.
DELETE /v1/startup-scripts/{id}Delete it.
curl "https://sandbox.tangle.tools/v1/startup-scripts" -H "Authorization: Bearer $TANGLE_API_KEY"
 
curl -X PUT "https://sandbox.tangle.tools/v1/startup-scripts/$SCRIPT_ID" \
  -H "Authorization: Bearer $TANGLE_API_KEY" -H "Content-Type: application/json" \
  -d '{"environments": ["universal"], "runOrder": 10}'
 
curl -X PATCH "https://sandbox.tangle.tools/v1/startup-scripts/$SCRIPT_ID/toggle" \
  -H "Authorization: Bearer $TANGLE_API_KEY"

The TypeScript SDK, the Python SDK and the CLI have no startup script commands, and the TypeScript create options have no startupScriptIds; use these routes.

Next