Templates
Shardflux templates: versioned images that workspaces start from, with environment, inputs, start commands and services, and python-node-browser.
What a template is
A template is the image a workspace starts from: an operating system, languages, packages and files, plus the settings every workspace of it gets when it opens. You name it by its slug when you open a key:
await cloud.workspaces.open({ key: 'customer-42/main', template: 'python-node-browser' });Templates come in two kinds:
| Kind | Who publishes it | Examples |
|---|---|---|
| Platform template | Shardflux. Every project can open it. | python-node-browser (category stack), ubuntu-24.04 (category os) |
| Organization template | You, by building one or saving a workspace as one | acme-dev |
Versions
A template has numbered, immutable versions. When a key is opened for the first time, the slug resolves to the template's latest published version, and the workspace keeps that version for its whole life. Publishing a new version changes what new keys get; existing workspaces keep theirs. Fork keeps the source's version, and reset returns to it.
workspace.template (TypeScript) and shard ws get <key> show the slug and version a workspace runs.
Public templates
List what your project can open, and look one up:
shard templates list
shard templates get python-node-browserconst page = await cloud.templates.list();
for (const t of page.data) console.log(t.slug);
const detail = await cloud.templates.get('python-node-browser');print([t["slug"] for t in sf.templates.list(owner="platform").data])
detail = sf.templates.get("python-node-browser")python-node-browser is the template these docs use. It is Ubuntu 24.04 with Python 3.12 (pip, venv), Node.js 24
(npm), git, curl, build-essential and a headless Chromium browser. A workspace of it gets
2,048 MiB of memory unless you set caps.memory_mib. ubuntu-24.04 is a minimal base (bash, apt, sudo, curl and
certificates) to build your own templates on.
Look inside a version without opening a workspace:
shard templates get acme-dev # versions, and which one open resolves to
shard templates files acme-dev 3 /home/user # one directory of version 3
shard templates diff acme-dev --from 2 --to 3 # what changed between two versionsVersions published before file lists existed answer 409 (details.reason: file_list_unavailable).
Settings: environment, inputs, start commands and services
A template version built from a recipe (see Build a template) or saved from a workspace carries settings that apply every time one of its workspaces opens:
| Setting | What it does | Limits |
|---|---|---|
env |
Environment variables for every command, terminal, start command and service | 128 names; values up to 4,096 bytes; names starting with SHARDFLUX_ are reserved |
inputs |
Values supplied when a workspace is opened: text (put into the environment) or secret (binds the stored secret of the same name) |
32 inputs; text values up to 4,096 bytes, no CR, LF or NUL |
start |
Commands run at create (first boot of a new workspace), boot (a later cold boot) or resume |
32 commands; timeout_seconds 1 to 1800 (default 300), 3,600 seconds in total |
services |
Long-running processes kept up by the workspace, with restart (always, on_failure, never) and a readiness check (port or command) |
16 services; ready_timeout_seconds 1 to 600 (default 60) |
defaults |
Default lifetime, idle_timeout_seconds for sessions, an egress ceiling (internet, allowlist, none) and resource limits |
Environment precedence, lowest first: the workspace's base environment, the template's env, the workspace's text
inputs, then the command's own env.
Pass inputs when you open a key:
const ws = await cloud.workspaces.open({ key: 'customer-42/main', template: 'acme-dev', inputs: { PROJECT_NAME: 'acme' } });
console.log(await ws.inputs(), ws.startup);ws = sf.open(key="customer-42/main", template="acme-dev", inputs={"PROJECT_NAME": "acme"})
print(ws.inputs(), ws.startup)shard ws open customer-42/main --template acme-dev --input PROJECT_NAME=acmeOn a new key, each input takes the given value, else its declared default. On an existing key, inputs replaces them
all; leaving it out keeps them. A missing required input is 422 (details.reason: input_required), an undeclared one
input_unknown, and a value that breaks the rules input_invalid.
Start commands and services at open
open waits for the start commands and services: a workspace is ready when they have run and its services report
ready. workspace.startup shows the progress (pending, running, ready or failed).
- Which commands run. A new workspace (and a reset one) runs its
createandbootcommands, in the declared order. A later cold boot runsbootcommands. A resume or fork restores memory, so it runsresumecommands, and the services are still running. - When a step fails. The open fails with
startup_failed(retryable). The workspace keeps running so you can look at it:workspace.startupnames the failed step, its exit code and the last 4 KiB of its output. The next open runs the failed step again. - Changed inputs apply to later commands, not to services that are already running.
Layered and legacy workspaces
Template versions that support it give workspaces a layered disk: the template is a read-only layer, and the workspace's own changes are a separate layer. That separation makes reset, saving a workspace as a template and listing a workspace's changes against its template possible:
const page = await workspace.changes({ pathPrefix: '/home/user', summary: true }); // added | modified | metadata | deleted | replacedWorkspaces created from older versions are legacy (one disk) and answer those calls with 409
(details.reason: legacy_disk_layout). The layout is chosen at the first open and never changes;
workspace.diskLayout (TypeScript) and ws.disk_layout (Python) report it.
Ways to make your own template
| Way | When | How |
|---|---|---|
Build from template.yaml |
Reproducible templates kept in your repository | Build a template |
| Save a workspace as a template | You set a workspace up by hand or with an agent | workspace.saveAsTemplate({ templateSlug }), ws.save_as_template(slug), shard ws save-as-template <key> --template <slug> |
| Draft (dev mode) | Iterate on a template in a live workspace, test copies, then publish | cloud.templates.draft(slug), sf.templates.draft(slug), shard templates draft ... |
Saving and drafts need a layered workspace. Organization templates are stored once per distinct layer, and their storage counts toward your plan's retained storage (see Pricing and limits).