| name | plugin-authoring |
| description | Bootstrap and iterate TypeScript/TSX JupyterLab plugins in Plugin Playground for plugin development, using command-driven workflows and extension references. |
| metadata | {"keywords":["jupyterlab","plugin-playground","plugin-authoring","plugin development","extension","typescript","tsx","token","command","share-link","clipboard"]} |
Plugin Authoring Skill (Playground)
Use this skill to bootstrap and iterate JupyterLab plugins inside Plugin Playground.
Goal
Produce working plugin code that can be loaded with plugin-playground:load-as-extension, using extension points and examples available in the running environment.
Inputs
- Desired behavior (what the plugin should do)
- Optional UI target (command palette, sidebar, status bar, notebook, etc.)
- Optional package constraints (JupyterLab-only APIs vs external AMD modules)
Workflow
- Prepare a TypeScript file
- If the user does not already have a plugin file open or specified, run
plugin-playground:create-new-plugin with a meaningful path argument (for example app.commands.execute('plugin-playground:create-new-plugin', { path: 'status-indicator.ts' })) instead of relying on untitled defaults.
- Start from the generated TypeScript scaffold and adapt it.
- Plugin Playground supports schema-backed settings during prototyping (
package.json with jupyterlab.schemaDir, with plugin.json fallback for single-plugin cases).
- For any plugin with multiple files, settings schema, CSS, SVG, or other local assets, create a package root up front (for example
my-extension/src/index.ts) and include a minimal package.json in my-extension/ so Share Package and extension export operate on the full folder.
- When creating nested files through AI file commands, create the parent directories first and verify the files appear in the file browser before continuing.
- Focus on TypeScript/TSX plugin code. Do not scaffold Python projects (
pyproject.toml, Python package layout) unless explicitly requested.
Minimal package metadata for Playground prototypes:
{
"name": "my-extension",
"version": "0.1.0",
"jupyterlab": {
"extension": true,
"schemaDir": "schema"
}
}
- Discover available extension points
- Run
plugin-playground:list-tokens to get available tokens.
- Run
plugin-playground:list-commands to get available commands.
- Use optional
query argument to narrow results:
app.commands.execute('plugin-playground:list-tokens', { query: 'status' })
app.commands.execute('plugin-playground:list-commands', { query: 'notebook' })
- Discover reference examples
- Run
plugin-playground:list-extension-examples.
- Filter by topic with
query (for example toolbar, commands, widget, notebook).
- Open selected example source/README from the sidebar for implementation details.
- Implement plugin code
- Start from a minimal plugin shape (
id, autoStart, activate).
- Add
requires tokens only after confirming availability from step 2.
- Add commands with stable, unique IDs (
<namespace>:<action>).
- Do not overwrite or reuse built-in JupyterLab command IDs. Plugin Playground skips duplicate command registrations; register a separate command and add it to the relevant palette, menu, toolbar, launcher, or cell toolbar instead.
- Use one or more
.ts/.tsx files as needed as complexity grows.
- Load and iterate
- Run
plugin-playground:load-as-extension.
- Validate behavior in UI.
- Check the command return value for
ok/status/message to detect and report loading or autostart errors.
- If reloading the same plugin ID repeatedly, ensure cleanup is handled via
deactivate() where needed.
- Export for standalone development
- Run
plugin-playground:export-as-extension to download a zip for local IDE + git workflows.
- For deterministic automation (or when another file is focused), pass an explicit file path:
app.commands.execute('plugin-playground:export-as-extension', { path: 'my-extension/src/index.ts' })
- Read export result metadata (
ok, archiveName, rootPath, fileCount, message) and report failures.
- Share a file link for collaboration
- Run
plugin-playground:share-via-link to create a shareable URL for a single file.
- It can target the active file or an explicit path:
app.commands.execute('plugin-playground:share-via-link', { path: 'my-extension/src/index.ts' })
- The command keeps the same flow: it copies the generated link to clipboard and also returns metadata (
ok, link, sourcePath, urlLength, message).
- Imports and module safety
- Prefer JupyterLab/Lumino imports first.
- For external packages, ensure AMD-compatible import targets are used.
- Avoid Node/Webpack-only modules that are not AMD-compatible.
Output expectations
- TypeScript-first plugin implementation (
.ts/.tsx)
- Clear command IDs and labels
- Minimal required tokens
- No unused imports
References
- JupyterLab Extension Tutorial:
- JupyterLab Extension Examples: