This complete example adds a Workspace info panel and Open workspace info command. It calls buildPlugin() directly, without the CLI or generator. The generator is the easier starting point for most projects; this version shows the underlying pieces.
Prepare the project
Section titled “Prepare the project”Source is available in examples/workspace-info. Use Node.js 22.14+ and pnpm 11.25.0. Versions are SDK 1.1.0-alpha.1, React/React DOM 19.2.8 and TypeScript 7.0.2. The build helper depends on tsup 8.5.1.
git clone https://github.com/lomi-dev/docs-app.gitcd docs-app/examples/workspace-infoBefore npm publication, prepare a local SDK archive using Tools and diagnostics, then provide its actual path. If plugin-archives is next to docs-app:
pnpm add --save-exact --ignore-scripts @lomi-dev/plugin-sdk@file:../../../plugin-archives/lomi-dev-plugin-sdk-1.1.0-alpha.1.tgzpnpm checkpnpm buildThis saves a file: dependency and updates the example lockfile, without using application sources. Once the matching package set is published, replace the archive with exact version @lomi-dev/[email protected], review the lockfile and retain it. Use pnpm install --frozen-lockfile --ignore-scripts after establishing that environment.
buildPlugin() does not type-check. The example’s build script therefore runs pnpm check first. Check the exit status: failed builds preserve the previous package/.
Install and open the panel
Section titled “Install and open the panel”- Start the desktop application and open a project folder.
- In Settings > Plugins > Import plugin, select
docs-app/examples/workspace-info/package. - Enable Workspace info, then select Trust and enable.
- Open Commands with
Ctrl+Shift+P, orCmd+Shift+Pon macOS, and run Open workspace info. - Toggle Show project path. Switch workspaces and return to confirm that the panel keeps this choice.
Import the generated package folder. The parent folder contains source code, dependencies and build tools that do not belong in an installed plugin.
Files in the example
Section titled “Files in the example”package.json
Section titled “package.json”This defines author dependencies and type checking. These are exact npm versions; for the local candidate, replace the SDK with an archive as shown above.
{ "name": "lomi-workspace-info-example", "version": "1.0.0", "private": true, "type": "module", "scripts": { "check": "tsc --noEmit", "build": "pnpm check && node build.mjs" }, "dependencies": { "@lomi-dev/plugin-sdk": "1.1.0-alpha.1", "react": "19.2.8", "react-dom": "19.2.8" }, "devDependencies": { "@types/react": "19.2.18", "@types/react-dom": "19.2.7", "tsup": "8.5.1", "typescript": "7.0.2" }}plugin.json
Section titled “plugin.json”{ "schemaVersion": 1, "hostApi": 1, "id": "example.workspace-info", "name": "Workspace info", "version": "1.0.0", "description": "Show the active project folder and workspace.", "entry": "dist/index.js", "activation": "lazy", "stylesheets": ["workspace-info.css"], "contributes": { "views": [ { "id": "example.workspace-info.panel", "title": "Workspace info", "placement": "central", "multiple": false, "stateVersion": 1 } ], "commands": [ { "id": "example.workspace-info.open", "label": "Open workspace info", "description": "Show the active project folder and workspace.", "context": { "workspace": true } } ] }}src/index.tsx
Section titled “src/index.tsx”import { useHostContext, type PluginContext, type ViewProps,} from '@lomi-dev/plugin-sdk';
function WorkspaceInfo({ panel, setState }: ViewProps) { const host = useHostContext(); const showPath = typeof panel.state === 'object' && panel.state !== null && !Array.isArray(panel.state) && panel.state.showPath === true;
return ( <section className="workspace-info"> <h2>{host.workspaceName ?? 'No workspace selected'}</h2> <label> <input type="checkbox" checked={showPath} onChange={(event) => setState({ showPath: event.target.checked })} /> Show project path </label> {showPath && <p>{host.projectPath ?? 'No project selected'}</p>} <p>Appearance: {host.appearance}</p> </section> );}
export function activate(context: PluginContext) { context.registerView('example.workspace-info.panel', WorkspaceInfo); context.registerCommand('example.workspace-info.open', async () => { await context.openView('example.workspace-info.panel', { showPath: true }); });}build.mjs
Section titled “build.mjs”import { buildPlugin } from '@lomi-dev/plugin-sdk/build';
await buildPlugin({ assets: ['workspace-info.css'] });tsconfig.json
Section titled “tsconfig.json”{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "bundler", "jsx": "react-jsx", "strict": true, "skipLibCheck": true, "rootDir": "src" }, "include": ["src"]}workspace-info.css
Section titled “workspace-info.css”.workspace-info { padding: 16px; color: var(--color-surface-text); background: var(--plugin-example-dworkspace-hinfo-surface, var(--color-surface)); overflow-wrap: anywhere;}
.workspace-info label { display: flex; align-items: center; gap: 8px;}What the host handles
Section titled “What the host handles”useHostContext() updates the panel when the active workspace or appearance changes. setState() writes a small JSON value into the saved panel descriptor. This example has no unsaved document, so it does not need a dirty-view guard.
The host releases the view and command registrations when the plugin is deactivated. If you later add event listeners, timers or retained data stores, follow the lifecycle rules.
Change and rebuild
Section titled “Change and rebuild”Change the authoring files and run pnpm build again. Disable the installed plugin, import the new package folder and approve the replacement. Restart when prompted. Installed packages are snapshots, so editing the authoring directory does not update a running plugin.
All buildPlugin options
Section titled “All buildPlugin options”| Option | Default | Meaning |
|---|---|---|
entry |
src/index.tsx |
Source file to compile; unused when the manifest has no entry |
manifest |
plugin.json |
Manifest inside the author project |
assets |
[] |
Files and directories copied into the package |
outDir |
package |
Output directory; use a separate directory dedicated to builds |
cwd |
process.cwd() |
Author project directory |
signal |
None | Optional AbortSignal for cancellation |
The function returns Promise<string> with the absolute output path. The calling script handles failures. Successful builds replace outDir, so do not keep manually authored files there.
plugin.json.entry determines the generated JavaScript filename and extension. For example, source src/main.tsx can produce dist/plugin.mjs. The helper emits browser ES2022 ESM, shares React/SDK and validates final imports. See Styles and assets for resource rules.
The helper itself creates neither a ZIP nor a release report. Share the complete package/ folder, or add the CLI and use its package command. Import and qualify the built folder in Lomi through the desktop qualification guide.
Source: SDK contract, build helper.