SpinneryDocs
Browse documentation

Configuration reference

spinnery.yml reference

New services normally use a root spinnery.yml. A service connected with a custom config path uses the same schema. Keep runtime facts in Docker Compose and add only the Spinnery-specific contract here.

Version 1

Complete example

This example shows every common capability. Start from the smallest file you need and add fields only when repository evidence supports them.

spinnery.yml
version: 1

compose:
  file: docker-compose.yml
  previews:
    - service: web
      port: 5173
      hmr: true

default_preview: web

inputs:
  api_url:
    required: true
    description: URL exposed by the API service

outputs:
  app_url:
    from: service.url

environment:
  VITE_API_URL:
    from: input.api_url
  APP_KEY:
    secret: app-key
  VITE_APP_ENV:
    value: development

setup:
  install:
    - npm install

tests:
  unit:
    - npm test

cli:
  seed:
    command: npm run seed
    description: Seed development data

Top-level fields

FieldStatusPurpose
versionrequiredInteger 1.
composerequiredCompose file and optional browser previews.
default_previewoptionalPrimary preview service when more than one is declared.
serviceoptionalService metadata for manifests that explicitly own their identity.
inputsoptionalValues this repository needs from another selected service or project binding.
outputsoptionalNamed values this repository makes available to other services.
environmentoptionalLiteral values, runtime references, or secret names mapped to environment variables.
setupoptionalNamed groups of evidence-backed setup commands.
testsoptionalNamed groups of evidence-backed test commands.
clioptionalRepository-specific cloud CLI entrypoints used by spin cli and spin x.

Service metadata

Most connected services omit service because Spinnery already owns their name and type. When present, it is a mapping that requires non-empty name and type strings. storage_mode is optional and accepts shared_fs or local_mirror. Additional scalar metadata is preserved.

compose and previews

compose is required. compose.file is an optional non-empty repository-relative path and defaults to docker-compose.yml. Each preview accepts:

  • service — a unique, non-empty Compose service name.
  • port — a container port from 1 through 65535.
  • hmr — an optional YAML boolean; defaults to false.

default_preview is optional; when present, it must name a declared preview. Spinnery infers the default when exactly one preview exists. With multiple previews, declare it so the bare preview URL and service.url point to the intended primary app.

Inputs and outputs

Inputs declare what this repository needs. Outputs publish values produced by this repository. Matching names provide the automatic path between selected workspace services.

Provider repository
version: 1

compose:
  previews:
    - service: api
      port: 8080

default_preview: api

outputs:
  api_url:
    from: service.url
Consumer repository
version: 1

compose:
  previews:
    - service: web
      port: 5173
      hmr: true

default_preview: web

inputs:
  api_url:
    required: true

environment:
  VITE_API_URL:
    from: input.api_url

An input may be true for required, false or null for optional, or a mapping with required, description, and default_value. The older default spelling remains a compatibility alias; prefer default_value. An output is a reference string or a mapping with from and an optional description.

Runtime references

Reference strings resolve from the current workspace service:

  • input.<name> reads a declared input.
  • service.name, service.slug, service.url, and service.internal_url describe the current service.
  • service.port.http and service.port.hmr expose its assigned runtime ports.
  • workspace.id, workspace.name, workspace.slug, and workspace.url_base describe the current workspace.
  • resource.<type>.<output> reads an available project resource output.

Cross-repository references such as services.api.url or service.api.url are not supported. Declare an input and connect it to a same-name output or an explicit project binding.

Environment and secrets

An environment entry may be a scalar or null literal shorthand. The mapping form must define exactly one source:

  • value for a scalar literal or null.
  • from for a runtime reference such as input.api_url, service.url, or an available resource.* value.
  • secret for the name of a Spinnery-managed secret. Secrets are required by default; add required: false only for an integration the service can run without.

Configure documented development defaults explicitly. If a checked-in local mode disables a production integration, use that safe mode and omit its unused credentials. Do not invent a bypass or infer that a variable is required merely because source code or an example template mentions it.

Never put a secret value in the manifest.

Reference the secret by name. Do not copy credentials from untracked .env files, private keys, or local credential files.

Setup, tests, and CLI commands

setup and tests map group names to one command or a list of commands. cli entries accept a command string or a mapping with command and an optional description. Select an entry with spin cli, then invoke it against the active workspace service with spin x. Add commands only when checked-in repository files prove them.

Rejected fields and references

Top-level ports, start, health, and resources are retired. Keep ports, commands, and health checks in Docker Compose. Configure managed resources and their bindings at the project level, then consume their available outputs through resource.*. A depends_on key is rejected anywhere, as are direct cross-repository service references.

Validation

Terminal
spin validate
spin validate ./path/to/repository
spin validate ./spinnery.yml --json

The validator requires Docker Compose v2 and runs docker compose config --services with a 30-second limit. It exits nonzero for malformed manifests, missing Compose files, unknown preview services, and undeclared input.* references.