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.yamlinside their packed contents atmeta/sdk.yaml.In-project SDKs use
.workshop/<NAME>/sdk.yamlor.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 |
|---|---|---|
|
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 |
|
string |
CPU architecture the SDK is built for,
following Debian’s naming scheme
(for example, |
|
string |
SDK version. Semantic versioning is recommended. Note Quote version strings in YAML when they look numeric
(for example, |
|
string |
One-line summary, up to 78 characters. |
|
string |
Longer free-form description, up to about a hundred words. |
|
string |
UTC timestamp marking when SDKcraft started the build. Set automatically; do not edit by hand. |
|
string |
Base operating system image the SDK targets.
One of |
|
string |
Human-readable title. |
|
string |
License name, as it would appear in package metadata. Note Match the license to the actual components the SDK installs. |
|
string, array, or URL |
Contact information for the SDK publisher. |
|
string, array, or URL |
Where users should report problems with the SDK. |
|
URL |
Where the SDK’s source code is hosted. |
|
URL |
The web page for the SDK. |
|
object |
Plugs the SDK requests from the workshop environment. Each key is the plug name; each value is an inline plug definition. See Interfaces. |
|
object |
Slots the SDK provides.
Each key is the slot name;
each value is an inline slot definition.
Only the |
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:cameraslot. 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 |
|---|---|---|
|
string |
The Linux kernel subsystem of the host devices to expose,
for example |
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:desktopslot. 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:gpuslot. 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 |
|---|---|---|
|
string |
Path inside the workshop used as the plug’s target directory.
Must be an absolute path;
|
|
integer |
File permissions, in octal, applied when creating |
|
integer |
User ID applied when creating |
|
integer |
Group ID applied when creating |
|
Boolean |
Whether the target directory should be read-only.
Defaults to |
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 |
|---|---|---|
|
string |
Path inside the workshop used as the slot’s source directory.
Must be an absolute path;
|
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-agentslot. 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 |
|---|---|---|
|
string |
Network address or Unix domain socket that forms one end of the tunnel.
Defaults to |
The endpoint value follows this grammar:
Field |
Format |
|---|---|
Endpoint |
|
Address |
|
Protocol |
Either |
Host |
An IPv4 or IPv6 address. When a port is supplied, IPv6 addresses must be enclosed in square brackets. Supported aliases: |
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.
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:
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:
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: