<a id="ref-sdk-definition"></a>

# SDK definition

<!-- @artefact 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](https://ubuntu.com/workshop/docs//reference/definition-files/sdkcraft-definition.md#ref-sdkcraft-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

<!-- @artefact SDK definition file -->
- 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<br/>and may consist of lowercase letters, digits, and hyphens between them.<br/>Up to 40 characters.<br/>Cannot be `agent`, `system`, `sketch`,<br/>or start with `try-` or `project-`; those names are reserved. |
| `architecture` (required for built SDKs)        | string                | CPU architecture the SDK is built for,<br/>following [Debian’s naming scheme](https://www.debian.org/ports/)<br/>(for example, `amd64`, `arm64`).<br/>Use `all` for SDKs that ship no compiled binaries.                                                                     |
| `version` (required for built SDKs)             | string                | SDK version. Semantic versioning is recommended.<br/><br/>#### NOTE<br/>Quote version strings in YAML when they look numeric<br/>(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.<br/>Set automatically; do not edit by hand.                                                                                                                                                                       |
| `base`                                          | string                | Base operating system image the SDK targets.<br/>One of `ubuntu@20.04`, `ubuntu@22.04`, `ubuntu@24.04`,<br/>or `ubuntu@26.04`.<br/>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.<br/><br/>#### NOTE<br/>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.<br/>Each key is the plug name; each value is an inline plug definition.<br/>See [Interfaces](#ref-sdk-definition-interfaces).                                                                                          |
| `slots`                                         | object                | Slots the SDK provides.<br/>Each key is the slot name;<br/>each value is an inline slot definition.<br/>Only the `mount` and `tunnel` interfaces<br/>support slots on regular SDKs.<br/>See [Interfaces](#ref-sdk-definition-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`).

<a id="ref-sdk-definition-interfaces"></a>

## Interfaces

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

<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### Camera interface

<!-- @artefact 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.

<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### Custom device interface

<!-- @artefact 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:

<!-- @artefact custom-device interface attributes -->

| Key                    | Value   | Description                                                                                         |
|------------------------|---------|-----------------------------------------------------------------------------------------------------|
| `subsystem` (required) | string  | The Linux kernel subsystem of the host devices to expose,<br/>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.

<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### Desktop interface

<!-- @artefact 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.

<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### GPU interface

<!-- @artefact 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.

<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### Mount interface

<!-- @artefact mount interface -->
<!-- @artefact $SDK -->

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.<br/>Must be an absolute path;<br/>`$SDK` expands to the SDK’s installation path in the workshop.                                                                          |
| `mode`                       | integer | File permissions, in octal, applied when creating `workshop-target`<br/>and any missing parent directories.<br/>Defaults to `0o775` for regular users.<br/>When `uid` is zero, defaults to `0o755`.                                     |
| `uid`                        | integer | User ID applied when creating `workshop-target`<br/>and any missing parent directories.<br/>Defaults to `1000` when `workshop-target` is under<br/>`/home/workshop/`, `/project/`, or `/run/user/1000/`.<br/>Defaults to `0` otherwise. |
| `gid`                        | integer | Group ID applied when creating `workshop-target`<br/>and any missing parent directories.<br/>Defaults to `1000` or `0`<br/>by the same path rule as `uid`,<br/>even when `uid` is set explicitly.                                       |
| `read-only`                  | Boolean | Whether the target directory should be read-only.<br/>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](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-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.<br/>Must be an absolute path;<br/>`$SDK` expands to the SDK’s installation path in the workshop. |
<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### SSH interface

<!-- @artefact 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.

<!-- Single-sourced snippet. Included by workshop-definition.rst,
sdk-definition.rst, and sdkcraft-definition.rst.
Do not add a top-level label; the including page provides the anchor. -->

### Tunnel interface

<!-- @artefact 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.<br/>Defaults to `localhost/tcp` for both plugs and slots. |

The `endpoint` value follows this grammar:

| Field    | Format                                                                                                                                                                                                                                                                                                        |
|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Endpoint | `<ADDRESS>/<PROTOCOL>` for network endpoints;<br/>may be shortened to `<ADDRESS>` or `<PROTOCOL>` alone.<br/><br/>`<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.<br/>When a port is supplied, IPv6 addresses must be enclosed in square brackets.<br/><br/>Supported aliases: `localhost`, `ip6-localhost`, and `ip6-loopback`.<br/>Defaults to `localhost`.                                                                                          |
| Port     | A TCP or UDP port number (1-65535).<br/>May be omitted, but only on one side of a connection; both sides then use the same port.<br/><br/>For security, tunnel plugs in the system SDK cannot use privileged ports (1-1023).                                                                                  |
| Path     | Absolute path to a Unix domain socket.<br/><br/>`$HOME` expands to the user’s home directory<br/>and `$XDG_RUNTIME_DIR` expands to the user runtime directory<br/>(typically `/run/user/1000`).<br/><br/>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:

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

## JSON Schema

<!-- @artefact SDK 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

```json
{
  "$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:

```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:

```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:

- [In-project SDKs](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-in-project-sdk)
- [SDK concepts](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-sdk-concepts)
- [SDK definition](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-sdk-definition)
- [System SDK](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-system-sdk)

Reference:

- [SDK internals](https://ubuntu.com/workshop/docs//reference/sdks.md#ref-sdk-internals)
- [SDKcraft project definition](https://ubuntu.com/workshop/docs//reference/definition-files/sdkcraft-definition.md#ref-sdkcraft-definition)
- [Workshop definition](https://ubuntu.com/workshop/docs//reference/definition-files/workshop-definition.md#ref-workshop-definition)

Tutorial:

- [Customize with sketch SDKs](https://ubuntu.com/workshop/docs//tutorial/part-3-sketch-sdks.md#tut-sketch-sdks)
