Skip to main content
A template is a single orgo.ai/v1 document, written in YAML or JSON. This page is the field-by-field reference. The canonical machine-readable contract is the JSON Schema at GET /api/template-schema — point your editor at it for autocomplete and inline validation.
# yaml-language-server: $schema=https://www.orgo.ai/api/template-schema

Two forms

Templates accept a canonical form and a shorter sugar form. Both normalize to the same document and the same digest.
api_version: orgo.ai/v1
template:
  name: my-workstation
  version: 1.0.0
hardware:
  cpu: 2
  ram_gb: 4
  resolution: 1280x800x24
env:
  NODE_ENV: production
files:
  - to: /opt/welcome.txt
    inline: "hello"
hooks:
  on_first_boot: |
    echo "ready"

Sugar → canonical

SugarCanonical
name: foo@1.0.0template: { name: foo, version: 1.0.0 }
cpu: 2hardware: { cpu: 2 }
ram: 4gbhardware: { ram_gb: 4 }
display: 1280x800hardware: { resolution: 1280x800x24 }
wallpaper: "https://…"downloads the image and sets it as the desktop background on every boot
files: { /path: "text" }files: [{ to: /path, inline: "text" }]
on_first_boot: |hooks: { on_first_boot: … }

Top-level fields

FieldTypeRequiredDescription
api_versionstringyesMust be orgo.ai/v1.
templateobjectyesIdentity: name, version, description.
hardwareobjectnoVM resource shape.
secretsarraynoVault secrets the template needs.
varsmapnoVariables for ${var.X} interpolation.
envmapnoEnvironment variables, literal or secret-backed.
buildobjectnoBuild-time install steps.
filesarraynoFiles written into the VM.
appsarraynoApps, services, and health checks.
triggersarraynoReactive automation.
terminalarraynoPre-staged tmux sessions.
hooksobjectnoLifecycle shell hooks.
telemetryobjectnoMetrics and logs.
egress_policyobjectnoPer-VM network rules.
streamingarraynoOutbound RTMP streams.

template

Identity and provenance. name and version are required.
template:
  name: claude-code          # lowercase kebab-case, 1-64 chars
  version: 1.0.0             # semver, immutable once published
  description: Claude Code CLI, ready in the terminal.
  publisher: orgo            # optional handle (kebab-case)
  license: MIT               # optional SPDX id (informational)
  homepage: https://…        # optional
  source: https://github.com/…  # optional

hardware

The VM’s resource shape. Every field is optional; sensible defaults apply.
FieldValuesNotes
oslinuxLinux only.
cpu1, 2, 4, 8, 16vCPU count. Capped by your plan.
ram_gb4, 8, 16, 32, 64RAM in GB. Capped by your plan.
disk_gbinteger ≥ 1Disk in GB.
gpunone, t4, l4, a10, l40s, a100-40, a100-80, h100GPU model.
gpu_countinteger ≥ 0Number of GPUs.
resolutionWIDTHxHEIGHTxDEPTHe.g. 1280x720x24.
auto_stop_minutes01440Idle minutes before auto-stop. 0 disables.
regionauto-us, iad, sjc, laxPlacement region.
audiobooleanEnable the audio device. Defaults to false.
bandwidth_mbpsinteger ≥ 0Network bandwidth cap (Mbps).
Hardware in a Create computer request overrides these defaults at launch.

vars and interpolation

vars are compile-time strings, interpolated across the document before build.
vars:
  region: sjc2
  tag: v7

env:
  REGION: "${var.region}"

files:
  - to: /opt/config
    inline: "region=${var.region} tag=${var.tag}"
  • ${var.X} resolves from vars.
  • ${env.X} resolves from a literal env value (not secret-backed ones).
  • $${var.X} escapes to a literal ${var.X}.
  • An unknown reference is a validation error with the exact field path.

env

Environment variables written to the VM. Keys must be UPPER_SNAKE_CASE. Each value is a literal string, or a {secret: <name>} reference resolved from the launching user’s vault at create time.
secrets:
  - name: anthropic_api_key

env:
  NODE_ENV: production
  ANTHROPIC_API_KEY:
    secret: anthropic_api_key
See Secrets for the full secret-injection model.

build

Package and command steps run once when baking the golden snapshot, before app installs. This is where dependencies get pre-installed so launches are instant.
build:
  apt: [ffmpeg, ripgrep]
  pip: [requests, httpx]
  npm: [pnpm]
  run:                      # up to 64 shell commands, in order
    - curl -fsSL https://example.com/install.sh | bash

files

Files materialized into the VM. Each entry sets exactly one of from or inline.
files:
  - to: /opt/hello.txt
    inline: "hello world"

  - to: /usr/share/backgrounds/bg.png
    from: https://example.com/bg.png   # http, https, git, s3, file, or secret://

  - to: /opt/run.sh
    mode: "0755"                        # octal permissions
    inline: |
      #!/bin/bash
      echo hi

  - to: /root/.config/app.json
    from: secret://app_config           # pulled from the vault
    when: runtime                        # build (default) or runtime
FieldDescription
toAbsolute destination path (or ~/…). No .., no reserved system paths.
fromSource URI: file, git, http, https, s3, or secret://<name>.
inlineInline file content.
modeOctal permissions, e.g. "0644".
owner / groupOwnership, resolved against the VM’s /etc/passwd.
whenbuild (baked into the snapshot) or runtime (re-applied each boot).
to must be an absolute path with no ... Reserved system paths are rejected: /proc, /sys, /boot, /dev, /tmp, /run, plus the Orgo runtime (/etc/orgo, /var/orgo, /orgo, /etc/supervisor, and Orgo’s own binaries under /opt and /usr/local/sbin). Your apps can still write under /opt and elsewhere — only Orgo’s own runtime files are off-limits.

apps

An app bundles an install step with the long-running services, health checks, and ports it needs. Services are managed by supervisord, so they start at boot and respawn on crash.
apps:
  - name: my-app
    title: "My Application"
    install: |
      npm install -g my-app
    services:
      - name: my-app-server
        run: "my-app serve --port 8000"
        cwd: /opt/my-app
        user: root            # default: orgo (unprivileged)
        restart: always       # always | on-failure | no
        env:
          PORT: "8000"
    health:
      type: http              # http | tcp | command | process
      url: http://127.0.0.1:8000/health
      every: 15s
      timeout: 3s
      retries: 3
      on_fail: restart_service:my-app-server
    ports:
      - { internal: 8000, public: true }
    autostart:
      - { run: "firefox http://localhost:8000", delay: 3 }

services

FieldDescription
nameUnique service name (kebab-case). Required.
runThe long-lived command. Required.
cwd / user / envWorking directory, run-as user, and extra environment variables for this service.
restartalways (default), on-failure, or no.
stop_signal / logStop signal (e.g. TERM) and log file path.

health

A polled liveness check. After retries consecutive failures, on_fail runs — this is the per-app watchdog.
typeChecks
httpurl returns 2xx/3xx
tcpport accepts a connection
commandcommand exits 0
processprocess name is running
on_fail is one of restart_service:<name>, restart_vm, alert, or none.

ports

FieldDescription
internalIn-VM port (1–65535). 5900, 5999, 6080, 8080 are reserved. Required.
externalExternally mapped port (0 = none).
protocoltcp, udp, http, or ws.
publicExpose publicly. When true, the host port is returned in the computer’s template_ports.

terminal

Pre-staged tmux sessions, created detached at first boot. Orgo’s browser terminal attaches to them by name.
terminal:
  - name: logs
    title: "Service Logs"
    cwd: /opt/my-app
    run: "tail -F /var/log/orgo/my-app.log"
Sessions are not auto-restarted. For a process that must respawn, use an app service instead.

hooks

Shell that runs at lifecycle points. Each runs with set -e; the default timeout is 10 minutes.
HookWhen
on_first_bootOnce, on the VM’s first boot.
on_every_bootEvery boot, including restores.
on_pre_snapshotBefore a golden snapshot is captured.
on_resumeAfter restoring from a snapshot.
on_shutdownOn graceful shutdown.
hooks:
  on_first_boot: |
    echo "ready" > /var/lib/orgo/stamp
  on_resume: |
    echo "restored at $(date)"
on_resume is the right place to do per-VM work that depends on launch-time state (like a freshly injected secret), because it runs on every restore — see Secrets.

telemetry

telemetry:
  metrics: true               # flag the VM as scrape-ready
  logs: [my-app-server]       # service log paths/names to ship
  otel_endpoint: https://otel.example.com   # push OTLP metrics + logs

egress_policy

Per-VM network filtering, enforced on the host.
egress_policy:
  mode: allow                 # allow = only these reachable; block = everything except these
  rules:
    - "*.github.com"
    - "api.anthropic.com"
    - "10.0.0.0/8"
Rules are domain patterns, exact domains, IPs, or CIDRs. The VNC and desktop API paths are always reachable.

streaming

Outbound RTMP(S) streams of the desktop.
streaming:
  - name: live
    url: rtmps://ingest.example.com/app
    key:
      secret: stream_key       # literal string or a vault secret
    autostart: true
streaming is parsed and validated today; the runtime streamer is rolling out. Track status in the JSON Schema.

Next steps

Secrets

The full secret-injection model.

Triggers

Sources, actions, and dedup.

Examples

Annotated real templates.

Publish API

Ship a template over HTTP.