
# Using extensions

An extension is an object you pass to `extensions` on the workbench. Some are values you import
directly; some are functions you call to set options. Pass a few together:

```ts
import { Workbench } from "codelet/workbench";
import { search } from "codelet/extensions/search";
import { logs } from "codelet/extensions/logs";
import { media } from "codelet/extensions/media";

const workbench = new Workbench({
  parent: document.getElementById("app")!,
  extensions: [search, logs(), media],
});
```

`search` and `media` are extension objects. `logs()` is a function that returns one — that's how
an extension takes options.

::codelet-playground{mode="workbench" active="src/index.ts" height="380" extensions="search logs" view="search"}

```ts [src/index.ts]
export const greet = (name: string) => `hi ${name}`;
```

```md [README.md]
# Hello
```

::

## Everything is opt-in

A workbench passed no `extensions` has no Search icon, no panel, no language support — none of it
is built into the workbench itself. Each built-in lives at its own package entry
(`codelet/extensions/search`, `codelet/extensions/logs`, and so on), so a page that never imports
one never bundles it. What you add is the only cost past the workbench itself.

## Where extensions show up

- **Activity bar** — an icon down the side that opens a sidebar view.
- **Panel** — a tab along the foot of the editor, beside Problems. Logs and Terminal both add one.
- **Secondary side bar** — a pane beside the editor rather than instead of the tree. Chat uses
  this.
- **Editor tab bar** — a button at the right of the strip, over the file showing. The markdown
  preview button is one.
- **Context menus** — the explorer's, a tab's, a view's own rows, and the document itself.
- **Command palette** — every command an extension registered a handler for, under `Mod-K` or
  `Mod-Shift-P`.

How a manifest declares each of these, and what a command or a view can do once it's there:

:read-more{to="/api/commands"}
:read-more{to="/api/views"}

## Manifest and activation

Every extension has two halves. Its manifest — what it contributes to the activity bar, the
panel, the palette, the tab bar — is plain data, read without running any of the extension's
code. Its `activate` function is where the real work happens: workers start, sockets open,
packages get fetched from a CDN.

That split is what lets the server render the shell around an extension without running it: the
icon and the title come from the manifest, and `activate` only runs once the workbench mounts in
a browser.

::warning
`extensions` is markup. Pass the exact same array, in the same order, to both `renderWorkbench()`
on the server and `Workbench` on the client — or hydration has nothing to match and the shell
rebuilds instead of taking over.
::

```ts
import { renderWorkbench } from "codelet/workbench/server";
import { EXTENSIONS } from "./extensions.ts";

const html = renderWorkbench({ extensions: EXTENSIONS });
```

## Starting and stopping an extension

`codelet/extensions/extensions` draws a card for every extension the workbench was given, what
each one contributes, and a button that stops it and starts it again — without a reload.

```ts
import { extensions } from "codelet/extensions/extensions";
import { search } from "codelet/extensions/search";
import { logs } from "codelet/extensions/logs";

new Workbench({ parent, extensions: [extensions, search, logs()] });
```

::codelet-playground{mode="workbench" height="380" extensions="search logs extensions-view" view="extensions"}

```ts [src/index.ts]
export const greet = (name: string) => `hi ${name}`;
```

::

## Every built-in

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

title: Search
icon: i-lucide-search
to: /extensions/search
---

A sidebar view over the tree, and where a reference search lands too.
::
::card
---

title: Terminal
icon: i-lucide-square-terminal
to: /extensions/terminal
---

xterm in the panel, over a shell another extension provides.
::
::card
---

title: Source control
icon: i-lucide-git-branch
to: /extensions/scm
---

What has changed, in a pane of its own.
::
::card
---

title: Language servers
icon: i-lucide-braces
to: /extensions/lsp
---

TypeScript, CSS, HTML, JSON and Markdown, each its own entry.
::
::

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

## Writing your own

:read-more{to="/api"}
