SDK definition

The sdk.yaml file is the runtime SDK definition: Workshop reads it when it installs an SDK in a workshop. For Store SDKs and SDKs from sdkcraft try, this file is produced by SDKcraft from sdkcraft.yaml (see SDKcraft project definition). For sketch SDKs and in-project SDKs, you author sdk.yaml directly: sketch SDKs through workshop sketch-sdk, in-project SDKs by hand under .workshop/.

Filename and location

  • Store SDKs and SDKs from sdkcraft try ship sdk.yaml inside their packed contents at meta/sdk.yaml.

  • In-project SDKs use .workshop/<NAME>/sdk.yaml or .workshop/<NAME>/meta/sdk.yaml, relative to the project directory. Their hook scripts live next to the definition, under .workshop/<NAME>/hooks/.

  • Sketch SDK definitions live in the per-workshop data directory: ~/.local/share/workshop/id/<PROJECT-ID>/<WORKSHOP>/sdk/sketch/current/sdk.yaml.

In-project and sketch SDKs do not support SDKcraft build-time features such as build-base, platforms, or parts. These belong to sdkcraft.yaml.

Top-level fields

Key

Value

Description

name (required)

string

SDK identifier. Must contain at least one lowercase letter and may consist of lowercase letters, digits, and hyphens between them. Up to 40 characters. Cannot be agent, system, sketch, or start with try- or project-; those names are reserved.

architecture (required for built SDKs)

string

CPU architecture the SDK is built for, following Debian’s naming scheme (for example, amd64, arm64). Use all for SDKs that ship no compiled binaries.

version (required for built SDKs)

string

SDK version. Semantic versioning is recommended.

Note

Quote version strings in YAML when they look numeric (for example, version: "1.0") to avoid type coercion.

summary (required for built SDKs)

string

One-line summary, up to 78 characters.

description (required for built SDKs)

string

Longer free-form description, up to about a hundred words.

sdkcraft-started-at (required for built SDKs)

string

UTC timestamp marking when SDKcraft started the build. Set automatically; do not edit by hand.

base

string

Base operating system image the SDK targets. One of ubuntu@20.04, ubuntu@22.04, ubuntu@24.04, or ubuntu@26.04. Omit for SDKs that work on any supported base.

title

string

Human-readable title.

license

string

License name, as it would appear in package metadata.

Note

Match the license to the actual components the SDK installs.

contact

string, array, or URL

Contact information for the SDK publisher.

issues

string, array, or URL

Where users should report problems with the SDK.

source-code

URL

Where the SDK’s source code is hosted.

website

URL

The web page for the SDK.

plugs

object

Plugs the SDK requests from the workshop environment. Each key is the plug name; each value is an inline plug definition. See Interfaces.

slots

object

Slots the SDK provides. Each key is the slot name; each value is an inline slot definition. Only the mount and tunnel interfaces support slots on regular SDKs. See Interfaces.

Note

“Required for built SDKs” means SDKcraft writes the field when it builds an SDK package; for an in-project SDK, you can author sdk.yaml with only name, plus whichever optional fields you need. In particular, architecture for in-project SDKs is assumed to match the host (or all).

Interfaces

A plug or slot value is an inline definition: a mapping that specifies the interface and any interface-specific attributes.

Camera interface

The camera interface exposes a host camera device.

  • Plug attributes: none.

  • Plug name: must be camera.

  • Plug owner: any regular SDK; not the system SDK.

  • Slot: the system SDK provides a single system:camera slot. Other SDKs cannot declare camera slots.

Custom device interface

The custom device interface exposes host devices that belong to a Linux kernel subsystem.

A custom device plug is described by this attribute:

Key

Value

Description

subsystem (required)

string

The Linux kernel subsystem of the host devices to expose, for example input, tty, or usb.

Plug owner: any regular SDK; not the system SDK.

Slot: the system SDK provides a single system:custom-device slot. Other SDKs cannot declare custom device slots.

Desktop interface

The desktop interface exposes the host display server.

  • Plug attributes: none.

  • Plug name: must be desktop.

  • Plug owner: any regular SDK; not the system SDK.

  • Slot: the system SDK provides a single system:desktop slot. Other SDKs cannot declare desktop slots.

GPU interface

The GPU interface exposes host GPU devices.

  • Plug attributes: none.

  • Plug name: must be gpu.

  • Plug owner: any regular SDK; not the system SDK.

  • Slot: the system SDK provides a single system:gpu slot. Other SDKs cannot declare GPU slots.

Mount interface

The mount interface exposes a directory between a slot owner and a plug owner.

A mount plug is described by these attributes:

Key

Value

Description

workshop-target (required)

string

Path inside the workshop used as the plug’s target directory. Must be an absolute path; $SDK expands to the SDK’s installation path in the workshop.

mode

integer

File permissions, in octal, applied when creating workshop-target and any missing parent directories. Defaults to 0o775 for regular users. When uid is zero, defaults to 0o755.

uid

integer

User ID applied when creating workshop-target and any missing parent directories. Defaults to 1000 when workshop-target is under /home/workshop/, /project/, or /run/user/1000/. Defaults to 0 otherwise.

gid

integer

Group ID applied when creating workshop-target and any missing parent directories. Defaults to 1000 or 0 by the same path rule as uid, even when uid is set explicitly.

read-only

Boolean

Whether the target directory should be read-only. Defaults to false.

Plug owner: any regular SDK; not the system SDK.

The system SDK provides one mount slot, system:mount, with a dynamic host-source attribute that can be configured only at remount. It is the only mount slot whose source is on the host filesystem.

A mount slot on a regular SDK is described by this attribute:

Key

Value

Description

workshop-source (required)

string

Path inside the workshop used as the slot’s source directory. Must be an absolute path; $SDK expands to the SDK’s installation path in the workshop.

SSH interface

The SSH interface exposes the user’s SSH agent socket.

  • Plug attributes: none.

  • Plug name: must be ssh-agent.

  • Plug owner: any regular SDK; not the system SDK.

  • Slot: the system SDK provides a single system:ssh-agent slot. Other SDKs cannot declare SSH slots.

Tunnel interface

The tunnel interface forwards a network address or Unix domain socket.

Both tunnel plugs and tunnel slots take a single attribute:

Key

Value

Description

endpoint

string

Network address or Unix domain socket that forms one end of the tunnel. Defaults to localhost/tcp for both plugs and slots.

The endpoint value follows this grammar:

Field

Format

Endpoint

<ADDRESS>/<PROTOCOL> for network endpoints; may be shortened to <ADDRESS> or <PROTOCOL> alone.

<PATH> or @<STRING> for Unix domain sockets.

Address

<HOST>:<PORT>; may be shortened to <HOST> or <PORT>.

Protocol

Either tcp or udp. Defaults to tcp.

Host

An IPv4 or IPv6 address. When a port is supplied, IPv6 addresses must be enclosed in square brackets.

Supported aliases: localhost, ip6-localhost, and ip6-loopback. Defaults to localhost.

Port

A TCP or UDP port number (1-65535). May be omitted, but only on one side of a connection; both sides then use the same port.

For security, tunnel plugs in the system SDK cannot use privileged ports (1-1023).

Path

Absolute path to a Unix domain socket.

$HOME expands to the user’s home directory and $XDG_RUNTIME_DIR expands to the user runtime directory (typically /run/user/1000).

For security, tunnel plugs in the system SDK cannot listen on sockets outside these two directories.

String

An abstract socket name.

