| name | backend-api |
| description | Guides backend development with @podman-desktop/api and the bootc extension's RPC system. Covers container engine operations, provider management, RPC communication, build orchestration, VM management, and configuration. Triggers when working on packages/backend/ code, adding RPC methods to BootcAPI, implementing container/image operations, or asking about backend patterns. |
| paths | ["packages/backend/src/**/*.ts","packages/shared/src/**/*.ts"] |
Backend API Development Guide
Extension API: @podman-desktop/api
The backend runs as a Podman Desktop extension in Node.js. All host interactions
go through @podman-desktop/api, which is provided by the Podman Desktop runtime
(not bundled — it's an external dependency).
import * as extensionApi from '@podman-desktop/api';
Check API
API signatures change across versions. Read the installed types directly:
- Full API types: Read
node_modules/@podman-desktop/api/index.d.ts
- Current RPC contract: Read
packages/shared/src/BootcAPI.ts
- Current models: Read files in
packages/shared/src/models/
- Current messages: Read
packages/shared/src/messages/Messages.ts
- See existing usage:
grep -r "extensionApi\." packages/backend/src/
Always verify method signatures against the actual type definitions before using them.
RPC Architecture
Frontend ↔ Backend communication uses a typed RPC proxy over webview postMessage.
Adding a New API Method
Step 1: Define in shared contract (packages/shared/src/BootcAPI.ts):
export abstract class BootcApi {
abstract myNewMethod(param: string): Promise<ResultType>;
}
Step 2: Implement in backend (packages/backend/src/api-impl.ts):
export class BootcApiImpl extends BootcApi {
async myNewMethod(param: string): Promise<ResultType> {
const result = await extensionApi.containerEngine.listImages();
return transformResult(result);
}
}
Step 3: Call from frontend (automatic — RPC proxy exposes all methods):
import { bootcClient } from '/@/api/client';
const result = await bootcClient.myNewMethod('value');
RPC Timeout
Default timeout is 5 seconds per RPC call. For long-running operations, add
the method name to the no-timeout list:
cat packages/shared/src/messages/NoTimeoutChannels.ts
Sending Notifications (Backend → Frontend)
Push data to the frontend via message IDs. See the current messages:
cat packages/shared/src/messages/Messages.ts
Send from backend:
this.panel.webview.postMessage({ id: Messages.MSG_HISTORY_UPDATE, body: data });
Frontend subscribes via RPC:
import { rpcBrowser } from '/@/api/client';
rpcBrowser.subscribe(Messages.MSG_NAVIGATE_BUILD, (path: string) => {
router.goto(`/disk-images/build/${path}`);
});
Discovering APIs
APIs change across versions. Always read the source rather than relying on memory.
@podman-desktop/api
cat node_modules/@podman-desktop/api/index.d.ts
grep -rn "extensionApi\.\(containerEngine\|window\|provider\|navigation\|configuration\|process\|env\)" packages/backend/src/
Internal helpers
ls packages/backend/src/*.ts
ls packages/shared/src/models/
Checklist: Adding a New Backend Feature
- Add abstract method to
packages/shared/src/BootcAPI.ts
- Implement in
packages/backend/src/api-impl.ts
- If long-running (>5s), add to
NoTimeoutChannels.ts
- If it pushes data to frontend, add a message to
Messages.ts
- Add types/models in
packages/shared/src/models/ if needed
- Add telemetry for usage and errors
- Write unit tests mocking
@podman-desktop/api
- Frontend can call via
bootcClient.myNewMethod() — no wiring needed