
# Extensions API

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.

:read-more{to="/guide/extensions"}

## 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:

```ts
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](/api/reference) is the full list of what's here, what
isn't, and why.

## A minimal extension

```ts
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:

```ts
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

::card-group{cols="2"}
::card
---

title: Anatomy of an extension
icon: i-lucide-puzzle
to: /api/extension
---

The manifest's contribution points, activation, and the extension context.
::
::card
---

title: Commands and menus
icon: i-lucide-square-menu
to: /api/commands
---

Registering commands, every place codelet draws a menu, and `when` clauses.
::
::card
---

title: Views
icon: i-lucide-layout-panel-left
to: /api/views
---

Tree views, webview views, component views, decorations and welcomes.
::
::card
---

title: Editors, tabs and webviews
icon: i-lucide-file-code
to: /api/editors
---

Custom editors, webview panels, and reading the tab strip.
::
::card
---

title: Language features
icon: i-lucide-languages
to: /api/languages
---

Diagnostics, definitions, hovers, completion and the rest of `languages`.
::
::card
---

title: Workspace, files and storage
icon: i-lucide-folder-tree
to: /api/workspace
---

`workspace.fs`, edits, configuration, and where an extension can remember things.
::
::card
---

title: Prompts, notifications and UI
icon: i-lucide-message-square
to: /api/ui
---

Quick picks, input boxes, progress, and the status bar.
::
::card
---

title: Tasks, source control and terminals
icon: i-lucide-workflow
to: /api/integrations
---

`vscode.tasks`, `vscode.scm`, and bringing a shell into the terminal.
::
::card
---

title: Full member reference
icon: i-lucide-library
to: /api/reference
---

Every member of `vscode` and `codelet`, and what's deliberately left out.
::
::
