Extensions API
What activate gets handed, what the vscode namespace covers, and where the rest of this section lives
An extension adds to a workbench: a view, a command, a language feature, a filesystem. The guide
covers passing extensions to a Workbench; this section is about writing the extensions
themselves.
#A namespace, not a module
codelet hands your activate function an object shaped like VS Code's own vscode namespace —
a strict subset of it. If you've written a VS Code extension, window.createStatusBarItem(),
workspace.onDidChangeTextDocument, TreeDataProvider all read exactly the same here.
There's no import * as vscode from "vscode" to write, because there's no module named vscode
to resolve. It's an argument:
function activate(context, vscode, codelet) {
vscode.window.createStatusBarItem();
}For the members codelet implements, the portability runs one way: a TreeDataProvider or a
WebviewViewProvider written for codelet is also valid VS Code extension code. The reverse
isn't true — plenty of the real namespace isn't here at all.
#codelet, the third argument
VS Code's extension host is a separate process talking to a workbench UI it never touches
directly; codelet's runs in the same page as the workbench, so a handful of calls — filling a
pane with a real component instead of a frame, reading a view's filter box, opening a second
workspace over the reader's own — have no VS Code equivalent to sit on. Those live on codelet
instead, so every codelet-specific call is visible at its call site rather than hidden inside a
member the real namespace also has.
#What's missing
Some of VS Code is absent outright: debug, notebooks, authentication, comments, tests,
lm, chat, l10n. There's no multi-root workspace support — a workbench holds one tree — and
no file dialogs, since a browser tab has no filesystem of its own to open one onto.
Plenty more is narrowed rather than missing entirely — read-only carets, one editor group, a single settings layer. Full reference is the full list of what's here, what isn't, and why.
#A minimal extension
import { defineExtension } from "codelet/extensions";
export const wordCount = defineExtension({
manifest: {
name: "word-count",
contributes: {
commands: [{ command: "wordCount.show", title: "Show Word Count" }],
},
},
activate(context, vscode) {
const item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
const update = () => {
const text = vscode.window.activeTextEditor?.document.getText().trim() ?? "";
item.text = `${text ? text.split(/\s+/).length : 0} words`;
};
update();
item.show();
context.subscriptions.push(
item,
vscode.window.onDidChangeActiveTextEditor(update),
vscode.workspace.onDidChangeTextDocument(update),
vscode.commands.registerCommand("wordCount.show", () =>
vscode.window.showQuickPick([{ label: item.text }]),
),
);
},
});Pass it to a workbench like any built-in:
import { Workbench } from "codelet/workbench";
new Workbench({
parent: document.getElementById("app")!,
extensions: [wordCount],
});That's the whole shape: a manifest describing what the extension contributes, and an
activate function that wires it up once the workbench mounts.
#Where to go next
Anatomy of an extension
The manifest's contribution points, activation, and the extension context.
Commands and menus
Registering commands, every place codelet draws a menu, and when clauses.
Views
Tree views, webview views, component views, decorations and welcomes.
Editors, tabs and webviews
Custom editors, webview panels, and reading the tab strip.
Language features
Diagnostics, definitions, hovers, completion and the rest of languages.
Workspace, files and storage
workspace.fs, edits, configuration, and where an extension can remember things.
Prompts, notifications and UI
Quick picks, input boxes, progress, and the status bar.
Tasks, source control and terminals
vscode.tasks, vscode.scm, and bringing a shell into the terminal.
Full member reference
Every member of vscode and codelet, and what's deliberately left out.