Endpoints that start with [ or @ must be quoted in YAML:

endpoint: '[::1]:8080/tcp'
endpoint: '@abstract.sock'

JSON Schema

The following JSON Schema is exported from SDKcraft’s runtime metadata model and describes the structure above:

Note

The schema describes a built sdk.yaml, that is, the file SDKcraft writes when it packs an SDK. The required list reflects what a packed SDK must carry; for an in-project sdk.yaml you author by hand, only name is mandatory (see the note below the table).

Numeric bounds use pydantic-style ge, le, and lt keywords. Generic JSON Schema validators will not enforce them; treat the bounds as documentation of the runtime’s accepted ranges, and rely on the field table above for the authoritative rules.

SDK definition schema
{
  "$defs": {
    "CameraPlug": {
      "additionalProperties": false,
      "description": "SDKcraft project camera plug definition.",
      "properties": {
        "interface": {
          "const": "camera",
          "title": "Interface",
          "type": "string"
        }
      },
      "required": [
        "interface"
      ],
      "title": "CameraPlug",
      "type": "object"
    },
    "CleanAbsPath": {
      "type": "string"
    },
    "CustomDevicePlug": {
      "additionalProperties": false,
      "description": "SDKcraft project custom-device plug definition.",
      "properties": {
        "interface": {
          "const": "custom-device",
          "title": "Interface",
          "type": "string"
        },
        "subsystem": {
          "description": "Device subsystem.",
          "examples": [
            "accel",
            "usb"
          ],
          "minLength": 1,
          "title": "Subsystem",
          "type": "string"
        }
      },
      "required": [
        "interface",
        "subsystem"
      ],
      "title": "CustomDevicePlug",
      "type": "object"
    },
    "DesktopPlug": {
      "additionalProperties": false,
      "description": "SDKcraft project desktop plug definition.",
      "properties": {
        "interface": {
          "const": "desktop",
          "title": "Interface",
          "type": "string"
        }
      },
      "required": [
        "interface"
      ],
      "title": "DesktopPlug",
      "type": "object"
    },
    "Endpoint": {
      "type": "string"
    },
    "FileMode": {
      "$ref": "#/$defs/Int",
      "ge": 0,
      "le": 511
    },
    "GPUPlug": {
      "additionalProperties": false,
      "description": "SDKcraft project GPU plug definition.",
      "properties": {
        "interface": {
          "const": "gpu",
          "title": "Interface",
          "type": "string"
        }
      },
      "required": [
        "interface"
      ],
      "title": "GPUPlug",
      "type": "object"
    },
    "Int": {
      "type": "integer"
    },
    "MountPlug": {
      "additionalProperties": false,
      "description": "SDKcraft project mount plug definition.",
      "properties": {
        "interface": {
          "const": "mount",
          "title": "Interface",
          "type": "string"
        },
        "workshop-target": {
          "$ref": "#/$defs/CleanAbsPath"
        },
        "uid": {
          "$ref": "#/$defs/UserGroupID"
        },
        "gid": {
          "$ref": "#/$defs/UserGroupID"
        },
        "mode": {
          "$ref": "#/$defs/FileMode"
        },
        "read-only": {
          "default": false,
          "title": "Read-Only",
          "type": "boolean"
        }
      },
      "required": [
        "interface",
        "workshop-target"
      ],
      "title": "MountPlug",
      "type": "object"
    },
    "MountSlot": {
      "additionalProperties": false,
      "description": "SDKcraft project mount slot definition.",
      "properties": {
        "interface": {
          "const": "mount",
          "title": "Interface",
          "type": "string"
        },
        "workshop-source": {
          "$ref": "#/$defs/CleanAbsPath"
        }
      },
      "required": [
        "interface",
        "workshop-source"
      ],
      "title": "MountSlot",
      "type": "object"
    },
    "Plug": {
      "discriminator": {
        "mapping": {
          "camera": "#/$defs/CameraPlug",
          "custom-device": "#/$defs/CustomDevicePlug",
          "desktop": "#/$defs/DesktopPlug",
          "gpu": "#/$defs/GPUPlug",
          "mount": "#/$defs/MountPlug",
          "ssh-agent": "#/$defs/SSHAgentPlug",
          "tunnel": "#/$defs/TunnelPlug"
        },
        "propertyName": "interface"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/CameraPlug"
        },
        {
          "$ref": "#/$defs/CustomDevicePlug"
        },
        {
          "$ref": "#/$defs/DesktopPlug"
        },
        {
          "$ref": "#/$defs/GPUPlug"
        },
        {
          "$ref": "#/$defs/MountPlug"
        },
        {
          "$ref": "#/$defs/SSHAgentPlug"
        },
        {
          "$ref": "#/$defs/TunnelPlug"
        }
      ]
    },
    "PlugName": {
      "description": "The name of the plug. This is used when connecting and disconnecting.\n\nThe plug name must consist only of lower-case ASCII letters (``a-z``), numerals\n(``0-9``), and hyphens (``-``). It must start with a letter, not end with a\nhyphen, and not contain two consecutive hyphens.\n",
      "examples": [
        "desktop",
        "gpu",
        "ssh-agent"
      ],
      "pattern": "^[a-z](-?[a-z0-9])*$",
      "title": "Plug Name",
      "type": "string"
    },
    "Plugs": {
      "additionalProperties": {
        "$ref": "#/$defs/Plug"
      },
      "propertyNames": {
        "$ref": "#/$defs/PlugName"
      },
      "type": "object"
    },
    "ProjectName": {
      "description": "The name of the project. This is used when uploading, publishing, or installing.\n\nThe project name must consist only of lower-case ASCII letters (``a``-``z``), numerals\n(``0``-``9``), and hyphens (``-``). It must contain at least one letter, not start or\nend with a hyphen, and not contain two consecutive hyphens. The maximum length is 40\ncharacters.\n",
      "examples": [
        "ubuntu",
        "jupyterlab-desktop",
        "lxd",
        "digikam",
        "kafka",
        "mysql-router-k8s"
      ],
      "maxLength": 40,
      "minLength": 1,
      "pattern": "(?!^(system|try-.*|project-.*|sketch)$)^([a-z0-9][a-z0-9-]?)*[a-z]+([a-z0-9-]?[a-z0-9])*$",
      "title": "Project Name",
      "type": "string"
    },
    "SSHAgentPlug": {
      "additionalProperties": false,
      "description": "SDKcraft project SSH agent plug definition.",
      "properties": {
        "interface": {
          "const": "ssh-agent",
          "title": "Interface",
          "type": "string"
        }
      },
      "required": [
        "interface"
      ],
      "title": "SSHAgentPlug",
      "type": "object"
    },
    "Slot": {
      "discriminator": {
        "mapping": {
          "mount": "#/$defs/MountSlot",
          "tunnel": "#/$defs/TunnelSlot"
        },
        "propertyName": "interface"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/MountSlot"
        },
        {
          "$ref": "#/$defs/TunnelSlot"
        }
      ]
    },
    "SlotName": {
      "description": "The name of the slot. This is used when connecting and disconnecting.\n\nThe slot name must consist only of lower-case ASCII letters (``a-z``), numerals\n(``0-9``), and hyphens (``-``). It must start with a letter, not end with a\nhyphen, and not contain two consecutive hyphens.\n",
      "examples": [
        "dashboard",
        "gdb",
        "toolchain"
      ],
      "pattern": "^[a-z](-?[a-z0-9])*$",
      "title": "Slot Name",
      "type": "string"
    },
    "Slots": {
      "additionalProperties": {
        "$ref": "#/$defs/Slot"
      },
      "propertyNames": {
        "$ref": "#/$defs/SlotName"
      },
      "type": "object"
    },
    "TunnelPlug": {
      "additionalProperties": false,
      "description": "SDKcraft project tunnel plug definition.",
      "properties": {
        "interface": {
          "const": "tunnel",
          "title": "Interface",
          "type": "string"
        },
        "endpoint": {
          "$ref": "#/$defs/Endpoint",
          "default": ""
        }
      },
      "required": [
        "interface"
      ],
      "title": "TunnelPlug",
      "type": "object"
    },
    "TunnelSlot": {
      "additionalProperties": false,
      "description": "SDKcraft project tunnel plug definition.",
      "properties": {
        "interface": {
          "const": "tunnel",
          "title": "Interface",
          "type": "string"
        },
        "endpoint": {
          "$ref": "#/$defs/Endpoint",
          "default": ""
        }
      },
      "required": [
        "interface"
      ],
      "title": "TunnelSlot",
      "type": "object"
    },
    "UserGroupID": {
      "$ref": "#/$defs/Int",
      "ge": 0,
      "lt": 4294967295
    }
  },
  "additionalProperties": true,
  "description": "Structure to hold output metadata.",
  "properties": {
    "name": {
      "$ref": "#/$defs/ProjectName"
    },
    "title": {
      "anyOf": [
        {
          "description": "A human-readable title.",
          "examples": [
            "Ubuntu Linux",
            "Jupyter Lab Desktop",
            "LXD",
            "DigiKam",
            "Apache Kafka",
            "MySQL Router K8s charm"
          ],
          "maxLength": 40,
          "minLength": 2,
          "title": "Title",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Title"
    },
    "version": {
      "description": "The version of the project, enclosed in quotation marks.",
      "examples": [
        "\"0.1\"",
        "\"1.0.0\"",
        "\"v1.0.0\"",
        "\"24.04\""
      ],
      "maxLength": 32,
      "title": "version string",
      "type": "string"
    },
    "summary": {
      "description": "A short description of the project. Maximum length 78 characters.",
      "examples": [
        "Linux for Human Beings",
        "The cross-platform desktop application for JupyterLab",
        "Container and VM manager",
        "Photo Management Program",
        "Charm for routing MySQL databases in Kubernetes",
        "An open-source event streaming platform for high-performance data pipelines"
      ],
      "maxLength": 78,
      "title": "Summary",
      "type": "string"
    },
    "description": {
      "title": "Description",
      "type": "string"
    },
    "base": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Base"
    },
    "architecture": {
      "title": "Architecture",
      "type": "string"
    },
    "contact": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array",
          "uniqueItems": true
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Contact"
    },
    "issues": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array",
          "uniqueItems": true
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Issues"
    },
    "source-code": {
      "anyOf": [
        {
          "format": "uri",
          "minLength": 1,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Source-Code"
    },
    "license": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "License"
    },
    "plugs": {
      "$ref": "#/$defs/Plugs",
      "default": {}
    },
    "slots": {
      "$ref": "#/$defs/Slots",
      "default": {}
    },
    "sdkcraft-started-at": {
      "title": "Sdkcraft-Started-At",
      "type": "string"
    }
  },
  "required": [
    "name",
    "version",
    "summary",
    "description",
    "architecture",
    "sdkcraft-started-at"
  ],
  "title": "Metadata",
  "type": "object"
}

Examples

In-project SDK that declares a mount plug:

.workshop/ccache/sdk.yaml
name: ccache
version: "0.1"
summary: Shared ccache
description: |
  Project-specific SDK that exposes a mount target
  for preserving cache across workshop updates.
plugs:
  ccache:
    interface: mount
    workshop-target: /home/workshop/.cache/ccache

Runtime sdk.yaml written by SDKcraft for a Go development SDK:

meta/sdk.yaml
name: go
title: Go SDK
version: "1.25.1"
summary: The Go programming language
description: |
  Go is an open source programming language that enables the production of simple,
  efficient and reliable software at scale.
base: ubuntu@24.04
architecture: amd64
license: LGPL-2.1
sdkcraft-started-at: "2026-04-12T08:30:00Z"
plugs:
  mod-cache:
    interface: mount
    workshop-target: /home/workshop/go/pkg/mod

See also

Explanation:

Reference:

Tutorial: