Customize with sketch SDKs

This is the third section of the four-part series; it teaches you to create experimental SDKs quickly using the workshop sketch-sdk command to run local SDK experiments without publishing them. It relies on the knowledge gained in the Get started with workshops section, where you learned how to create and run workshops.

Suppose you built your workshop with a number of SDKs only to realize it still lacks some functionality you need. Naturally, you’d like to add that, but can you align it with the way Workshop operates?

Fortunately, Workshop allows you to quickly draft a local SDK and use it within your workshop. This process is called sketching.

Note

For details on how sketch SDKs are different from regular SDKs, see the Sketch SDK explanation section.

Introduction

We’ll use the following scenario to demonstrate how to iterate on an SDK to add missing functionality.

Suppose you’re running the dev workshop from the Get started with workshops tutorial section, additionally augmented with the jupyter SDK when we discussed Work with interfaces:

workshop.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: ollama
    channel: vulkan/stable
  - name: jupyter
  - name: system
    plugs:
      jupyter:
        interface: tunnel
        endpoint: 127.0.0.1:8989

In our example workshop, this setup allows you to work with AI models using Ollama and Jupyter. But what if the SDKs in your workshop don’t provide some tools? For instance, you may have a HuggingFace SDK without huggingface-cli. Should you create and publish an SDK just for your personal setup? Probably not.

In this guide, we’ll add jupyter-console, an interactive Python environment that can run notebook-style code directly in the terminal. Let’s explore how to integrate this utility into your workshop in a way that aligns with Workshop.

Start sketching

Instead of manually installing tools using workshop shell or workshop exec, you can create a local SDK that automates these tasks with Workshop.

Running workshop sketch-sdk opens a simplified version of an SDK definition. This defines all SDK components in a single file named sdk.yaml:

$ workshop sketch-sdk

The editor presents a minimal setup with empty hooks, plugs, and slots:

sdk.yaml
name: sketch

hooks:
 # ...
plugs:
 # ...
slots:
 # ...

Under hooks, you’ll find a commented setup-project section. It runs as the workshop user after the project directory is mounted and interfaces are connected.

Normally, you use it for commands that access the project files or simply should not run as root, so add the following to install Jupyter Console:

sdk.yaml
name: sketch

hooks:
  setup-project: |
    source /var/lib/workshop/sdk/jupyter/venv/bin/activate
    pip install jupyter-console

This uses the existing Jupyter virtual environment, created by the jupyter SDK to install the jupyter-console package.

Here, the path follows a certain structure: /var/lib/workshop/sdk/ is the location of all SDKs inside a workshop, jupyter/ is the specific SDK name, and venv/ is a directory specific to the SDK.

Once you save and exit sdk.yaml, Workshop refreshes the workshop, running the new hooks:

...
Run hook "setup-project" for "sketch" SDK
...
"dev" sketch refreshed

If errors occur, you can debug the sketch SDK like any other, using workshop changes, workshop tasks, and workshop refresh with --continue or --abort. For help, see this guide.

Note that aborting the refresh does not revert your sketched changes, so you can always restart where you left off by running workshop sketch-sdk again.

After the refresh, the output of workshop info should include something like this:

$ workshop info

  ...
  sketch:
    tracking:   ~/.local/share/workshop/id/6b79e889/dev/sdk/sketch/current
    installed:  2025-08-27  (x1)

The sketch SDK entry shows the last update time and its revision (x1). The SDK is local, so tracking lists the SDK definition path on the host; each edit with workshop sketch-sdk bumps the revision number.

At this point, you’ve created a functional, albeit simple, SDK in minutes. Now you can use Jupyter Console to interactively work with your Ollama models.

Start the Jupyter Console by activating the virtual environment provided by the jupyter SDK and using the jupyter console command enabled by the sketch SDK:

$ workshop shell
workshop@dev-6b79e889:/project$ source /var/lib/workshop/sdk/jupyter/venv/bin/activate
(jupyter-venv) workshop@dev-6b79e889:/project$ jupyter console

  Jupyter console 6.6.3
  ...

This opens an interactive environment where you can experiment with Ollama. Try it out by running some Python code to interact with your models.

Install some dependencies first, as you would normally do with Jupyter:

In [1]: %pip install requests

Then execute the following code to test the Ollama API:

import requests

# Check if Ollama is running
response = requests.get('http://localhost:11434/api/version')
print(f"Ollama version: {response.json()['version']}")

# Generate text with the tinyllama model, installed in Part 1
data = {
    "model": "tinyllama",
    "prompt": "Why is the sky blue?",
    "stream": False
}
response = requests.post('http://localhost:11434/api/generate', json=data)
print(response.json()['response'])

If everything is set up correctly, you should see the Ollama version and a response to the prompt:

