Developing a Podman Desktop extension
Podman Desktop is organized so that you can modularly add new functionality in the form of "extensions" as well as the corresponding extension-api. This allows you to communicate with Podman Desktop without having to know the internal workings. You look for the API call and Podman Desktop will do the rest.
It is recommended that an extension be written in TypeScript for type checking, but extensions can be written in JavaScript.
Most extensions are externally loaded; however, we also dogfood our own API by loading them as internal extensions that use the same API. These internally maintained extensions can be used as an example and basis for how to build an externally loaded extension.
Overview of creating a new extension
We try to simplify extension creation as much as possible by utilizing package.json and by keeping activations simple within the extension, providing only two entrypoints: activate() and deactivate().
All Podman Desktop functionalities are communicated entirely through the API. The extension you create interacts with the Podman Desktop API through the @podman-desktop/api package. The API code is located here, while the website representation of the code can be found here.
Activating
When activating an extension, Podman Desktop will:
- Search and load the
JavaScriptfile specified inmainentry of thepackage.jsonfile in the extension directory (typicallyextension.js). - Run the exported
activatefunction.
Deactivating
When deactivating an extension, Podman Desktop will:
- Run the optionally exported
deactivatefunction. - Dispose of any resources that have been added to
extensionContext.subscriptions, seedeactivateExtensionin extension-loader.ts.
Example boilerplate code
This is an example extensions/foobar/src/extensions.ts file with the basic activate and deactivate functionalities, provided that you already have a package.json created as well:
import * as extensionApi from '@podman-desktop/api';
// Activate the extension asynchronously
export async function activate(extensionContext: extensionApi.ExtensionContext): Promise<void> {
// Create a provider with an example name, ID and icon
const provider = extensionApi.provider.createProvider({
name: 'FooBar',
id: 'foobar',
status: 'unknown',
images: {
icon: './icon.png',
logo: './icon.png',
},
});
// Push the new provider to Podman Desktop
extensionContext.subscriptions.push(provider);
}
// Deactivate the extension
export function deactivate(): void {
console.log('stopping FooBar extension');
}
Interacting with the UI
The extension "hooks" into the Podman Desktop UI by various means, which include:
- Registering the extension as a specific provider (authentication, registry, Kubernetes, containers, CLI tools, or others).
- Registering to specific events (with functions starting with
onDid...). - Adding entries to menus (tray menu, status bar, and other types of menus).
- Adding fields to the configuration panel.
- Watching files in the filesystem.
When the extension code is accessed through these different registrations, the extension can use utility functions provided by the API to:
- Get values of configuration fields.
- Interact with the user through input boxes and quick picks.
- Display information, warnings, error messages, and notifications to the user.
- Get information about the environment (OS, telemetry, system clipboard).
- Execute the process in the system.
- Send data to the telemetry.
- Set data in the context, which is propagated in the UI.
Creating and running your extension
You can create and run an extension by performing the following end-to-end tasks:
- Initializing an extension
- Writing the extension's features
- Build dependencies
- Running the extension
- Verifying the extension's features
Expanding your extension
Below is documentation and/or "boiler-plate" code that can help expand your extension.