Ollama version: 0.9.6

The sky is blue due to its light absorption by the air and water molecules.
The atmosphere contains small amounts of carbon dioxide, which helps absorb
more blue-violet light from the sun. The amount of red light absorbed also
plays a role in determining the color of the sky. The exact combination of
these factors can vary between different regions around the world due to
changes in climate and topography. Additionally, some cultures have myths or
beliefs about what colors are associated with various things, such as green
for growth, blue for water, etc.

Quit the Jupyter console and the workshop shell by pressing Ctrl+D twice.

If you need to make more changes or experiment, just run workshop sketch-sdk again to update your sketch SDK. Repeat this as often as needed until it works the way you want.

Note

The workshop sketch-sdk command opens the SDK definition in your default text editor. To use a specific editor, set the EDITOR environment variable, e.g.:

$ export EDITOR=vim
$ workshop sketch-sdk

Note

For more details on SDK definition components, see the explanation section. You may want to start with SDKs and Interfaces.

Stash and restore

You can temporarily stash the sketch SDK to revert your workshop to its presketching state:

$ workshop sketch-sdk --stash
$ workshop info

To restore the stashed SDK:

$ workshop sketch-sdk --restore

Warning

Stashing does not delete the SDK, allowing you to restore it and continue working later.

However, there’s only one slot available for stashing. Running workshop sketch-sdk overwrites the existing stash, if any. Be cautious to avoid losing your changes.

Explore sketches

You can only have one sketch SDK per workshop at a time; there’s no way to add sketch-foo, sketch-draft, sketch-final-final, and so on. However, a project may contain multiple workshops, each with its own sketch SDK.

To explore the available sketches in your project and their respective states, use the workshop sketches command:

$ workshop sketches

Convert to in-project SDK

If you’re happy with your sketch SDK, your first option is to convert it into an in-project SDK. This makes it a permanent, version-controllable part of your project, shareable with your team; a good step before deciding to publish it to the SDK Store for wider use.

To convert the sketch, you eject it with the --eject option. This creates a new in-project SDK by moving the sketch’s definition files into the .workshop/ subdirectory of your project. The original sketch SDK is removed from the workshop. Workshop can then pull the SDK directly from this directory, bypassing the SDK Store.

By default, the new SDK is named after the project directory; to change this, use the --name option:

$ workshop sketch-sdk --eject --name console

  "dev" sketch ejected to ".workshop/console"
  To use it, add "project-console" to the list of SDKs and run 'workshop refresh dev'

After ejecting, add the new in-project SDK to your workshop definition (usually in workshop.yaml) under the sdks: list, using the project- prefix so Workshop knows it’s an in-project SDK and looks for it in the .workshop/ directory:

sdks:
  - name: project-console

Next, run workshop refresh to apply the change. If everything is set up correctly, it’s time to preserve the changes.

The definition and hooks of the newly ejected console SDK are placed in the .workshop/console/ subdirectory:

.workshop/console/
├── hooks
│   └── setup-project
└── sdk.yaml

If your project did not previously have a .workshop/ directory, add its contents to version control:

$ git add .workshop/
$ git commit -m "Add jupyter-console in-project SDK"

This ensures your in-project SDK is tracked and can be shared with collaborators or CI systems.

Note

For a detailed comparison of in-project SDKs with other SDK types, see the In-project SDKs explanation section.

If you intend to publish a regular SDK, proceed to the next part of the tutorial, Craft SDKs with SDKcraft.

Clean up

If you’re not quite satisfied with your sketching experiments, your second option is to remove the sketch SDK permanently:

$ workshop sketch-sdk --remove

This deletes all changes introduced by the sketch. Also, note that workshop remove removes the sketch SDK, as you could expect, including its stashed version.

Remove a workshop

When you’re done with sketching, the only thing left to cover for local workshops is the cleanup.

If you no longer need your workshop, remove it:

$ workshop remove

This doesn’t affect the files in the project directory, including the workshop definition, or any other content that was stored outside the workshop (e.g., using the mount interface with a custom workshop remount location; however, the content in default mount locations will be deleted).

Even if you remove the workshop completely, you can rebuild it with workshop launch; this may come in handy if you have removed your workshop using the command above before proceeding to the other parts of the tutorial.

Warning

Don’t delete the project directory without first removing the workshop. Otherwise, you’ll need to manually delete the orphaned workshops; for help, see this how-to guide section: Explore LXD containers.

Next steps

This was the last step in this tutorial section; you are now familiar with the essentials of building SDKs in Workshop and have had your first taste of what sketching can achieve.

If you’ve mastered local SDKs, your next step is to start creating publicly available SDKs; proceed to the Craft SDKs with SDKcraft section.